NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
dump.c
Go to the documentation of this file.
1
24
30
31#include "config.h"
32#include <stdbool.h>
33#include <stdio.h>
34#include <string.h>
35#include "mutt/lib.h"
36#include "dump.h"
37#include "muttlib.h"
38#include "set.h"
39#include "types.h"
40
47size_t escape_string(struct Buffer *buf, const char *src)
48{
49 if (!buf || !src)
50 return 0;
51
52 size_t len = 0;
53 for (; *src; src++)
54 {
55 switch (*src)
56 {
57 case '\007':
58 len += buf_addstr(buf, "\\g");
59 break;
60 case '\n':
61 len += buf_addstr(buf, "\\n");
62 break;
63 case '\r':
64 len += buf_addstr(buf, "\\r");
65 break;
66 case '\t':
67 len += buf_addstr(buf, "\\t");
68 break;
69 case '`':
70 len += buf_addstr(buf, "\\`");
71 break;
72 default:
73 if ((*src == '\\') || (*src == '"'))
74 len += buf_addch(buf, '\\');
75 len += buf_addch(buf, src[0]);
76 }
77 }
78 return len;
79}
80
87size_t pretty_var(const char *str, struct Buffer *buf)
88{
89 if (!buf || !str)
90 return 0;
91
92 int len = 0;
93
94 len += buf_addch(buf, '"');
95 len += escape_string(buf, str);
96 len += buf_addch(buf, '"');
97
98 return len;
99}
100
110void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
111 struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
112{
113 if (!he || !value || !fp)
114 return;
115
116 const char *name = he->key.strkey;
117
118 if ((flags & CS_DUMP_ONLY_CHANGED) &&
119 (!initial || mutt_str_equal(value->data, initial->data)))
120 {
121 return;
122 }
123
124 if (he->type == DT_SYNONYM)
125 {
126 const struct ConfigDef *cdef = he->data;
127 const char *syn = (const char *) cdef->initial;
128 fprintf(fp, "# synonym: %s -> %s\n", name, syn);
129 return;
130 }
131
132 if (flags & CS_DUMP_SHOW_DOCS)
133 {
134 const struct ConfigDef *cdef = he->data;
135 fprintf(fp, "# %s\n", cdef->docs);
136 }
137
138 bool show_name = !(flags & CS_DUMP_HIDE_NAME);
139 bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
140
141 if (show_name && show_value)
142 fprintf(fp, "set ");
143 if (show_name)
144 {
145 if (flags & CS_DUMP_LINK_DOCS)
146 {
147 // Used to generate unique ids for the urls
148 static int seq_num = 1;
149
150 if (CONFIG_TYPE(he->type) == DT_MYVAR)
151 {
152 static const char *url = "https://neomutt.org/guide/configuration#set-myvar";
153 fprintf(fp, "\033]8;id=%d;%s\a%s\033]8;;\a", seq_num++, url, name);
154 }
155 else
156 {
157 char *fragment = mutt_str_dup(name);
158 for (char *underscore = fragment; (underscore = strchr(underscore, '_')); underscore++)
159 {
160 *underscore = '-';
161 }
162
163 static const char *url = "https://neomutt.org/guide/reference";
164 fprintf(fp, "\033]8;id=%d;%s#%s\a%s\033]8;;\a", seq_num++, url, fragment, name);
165 FREE(&fragment);
166 }
167 }
168 else
169 {
170 fprintf(fp, "%s", name);
171 }
172 }
173 if (show_name && show_value)
174 fprintf(fp, " = ");
175 if (show_value)
176 fprintf(fp, "%s", value->data);
177 if (show_name || show_value)
178 fprintf(fp, "\n");
179
180 if (flags & CS_DUMP_SHOW_DEFAULTS)
181 {
182 const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
183 if (cst)
184 fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
185 }
186
187 if (flags & CS_DUMP_SHOW_DOCS)
188 fprintf(fp, "\n");
189}
190
198bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea,
199 ConfigDumpFlags flags, FILE *fp)
200{
201 if (!cs || !hea || !fp)
202 return false;
203
204 bool result = true;
205
206 struct Buffer *value = buf_pool_get();
207 struct Buffer *initial = buf_pool_get();
208 struct Buffer *tmp = buf_pool_get();
209
210 struct HashElem **hep = NULL;
211 ARRAY_FOREACH(hep, hea)
212 {
213 struct HashElem *he = *hep;
214 buf_reset(value);
215 buf_reset(initial);
216 const int type = CONFIG_TYPE(he->type);
217
218 /* If necessary, get the current value */
219 if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
220 (flags & CS_DUMP_SHOW_DEFAULTS))
221 {
222 int rc = cs_he_string_get(cs, he, value);
223 if (CSR_RESULT(rc) != CSR_SUCCESS)
224 {
225 result = false; /* LCOV_EXCL_LINE */
226 break; /* LCOV_EXCL_LINE */
227 }
228
229 const struct ConfigDef *cdef = he->data;
230 if ((type == DT_STRING) && (cdef->type & D_SENSITIVE) &&
231 (flags & CS_DUMP_HIDE_SENSITIVE) && !buf_is_empty(value))
232 {
233 buf_reset(value);
234 buf_addstr(value, "***");
235 }
236
237 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(value, 0) == '/'))
238 pretty_mailbox(value);
239
240 // Quote/escape the values of config options NOT of these types
241 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
242 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
243 !(flags & CS_DUMP_NO_ESCAPING))
244 {
245 buf_reset(tmp);
246 pretty_var(value->data, tmp);
247 buf_strcpy(value, tmp->data);
248 }
249 }
250
251 /* If necessary, get the default value */
253 {
254 int rc = cs_he_initial_get(cs, he, initial);
255 if (CSR_RESULT(rc) != CSR_SUCCESS)
256 {
257 result = false; /* LCOV_EXCL_LINE */
258 break; /* LCOV_EXCL_LINE */
259 }
260
261 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (buf_at(initial, 0) == '/'))
263
264 // Quote/escape the values of config options NOT of these types
265 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
266 (type != DT_QUAD) && (type != DT_ENUM) && (type != DT_SORT) &&
267 !(flags & CS_DUMP_NO_ESCAPING))
268 {
269 buf_reset(tmp);
270 pretty_var(initial->data, tmp);
271 buf_strcpy(initial, tmp->data);
272 }
273 }
274
275 dump_config_neo(cs, he, value, initial, flags, fp);
276 }
277
278 buf_pool_release(&value);
280 buf_pool_release(&tmp);
281
282 return result;
283}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
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_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
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition dump.c:47
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition dump.c:87
bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition dump.c:198
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:110
Dump all the config.
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition dump.h:41
#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
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition dump.h:35
#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:199
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:692
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:558
A collection of config items.
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
Some miscellaneous functions.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
const char * name
User-visible name.
Definition set.h:66
intptr_t initial
Initial value.
Definition set.h:68
uint32_t type
Variable type, e.g. DT_STRING.
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
Container for lots of config items.
Definition set.h:251
The item stored in a Hash Table.
Definition hash.h:44
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
Constants for all the config types.
#define CONFIG_TYPE(t)
Extract the type from the flags.
Definition types.h:50
#define IS_MAILBOX(flags)
Definition types.h:122
@ 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_SYNONYM
synonym for another variable
Definition types.h:45
@ DT_STRING
a string
Definition types.h:44
@ DT_SORT
sorting methods
Definition types.h:43
@ DT_MYVAR
a user-defined variable (my_foo)
Definition types.h:37
@ 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:81
const char * strkey
String key.
Definition hash.h:36