NeoMutt  2025-09-05-43-g177ed6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
dump.c File Reference

Dump all the config. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.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 '='.
 
size_t escape_string (struct Buffer *buf, const char *src)
 Write a string to a buffer, escaping special characters.
 
size_t pretty_var (const char *str, struct Buffer *buf)
 Escape and stringify a config item value.
 
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.
 
bool dump_config (struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
 Write all the config to a file.
 

Detailed Description

Dump all the config.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Dennis Schön

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 439 of file muttlib.c.

440{
441 if (!buf)
442 return;
443
444 char *p = buf, *q = buf;
445 size_t len;
446 enum UrlScheme scheme;
447 char tmp[PATH_MAX] = { 0 };
448
449 scheme = url_check_scheme(buf);
450
451 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
452 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
453 {
454 imap_pretty_mailbox(buf, buflen, c_folder);
455 return;
456 }
457
458 if (scheme == U_NOTMUCH)
459 return;
460
461 /* if buf is an url, only collapse path component */
462 if (scheme != U_UNKNOWN)
463 {
464 p = strchr(buf, ':') + 1;
465 if (mutt_strn_equal(p, "//", 2))
466 q = strchr(p + 2, '/');
467 if (!q)
468 q = strchr(p, '\0');
469 p = q;
470 }
471
472 /* cleanup path */
473 if (strstr(p, "//") || strstr(p, "/./"))
474 {
475 /* first attempt to collapse the pathname, this is more
476 * lightweight than realpath() and doesn't resolve links */
477 while (*p)
478 {
479 if ((p[0] == '/') && (p[1] == '/'))
480 {
481 *q++ = '/';
482 p += 2;
483 }
484 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
485 {
486 *q++ = '/';
487 p += 3;
488 }
489 else
490 {
491 *q++ = *p++;
492 }
493 }
494 *q = '\0';
495 }
496 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
497 realpath(p, tmp))
498 {
499 mutt_str_copy(p, tmp, buflen - (p - buf));
500 }
501
502 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
503 {
504 *buf++ = '=';
505 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
506 }
507 else if ((len = mutt_str_startswith(buf, NeoMutt->home_dir)) && (buf[len] == '/'))
508 {
509 *buf++ = '~';
510 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
511 }
512}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition util.c:583
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:427
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:232
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:498
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:581
#define PATH_MAX
Definition mutt.h:42
Container for Accounts, Notifications.
Definition neomutt.h:43
char * home_dir
User's home directory.
Definition neomutt.h:53
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition url.c:225
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 48 of file dump.c.

49{
50 if (!buf || !src)
51 return 0;
52
53 size_t len = 0;
54 for (; *src; src++)
55 {
56 switch (*src)
57 {
58 case '\007':
59 len += buf_addstr(buf, "\\g");
60 break;
61 case '\n':
62 len += buf_addstr(buf, "\\n");
63 break;
64 case '\r':
65 len += buf_addstr(buf, "\\r");
66 break;
67 case '\t':
68 len += buf_addstr(buf, "\\t");
69 break;
70 default:
71 if ((*src == '\\') || (*src == '"'))
72 len += buf_addch(buf, '\\');
73 len += buf_addch(buf, src[0]);
74 }
75 }
76 return len;
77}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
+ 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 85 of file dump.c.

86{
87 if (!buf || !str)
88 return 0;
89
90 int len = 0;
91
92 len += buf_addch(buf, '"');
93 len += escape_string(buf, str);
94 len += buf_addch(buf, '"');
95
96 return len;
97}
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition dump.c:48
+ 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 108 of file dump.c.

110{
111 if (!he || !value || !fp)
112 return;
113
114 const char *name = he->key.strkey;
115
116 if ((flags & CS_DUMP_ONLY_CHANGED) &&
117 (!initial || mutt_str_equal(value->data, initial->data)))
118 {
119 return;
120 }
121
122 if (he->type == DT_SYNONYM)
123 {
124 const struct ConfigDef *cdef = he->data;
125 const char *syn = (const char *) cdef->initial;
126 fprintf(fp, "# synonym: %s -> %s\n", name, syn);
127 return;
128 }
129
130 if (flags & CS_DUMP_SHOW_DOCS)
131 {
132 const struct ConfigDef *cdef = he->data;
133 fprintf(fp, "# %s\n", cdef->docs);
134 }
135
136 bool show_name = !(flags & CS_DUMP_HIDE_NAME);
137 bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
138
139 if (show_name && show_value)
140 fprintf(fp, "set ");
141 if (show_name)
142 {
143 if (flags & CS_DUMP_LINK_DOCS)
144 {
145 // Used to generate unique ids for the urls
146 static int seq_num = 1;
147
148 if (CONFIG_TYPE(he->type) == DT_MYVAR)
149 {
150 static const char *url = "https://neomutt.org/guide/configuration#set-myvar";
151 fprintf(fp, "\033]8;id=%d;%s\a%s\033]8;;\a", seq_num++, url, name);
152 }
153 else
154 {
155 char *fragment = mutt_str_dup(name);
156 for (char *underscore = fragment; (underscore = strchr(underscore, '_')); underscore++)
157 {
158 *underscore = '-';
159 }
160
161 static const char *url = "https://neomutt.org/guide/reference";
162 fprintf(fp, "\033]8;id=%d;%s#%s\a%s\033]8;;\a", seq_num++, url, fragment, name);
163 FREE(&fragment);
164 }
165 }
166 else
167 {
168 fprintf(fp, "%s", name);
169 }
170 }
171 if (show_name && show_value)
172 fprintf(fp, " = ");
173 if (show_value)
174 fprintf(fp, "%s", value->data);
175 if (show_name || show_value)
176 fprintf(fp, "\n");
177
178 if (flags & CS_DUMP_SHOW_DEFAULTS)
179 {
180 const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
181 if (cst)
182 fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
183 }
184
185 if (flags & CS_DUMP_SHOW_DOCS)
186 fprintf(fp, "\n");
187}
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition dump.h:41
#define CS_DUMP_LINK_DOCS
Link to the online docs.
Definition dump.h:47
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition dump.h:37
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition dump.h:40
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition dump.h:42
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition dump.h:46
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition set.c:198
#define FREE(x)
Definition memory.h:62
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
char * data
Pointer to data.
Definition buffer.h:37
const char * name
User-visible name.
Definition set.h:63
intptr_t initial
Initial value.
Definition set.h:65
const char * docs
One-liner description.
Definition set.h:81
const char * name
Name of the type, e.g. "String".
Definition set.h:95
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 CONFIG_TYPE(t)
Definition types.h:49
@ DT_SYNONYM
synonym for another variable
Definition types.h:45
@ DT_MYVAR
a user-defined variable (my_foo)
Definition types.h:37
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,
struct HashElemArray * hea,
ConfigDumpFlags flags,
FILE * fp )

Write all the config to a file.

Parameters
csConfigSet to dump
heaArray of Config HashElem to dump
flagsFlags, see ConfigDumpFlags
fpFile to write config to

Definition at line 196 of file dump.c.

198{
199 if (!cs || !hea || !fp)
200 return false;
201
202 bool result = true;
203
204 struct Buffer *value = buf_pool_get();
205 struct Buffer *initial = buf_pool_get();
206 struct Buffer *tmp = buf_pool_get();
207
208 struct HashElem **hep = NULL;
209 ARRAY_FOREACH(hep, hea)
210 {
211 struct HashElem *he = *hep;
212 buf_reset(value);
213 buf_reset(initial);
214 const int type = CONFIG_TYPE(he->type);
215
216 /* If necessary, get the current value */
217 if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
218 (flags & CS_DUMP_SHOW_DEFAULTS))
219 {
220 int rc = cs_he_string_get(cs, he, value);
221 if (CSR_RESULT(rc) != CSR_SUCCESS)
222 {
223 result = false; /* LCOV_EXCL_LINE */
224 break; /* LCOV_EXCL_LINE */
225 }
226
227 const struct ConfigDef *cdef = he->data;
228 if ((type == DT_STRING) && (cdef->type & D_SENSITIVE) &&
229 (flags & CS_DUMP_HIDE_SENSITIVE) && !buf_is_empty(value))
230 {
231 buf_reset(value);
232 buf_addstr(value, "***");
233 }
234
235 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(value, 0) == '/'))
236 mutt_pretty_mailbox(value->data, value->dsize);
237
238 // Quote/escape the values of config options NOT of these types
239 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
240 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
241 !(flags & CS_DUMP_NO_ESCAPING))
242 {
243 buf_reset(tmp);
244 pretty_var(value->data, tmp);
245 buf_strcpy(value, tmp->data);
246 }
247 }
248
249 /* If necessary, get the default value */
251 {
252 int rc = cs_he_initial_get(cs, he, initial);
253 if (CSR_RESULT(rc) != CSR_SUCCESS)
254 {
255 result = false; /* LCOV_EXCL_LINE */
256 break; /* LCOV_EXCL_LINE */
257 }
258
259 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(initial, 0) == '/'))
260 mutt_pretty_mailbox(initial->data, initial->dsize);
261
262 // Quote/escape the values of config options NOT of these types
263 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
264 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
265 !(flags & CS_DUMP_NO_ESCAPING))
266 {
267 buf_reset(tmp);
268 pretty_var(initial->data, tmp);
269 buf_strcpy(initial, tmp->data);
270 }
271 }
272
273 dump_config_neo(cs, he, value, initial, flags, fp);
274 }
275
276 buf_pool_release(&value);
278 buf_pool_release(&tmp);
279
280 return result;
281}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition dump.c:85
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:108
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:439
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition dump.h:39
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition dump.h:38
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:691
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:557
#define CSR_RESULT(x)
Definition set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
uint32_t type
Variable type, e.g. DT_STRING.
Definition set.h:64
The item stored in a Hash Table.
Definition hash.h:44
#define IS_MAILBOX(flags)
Definition types.h:121
@ DT_NUMBER
a number
Definition types.h:38
@ DT_BOOL
boolean option
Definition types.h:32
@ DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition types.h:40
@ DT_STRING
a string
Definition types.h:44
@ DT_SORT
sorting methods
Definition types.h:43
@ DT_LONG
a number (long)
Definition types.h:35
@ DT_ENUM
an enumeration
Definition types.h:33
@ DT_PATH
a path to a file/directory
Definition types.h:39
#define D_SENSITIVE
Contains sensitive value, e.g. password.
Definition types.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function: