NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
dump.c File Reference

Dump all the config. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "mutt/mutt.h"
#include "dump.h"
#include "set.h"
#include "types.h"
+ Include dependency graph for dump.c:

Go to the source code of this file.

Functions

void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='. More...
 
size_t escape_string (struct Buffer *buf, const char *src)
 Write a string to a buffer, escaping special characters. More...
 
size_t pretty_var (const char *str, struct Buffer *buf)
 Escape and stringify a config item value. More...
 
int elem_list_sort (const void *a, const void *b)
 Sort two HashElem pointers to config. More...
 
struct HashElem ** get_elem_list (struct ConfigSet *cs)
 Create a sorted list of all config items. More...
 
void dump_config_neo (struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
 Dump the config in the style of NeoMutt. More...
 
bool dump_config (struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
 Write all the config to a file. More...
 

Detailed Description

Dump all the config.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file dump.c.

Function Documentation

◆ mutt_pretty_mailbox()

void mutt_pretty_mailbox ( char *  buf,
size_t  buflen 
)

Shorten a mailbox path using '~' or '='.

Parameters
bufBuffer containing string to shorten
buflenLength of buffer

Collapse the pathname using ~ or = when possible

Definition at line 612 of file muttlib.c.

613 {
614  if (!buf)
615  return;
616 
617  char *p = buf, *q = buf;
618  size_t len;
619  enum UrlScheme scheme;
620  char tmp[PATH_MAX];
621 
622  scheme = url_check_scheme(buf);
623 
624  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
625  {
626  imap_pretty_mailbox(buf, buflen, C_Folder);
627  return;
628  }
629 
630  if (scheme == U_NOTMUCH)
631  return;
632 
633  /* if buf is an url, only collapse path component */
634  if (scheme != U_UNKNOWN)
635  {
636  p = strchr(buf, ':') + 1;
637  if (strncmp(p, "//", 2) == 0)
638  q = strchr(p + 2, '/');
639  if (!q)
640  q = strchr(p, '\0');
641  p = q;
642  }
643 
644  /* cleanup path */
645  if (strstr(p, "//") || strstr(p, "/./"))
646  {
647  /* first attempt to collapse the pathname, this is more
648  * lightweight than realpath() and doesn't resolve links */
649  while (*p)
650  {
651  if ((p[0] == '/') && (p[1] == '/'))
652  {
653  *q++ = '/';
654  p += 2;
655  }
656  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
657  {
658  *q++ = '/';
659  p += 3;
660  }
661  else
662  *q++ = *p++;
663  }
664  *q = '\0';
665  }
666  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
667  realpath(p, tmp))
668  {
669  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
670  }
671 
672  if ((len = mutt_str_startswith(buf, C_Folder, CASE_MATCH)) && (buf[len] == '/'))
673  {
674  *buf++ = '=';
675  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
676  }
677  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && (buf[len] == '/'))
678  {
679  *buf++ = '~';
680  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
681  }
682 }
Url is notmuch://.
Definition: url.h:45
Url is imaps://.
Definition: url.h:39
Url wasn&#39;t recognised.
Definition: url.h:34
Url is imap://.
Definition: url.h:38
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
enum UrlScheme url_check_scheme(const char *s)
Check the protocol of a URL.
Definition: url.c:132
UrlScheme
All recognised Url types.
Definition: url.h:32
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:124
#define PATH_MAX
Definition: mutt.h:52
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:688
Url is file://.
Definition: url.h:35
+ Here is the caller graph for this function:

◆ escape_string()

size_t escape_string ( struct Buffer buf,
const char *  src 
)

Write a string to a buffer, escaping special characters.

Parameters
bufBuffer to write to
srcString to write
Return values
numBytes written to buffer

Definition at line 46 of file dump.c.

47 {
48  if (!buf || !src)
49  return 0;
50 
51  size_t len = 0;
52  for (; *src; src++)
53  {
54  switch (*src)
55  {
56  case '\n':
57  len += mutt_buffer_addstr(buf, "\\n");
58  break;
59  case '\r':
60  len += mutt_buffer_addstr(buf, "\\r");
61  break;
62  case '\t':
63  len += mutt_buffer_addstr(buf, "\\t");
64  break;
65  default:
66  if ((*src == '\\') || (*src == '"'))
67  len += mutt_buffer_addch(buf, '\\');
68  len += mutt_buffer_addch(buf, src[0]);
69  }
70  }
71  return len;
72 }
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pretty_var()

size_t pretty_var ( const char *  str,
struct Buffer buf 
)

Escape and stringify a config item value.

Parameters
strString to escape
bufBuffer to write to
Return values
numNumber of bytes written to buffer

Definition at line 80 of file dump.c.

81 {
82  if (!buf || !str)
83  return 0;
84 
85  int len = 0;
86 
87  len += mutt_buffer_addch(buf, '"');
88  len += escape_string(buf, str);
89  len += mutt_buffer_addch(buf, '"');
90 
91  return len;
92 }
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ elem_list_sort()

int elem_list_sort ( const void *  a,
const void *  b 
)

Sort two HashElem pointers to config.

Parameters
aFirst HashElem
bSecond HashElem
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 102 of file dump.c.

103 {
104  if (!a || !b)
105  return 0;
106 
107  const struct HashElem *hea = *(struct HashElem const *const *) a;
108  const struct HashElem *heb = *(struct HashElem const *const *) b;
109 
110  return mutt_str_strcasecmp(hea->key.strkey, heb->key.strkey);
111 }
union HashKey key
Definition: hash.h:45
const char * strkey
Definition: hash.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
The item stored in a Hash Table.
Definition: hash.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_elem_list()

struct HashElem** get_elem_list ( struct ConfigSet cs)

Create a sorted list of all config items.

Parameters
csConfigSet to read
Return values
ptrNull-terminated array of HashElem

Definition at line 118 of file dump.c.

119 {
120  if (!cs)
121  return NULL;
122 
123  struct HashElem **list = mutt_mem_calloc(1024, sizeof(struct HashElem *));
124  size_t index = 0;
125 
126  struct HashWalkState walk = { 0 };
127  struct HashElem *he = NULL;
128 
129  while ((he = mutt_hash_walk(cs->hash, &walk)))
130  {
131  list[index++] = he;
132  if (index == 1022)
133  break; /* LCOV_EXCL_LINE */
134  }
135 
136  qsort(list, index, sizeof(struct HashElem *), elem_list_sort);
137 
138  return list;
139 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Hash * hash
HashTable storing the config items.
Definition: set.h:189
Cursor to iterate through a Hash Table.
Definition: hash.h:96
int elem_list_sort(const void *a, const void *b)
Sort two HashElem pointers to config.
Definition: dump.c:102
struct HashElem * mutt_hash_walk(const struct Hash *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash table.
Definition: hash.c:504
The item stored in a Hash Table.
Definition: hash.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_config_neo()

void dump_config_neo ( struct ConfigSet cs,
struct HashElem he,
struct Buffer value,
struct Buffer initial,
ConfigDumpFlags  flags,
FILE *  fp 
)

Dump the config in the style of NeoMutt.

Parameters
csConfig items
heHashElem representing config item
valueCurrent value of the config item
initialInitial value of the config item
flagsFlags, see ConfigDumpFlags
fpFile pointer to write to

Definition at line 150 of file dump.c.

152 {
153  if (!he || !value || !fp)
154  return;
155 
156  const char *name = he->key.strkey;
157 
158  if ((flags & CS_DUMP_ONLY_CHANGED) &&
159  (!initial || (mutt_str_strcmp(value->data, initial->data) == 0)))
160  return;
161 
162  if (he->type == DT_SYNONYM)
163  {
164  const struct ConfigDef *cdef = he->data;
165  const char *syn = (const char *) cdef->initial;
166  fprintf(fp, "# synonym: %s -> %s\n", name, syn);
167  return;
168  }
169 
170  bool show_name = !(flags & CS_DUMP_HIDE_NAME);
171  bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
172 
173  if (show_name && show_value)
174  fprintf(fp, "set ");
175  if (show_name)
176  fprintf(fp, "%s", name);
177  if (show_name && show_value)
178  fprintf(fp, " = ");
179  if (show_value)
180  fprintf(fp, "%s", value->data);
181  if (show_name || show_value)
182  fprintf(fp, "\n");
183 
184  if (flags & CS_DUMP_SHOW_DEFAULTS)
185  {
186  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
187  if (cst)
188  fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
189  }
190 }
union HashKey key
Definition: hash.h:45
Type definition for a config item.
Definition: set.h:168
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
intptr_t initial
Initial value.
Definition: set.h:158
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:153
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition: dump.h:41
const char * name
Definition: pgpmicalg.c:45
char * data
Pointer to data.
Definition: buffer.h:35
void * data
Definition: hash.h:46
#define DT_SYNONYM
synonym for another variable
Definition: types.h:41
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:239
const char * name
Name of the type, e.g.
Definition: set.h:170
const char * strkey
Definition: hash.h:35
int type
Definition: hash.h:44
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition: dump.h:39
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_config()

bool dump_config ( struct ConfigSet cs,
ConfigDumpFlags  flags,
FILE *  fp 
)

Write all the config to a file.

Parameters
csConfigSet to dump
flagsFlags, see ConfigDumpFlags
fpFile to write config to

Definition at line 198 of file dump.c.

199 {
200  if (!cs)
201  return false;
202 
203  struct HashElem *he = NULL;
204 
205  struct HashElem **list = get_elem_list(cs);
206  if (!list)
207  return false; /* LCOV_EXCL_LINE */
208 
209  bool result = true;
210 
211  struct Buffer value = mutt_buffer_make(256);
212  struct Buffer initial = mutt_buffer_make(256);
213  struct Buffer tmp = mutt_buffer_make(256);
214 
215  for (size_t i = 0; list[i]; i++)
216  {
217  mutt_buffer_reset(&value);
218  mutt_buffer_reset(&initial);
219  he = list[i];
220  const int type = DTYPE(he->type);
221 
222  if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
223  continue;
224 
225  if ((he->type & DT_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
226  continue;
227 
228  // if ((type == DT_DISABLED) && !(flags & CS_DUMP_SHOW_DISABLED))
229  // continue;
230 
231  if (type != DT_SYNONYM)
232  {
233  /* If necessary, get the current value */
234  if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
235  (flags & CS_DUMP_SHOW_DEFAULTS))
236  {
237  int rc = cs_he_string_get(cs, he, &value);
238  if (CSR_RESULT(rc) != CSR_SUCCESS)
239  {
240  result = false; /* LCOV_EXCL_LINE */
241  break; /* LCOV_EXCL_LINE */
242  }
243 
244  const struct ConfigDef *cdef = he->data;
245  if ((type == DT_STRING) && IS_SENSITIVE(*cdef) &&
246  (flags & CS_DUMP_HIDE_SENSITIVE) && !mutt_buffer_is_empty(&value))
247  {
248  mutt_buffer_reset(&value);
249  mutt_buffer_addstr(&value, "***");
250  }
251 
252  if (IS_PATH(he) && (value.data[0] == '/'))
253  mutt_pretty_mailbox(value.data, value.dsize);
254 
255  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
256  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
257  {
258  mutt_buffer_reset(&tmp);
259  pretty_var(value.data, &tmp);
260  mutt_buffer_strcpy(&value, tmp.data);
261  }
262  }
263 
264  /* If necessary, get the default value */
265  if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
266  {
267  int rc = cs_he_initial_get(cs, he, &initial);
268  if (CSR_RESULT(rc) != CSR_SUCCESS)
269  {
270  result = false; /* LCOV_EXCL_LINE */
271  break; /* LCOV_EXCL_LINE */
272  }
273 
274  if (IS_PATH(he) && !(he->type & DT_MAILBOX))
275  mutt_pretty_mailbox(initial.data, initial.dsize);
276 
277  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
278  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
279  {
280  mutt_buffer_reset(&tmp);
281  pretty_var(initial.data, &tmp);
282  mutt_buffer_strcpy(&initial, tmp.data);
283  }
284  }
285  }
286 
287  dump_config_neo(cs, he, &value, &initial, flags, fp);
288  }
289 
290  FREE(&list);
291  mutt_buffer_dealloc(&value);
292  mutt_buffer_dealloc(&initial);
293  mutt_buffer_dealloc(&tmp);
294 
295  return result;
296 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define DT_LONG
a number (long)
Definition: types.h:33
#define IS_PATH(x)
Definition: types.h:55
#define CSR_RESULT(x)
Definition: set.h:62
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition: dump.h:38
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define IS_SENSITIVE(x)
Definition: types.h:54
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: dump.c:118
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:153
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:43
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#define CS_DUMP_SHOW_DEPRECATED
Show config items that aren&#39;t used any more.
Definition: dump.h:44
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition: dump.h:41
size_t dsize
Length of data.
Definition: buffer.h:37
void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
Dump the config in the style of NeoMutt.
Definition: dump.c:150
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:293
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:46
#define DT_STRING
a string
Definition: types.h:40
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:77
#define DT_MAILBOX
Don&#39;t perform path expansions.
Definition: types.h:47
char * data
Pointer to data.
Definition: buffer.h:35
#define CS_DUMP_SHOW_SYNONYMS
Show synonyms and the config items they&#39;re linked to.
Definition: dump.h:43
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:612
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition: set.c:513
int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: set.c:650
void * data
Definition: hash.h:46
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:80
#define DT_SYNONYM
synonym for another variable
Definition: types.h:41
int type
Definition: hash.h:44
#define FREE(x)
Definition: memory.h:40
The item stored in a Hash Table.
Definition: hash.h:42
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30
+ Here is the call graph for this function:
+ Here is the caller graph for this function: