NeoMutt  2020-09-25
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 "mutt/lib.h"
#include "dump.h"
#include "set.h"
#include "subset.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...
 
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 522 of file muttlib.c.

523 {
524  if (!buf)
525  return;
526 
527  char *p = buf, *q = buf;
528  size_t len;
529  enum UrlScheme scheme;
530  char tmp[PATH_MAX];
531 
532  scheme = url_check_scheme(buf);
533 
534  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
535  {
536  imap_pretty_mailbox(buf, buflen, C_Folder);
537  return;
538  }
539 
540  if (scheme == U_NOTMUCH)
541  return;
542 
543  /* if buf is an url, only collapse path component */
544  if (scheme != U_UNKNOWN)
545  {
546  p = strchr(buf, ':') + 1;
547  if (mutt_strn_equal(p, "//", 2))
548  q = strchr(p + 2, '/');
549  if (!q)
550  q = strchr(p, '\0');
551  p = q;
552  }
553 
554  /* cleanup path */
555  if (strstr(p, "//") || strstr(p, "/./"))
556  {
557  /* first attempt to collapse the pathname, this is more
558  * lightweight than realpath() and doesn't resolve links */
559  while (*p)
560  {
561  if ((p[0] == '/') && (p[1] == '/'))
562  {
563  *q++ = '/';
564  p += 2;
565  }
566  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
567  {
568  *q++ = '/';
569  p += 3;
570  }
571  else
572  *q++ = *p++;
573  }
574  *q = '\0';
575  }
576  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
577  realpath(p, tmp))
578  {
579  mutt_str_copy(p, tmp, buflen - (p - buf));
580  }
581 
582  if ((len = mutt_str_startswith(buf, C_Folder)) && (buf[len] == '/'))
583  {
584  *buf++ = '=';
585  memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
586  }
587  else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
588  {
589  *buf++ = '~';
590  memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
591  }
592 }
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
Url is notmuch://.
Definition: url.h:45
Url is imaps://.
Definition: url.h:39
Url wasn&#39;t recognised.
Definition: url.h:34
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:725
Url is imap://.
Definition: url.h:38
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:49
UrlScheme
All recognised Url types.
Definition: url.h:32
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
#define PATH_MAX
Definition: mutt.h:44
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
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 '\007':
57  len += mutt_buffer_addstr(buf, "\\g");
58  break;
59  case '\n':
60  len += mutt_buffer_addstr(buf, "\\n");
61  break;
62  case '\r':
63  len += mutt_buffer_addstr(buf, "\\r");
64  break;
65  case '\t':
66  len += mutt_buffer_addstr(buf, "\\t");
67  break;
68  default:
69  if ((*src == '\\') || (*src == '"'))
70  len += mutt_buffer_addch(buf, '\\');
71  len += mutt_buffer_addch(buf, src[0]);
72  }
73  }
74  return len;
75 }
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 83 of file dump.c.

84 {
85  if (!buf || !str)
86  return 0;
87 
88  int len = 0;
89 
90  len += mutt_buffer_addch(buf, '"');
91  len += escape_string(buf, str);
92  len += mutt_buffer_addch(buf, '"');
93 
94  return len;
95 }
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:

◆ 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 106 of file dump.c.

108 {
109  if (!he || !value || !fp)
110  return;
111 
112  const char *name = he->key.strkey;
113 
114  if ((flags & CS_DUMP_ONLY_CHANGED) &&
115  (!initial || mutt_str_equal(value->data, initial->data)))
116  {
117  return;
118  }
119 
120  if (he->type == DT_SYNONYM)
121  {
122  const struct ConfigDef *cdef = he->data;
123  const char *syn = (const char *) cdef->initial;
124  fprintf(fp, "# synonym: %s -> %s\n", name, syn);
125  return;
126  }
127 
128  if (flags & CS_DUMP_SHOW_DOCS)
129  {
130  const struct ConfigDef *cdef = he->data;
131  fprintf(fp, "# %s\n", cdef->docs);
132  }
133 
134  bool show_name = !(flags & CS_DUMP_HIDE_NAME);
135  bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
136 
137  if (show_name && show_value)
138  fprintf(fp, "set ");
139  if (show_name)
140  fprintf(fp, "%s", name);
141  if (show_name && show_value)
142  fprintf(fp, " = ");
143  if (show_value)
144  fprintf(fp, "%s", value->data);
145  if (show_name || show_value)
146  fprintf(fp, "\n");
147 
148  if (flags & CS_DUMP_SHOW_DEFAULTS)
149  {
150  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
151  if (cst)
152  fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
153  }
154 
155  if (flags & CS_DUMP_SHOW_DOCS)
156  fprintf(fp, "\n");
157 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
union HashKey key
Key representing the data.
Definition: hash.h:46
Type definition for a config item.
Definition: set.h:88
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
const char * docs
One-liner description.
Definition: set.h:80
intptr_t initial
Initial value.
Definition: set.h:66
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:61
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition: dump.h:41
char * data
Pointer to data.
Definition: buffer.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
void * data
User-supplied data.
Definition: hash.h:47
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
const char * name
Name of the type, e.g. "String".
Definition: set.h:91
const char * strkey
String key.
Definition: hash.h:36
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:237
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition: dump.h:39
+ 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 165 of file dump.c.

166 {
167  if (!cs)
168  return false;
169 
170  struct HashElem *he = NULL;
171 
172  struct HashElem **list = get_elem_list(cs);
173  if (!list)
174  return false; /* LCOV_EXCL_LINE */
175 
176  bool result = true;
177 
178  struct Buffer value = mutt_buffer_make(256);
179  struct Buffer initial = mutt_buffer_make(256);
180  struct Buffer tmp = mutt_buffer_make(256);
181 
182  for (size_t i = 0; list[i]; i++)
183  {
184  mutt_buffer_reset(&value);
185  mutt_buffer_reset(&initial);
186  he = list[i];
187  const int type = DTYPE(he->type);
188 
189  if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
190  continue;
191 
192  if ((he->type & DT_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
193  continue;
194 
195  // if ((type == DT_DISABLED) && !(flags & CS_DUMP_SHOW_DISABLED))
196  // continue;
197 
198  if (type != DT_SYNONYM)
199  {
200  /* If necessary, get the current value */
201  if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
202  (flags & CS_DUMP_SHOW_DEFAULTS))
203  {
204  int rc = cs_he_string_get(cs, he, &value);
205  if (CSR_RESULT(rc) != CSR_SUCCESS)
206  {
207  result = false; /* LCOV_EXCL_LINE */
208  break; /* LCOV_EXCL_LINE */
209  }
210 
211  const struct ConfigDef *cdef = he->data;
212  if ((type == DT_STRING) && IS_SENSITIVE(*cdef) &&
213  (flags & CS_DUMP_HIDE_SENSITIVE) && !mutt_buffer_is_empty(&value))
214  {
215  mutt_buffer_reset(&value);
216  mutt_buffer_addstr(&value, "***");
217  }
218 
219  if (((type == DT_PATH) || IS_MAILBOX(he)) && (value.data[0] == '/'))
220  mutt_pretty_mailbox(value.data, value.dsize);
221 
222  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
223  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
224  {
225  mutt_buffer_reset(&tmp);
226  pretty_var(value.data, &tmp);
227  mutt_buffer_strcpy(&value, tmp.data);
228  }
229  }
230 
231  /* If necessary, get the default value */
232  if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
233  {
234  int rc = cs_he_initial_get(cs, he, &initial);
235  if (CSR_RESULT(rc) != CSR_SUCCESS)
236  {
237  result = false; /* LCOV_EXCL_LINE */
238  break; /* LCOV_EXCL_LINE */
239  }
240 
241  if (((type == DT_PATH) || IS_MAILBOX(he)) && !(he->type & DT_MAILBOX))
242  mutt_pretty_mailbox(initial.data, initial.dsize);
243 
244  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
245  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
246  {
247  mutt_buffer_reset(&tmp);
248  pretty_var(initial.data, &tmp);
249  mutt_buffer_strcpy(&initial, tmp.data);
250  }
251  }
252  }
253 
254  dump_config_neo(cs, he, &value, &initial, flags, fp);
255  }
256 
257  FREE(&list);
258  mutt_buffer_dealloc(&value);
259  mutt_buffer_dealloc(&initial);
260  mutt_buffer_dealloc(&tmp);
261 
262  return result;
263 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
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 CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
#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:56
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:61
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:64
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#define CSR_RESULT(x)
Definition: set.h:52
#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 mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define DT_STRING
a string
Definition: types.h:41
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define IS_MAILBOX(x)
Definition: types.h:57
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:79
#define DT_MAILBOX
Don&#39;t perform path expansions.
Definition: types.h:48
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:499
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
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void * data
User-supplied data.
Definition: hash.h:47
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
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:106
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#define FREE(x)
Definition: memory.h:40
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:636
The item stored in a Hash Table.
Definition: hash.h:43
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: