NeoMutt  2021-10-22-8-g9cb437
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 526 of file muttlib.c.

527 {
528  if (!buf)
529  return;
530 
531  char *p = buf, *q = buf;
532  size_t len;
533  enum UrlScheme scheme;
534  char tmp[PATH_MAX];
535 
536  scheme = url_check_scheme(buf);
537 
538  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
539  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
540  {
541  imap_pretty_mailbox(buf, buflen, c_folder);
542  return;
543  }
544 
545  if (scheme == U_NOTMUCH)
546  return;
547 
548  /* if buf is an url, only collapse path component */
549  if (scheme != U_UNKNOWN)
550  {
551  p = strchr(buf, ':') + 1;
552  if (mutt_strn_equal(p, "//", 2))
553  q = strchr(p + 2, '/');
554  if (!q)
555  q = strchr(p, '\0');
556  p = q;
557  }
558 
559  /* cleanup path */
560  if (strstr(p, "//") || strstr(p, "/./"))
561  {
562  /* first attempt to collapse the pathname, this is more
563  * lightweight than realpath() and doesn't resolve links */
564  while (*p)
565  {
566  if ((p[0] == '/') && (p[1] == '/'))
567  {
568  *q++ = '/';
569  p += 2;
570  }
571  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
572  {
573  *q++ = '/';
574  p += 3;
575  }
576  else
577  *q++ = *p++;
578  }
579  *q = '\0';
580  }
581  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
582  realpath(p, tmp))
583  {
584  mutt_str_copy(p, tmp, buflen - (p - buf));
585  }
586 
587  if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
588  {
589  *buf++ = '=';
590  memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
591  }
592  else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
593  {
594  *buf++ = '~';
595  memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
596  }
597 }
char * HomeDir
User's home directory.
Definition: mutt_globals.h:51
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:590
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
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:749
#define PATH_MAX
Definition: mutt.h:40
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
UrlScheme
All recognised Url types.
Definition: url.h:34
@ U_NOTMUCH
Url is notmuch://.
Definition: url.h:46
@ U_UNKNOWN
Url wasn't recognised.
Definition: url.h:35
@ U_FILE
Url is file://.
Definition: url.h:36
@ U_IMAP
Url is imap://.
Definition: url.h:39
@ U_IMAPS
Url is imaps://.
Definition: url.h:40
+ Here is the call graph for this function:
+ 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_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
+ 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 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 }
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition: dump.h:39
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition: dump.h:41
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:227
char * data
Pointer to data.
Definition: buffer.h:35
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
intptr_t initial
Initial value.
Definition: set.h:67
const char * docs
One-liner description.
Definition: set.h:84
const char * name
Name of the type, e.g. "String".
Definition: set.h:98
union HashKey key
Key representing the data.
Definition: hash.h:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
void * data
User-supplied data.
Definition: hash.h:47
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
const char * strkey
String key.
Definition: hash.h:36
+ 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 */
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);
250  }
251  }
252  }
253 
254  dump_config_neo(cs, he, &value, &initial, flags, fp);
255  }
256 
257  FREE(&list);
258  mutt_buffer_dealloc(&value);
260  mutt_buffer_dealloc(&tmp);
261 
262  return result;
263 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
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
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:526
#define CS_DUMP_SHOW_SYNONYMS
Show synonyms and the config items they're linked to.
Definition: dump.h:43
#define CS_DUMP_SHOW_DEPRECATED
Show config items that aren't used any more.
Definition: dump.h:44
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition: dump.h:38
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#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:618
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:484
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
The item stored in a Hash Table.
Definition: hash.h:44
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:75
#define IS_SENSITIVE(x)
Definition: types.h:56
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
#define IS_MAILBOX(x)
Definition: types.h:57
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
#define DT_LONG
a number (long)
Definition: types.h:33
#define DT_BOOL
boolean option
Definition: types.h:30
#define DT_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:77
#define DT_MAILBOX
Don't perform path expansions.
Definition: types.h:48
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_STRING
a string
Definition: types.h:41
#define DT_NUMBER
a number
Definition: types.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function: