NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
dump.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdio.h>
32#include "mutt/lib.h"
33#include "dump.h"
34#include "set.h"
35#include "subset.h"
36#include "types.h"
37
38void mutt_pretty_mailbox(char *buf, size_t buflen);
39
46size_t escape_string(struct Buffer *buf, const char *src)
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 += buf_addstr(buf, "\\g");
58 break;
59 case '\n':
60 len += buf_addstr(buf, "\\n");
61 break;
62 case '\r':
63 len += buf_addstr(buf, "\\r");
64 break;
65 case '\t':
66 len += buf_addstr(buf, "\\t");
67 break;
68 default:
69 if ((*src == '\\') || (*src == '"'))
70 len += buf_addch(buf, '\\');
71 len += buf_addch(buf, src[0]);
72 }
73 }
74 return len;
75}
76
83size_t pretty_var(const char *str, struct Buffer *buf)
84{
85 if (!buf || !str)
86 return 0;
87
88 int len = 0;
89
90 len += buf_addch(buf, '"');
91 len += escape_string(buf, str);
92 len += buf_addch(buf, '"');
93
94 return len;
95}
96
106void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
107 struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
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}
158
165bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
166{
167 if (!cs)
168 return false;
169
170 struct HashElem *he = NULL;
171
172 struct HashElem **he_list = get_elem_list(cs);
173 if (!he_list)
174 return false; /* LCOV_EXCL_LINE */
175
176 bool result = true;
177
178 struct Buffer value = buf_make(256);
179 struct Buffer initial = buf_make(256);
180 struct Buffer tmp = buf_make(256);
181
182 for (size_t i = 0; he_list[i]; i++)
183 {
184 buf_reset(&value);
185 buf_reset(&initial);
186 he = 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->type) &&
213 (flags & CS_DUMP_HIDE_SENSITIVE) && !buf_is_empty(&value))
214 {
215 buf_reset(&value);
216 buf_addstr(&value, "***");
217 }
218
219 if (((type == DT_PATH) || IS_MAILBOX(he->type)) && (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 buf_reset(&tmp);
226 pretty_var(value.data, &tmp);
227 buf_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->type)) && !(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 buf_reset(&tmp);
248 pretty_var(initial.data, &tmp);
249 buf_strcpy(&initial, tmp.data);
250 }
251 }
252 }
253
254 dump_config_neo(cs, he, &value, &initial, flags, fp);
255 }
256
257 FREE(&he_list);
258 buf_dealloc(&value);
260 buf_dealloc(&tmp);
261
262 return result;
263}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:383
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:401
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:195
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:662
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:528
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
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:481
Dump all the config.
#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_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
#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
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:34
#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
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
Parse the 'set' command.
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
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
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
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:252
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
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:76
Subset of Config Items.
Constants for all the config types.
#define IS_SENSITIVE(type)
Definition: types.h:59
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:45
#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 IS_MAILBOX(type)
Definition: types.h:60
#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:51
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_STRING
a string
Definition: types.h:41
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
#define DT_DISABLED
Config item is disabled.
Definition: types.h:80
#define DT_NUMBER
a number
Definition: types.h:35
const char * strkey
String key.
Definition: hash.h:36