NeoMutt  2022-04-29-247-gc6aae8
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] = { 0 };
531
532 scheme = url_check_scheme(buf);
533
534 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
535 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
536 {
537 imap_pretty_mailbox(buf, buflen, c_folder);
538 return;
539 }
540
541 if (scheme == U_NOTMUCH)
542 return;
543
544 /* if buf is an url, only collapse path component */
545 if (scheme != U_UNKNOWN)
546 {
547 p = strchr(buf, ':') + 1;
548 if (mutt_strn_equal(p, "//", 2))
549 q = strchr(p + 2, '/');
550 if (!q)
551 q = strchr(p, '\0');
552 p = q;
553 }
554
555 /* cleanup path */
556 if (strstr(p, "//") || strstr(p, "/./"))
557 {
558 /* first attempt to collapse the pathname, this is more
559 * lightweight than realpath() and doesn't resolve links */
560 while (*p)
561 {
562 if ((p[0] == '/') && (p[1] == '/'))
563 {
564 *q++ = '/';
565 p += 2;
566 }
567 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
568 {
569 *q++ = '/';
570 p += 3;
571 }
572 else
573 *q++ = *p++;
574 }
575 *q = '\0';
576 }
577 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
578 realpath(p, tmp))
579 {
580 mutt_str_copy(p, tmp, buflen - (p - buf));
581 }
582
583 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
584 {
585 *buf++ = '=';
586 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
587 }
588 else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
589 {
590 *buf++ = '~';
591 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
592 }
593}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:589
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:496
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
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:652
#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:248
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
+ 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:807
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 ((he->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))
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);
261
262 return result;
263}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
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:522
#define CS_DUMP_SHOW_SYNONYMS
Show synonyms and the config items they're linked to.
Definition: dump.h:43
#define CS_DUMP_SHOW_DISABLED
Show disabled config items, too.
Definition: dump.h:42
#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:43
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_DISABLED
Config item is disabled.
Definition: types.h:80
#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: