NeoMutt  2020-09-25
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 
38 void mutt_pretty_mailbox(char *buf, size_t buflen);
39 
46 size_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 += 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 }
76 
83 size_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 += mutt_buffer_addch(buf, '"');
91  len += escape_string(buf, str);
92  len += mutt_buffer_addch(buf, '"');
93 
94  return len;
95 }
96 
106 void 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 
165 bool 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 **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 */
232  if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
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);
249  mutt_buffer_strcpy(&initial, tmp.data);
250  }
251  }
252  }
253 
254  dump_config_neo(cs, he, &value, &initial, flags, fp);
255  }
256 
257  FREE(&list);
258  mutt_buffer_dealloc(&value);
259  mutt_buffer_dealloc(&initial);
260  mutt_buffer_dealloc(&tmp);
261 
262  return result;
263 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
union HashKey key
Key representing the data.
Definition: hash.h:46
Type definition for a config item.
Definition: set.h:88
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
Container for lots of config items.
Definition: set.h:228
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
Constants for all the config types.
#define DT_LONG
a number (long)
Definition: types.h:33
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
const char * docs
One-liner description.
Definition: set.h:80
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition: dump.h:38
A collection of config items.
intptr_t initial
Initial value.
Definition: set.h:66
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define IS_SENSITIVE(x)
Definition: types.h:56
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:61
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:64
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#define CSR_RESULT(x)
Definition: set.h:52
#define CS_DUMP_SHOW_DEPRECATED
Show config items that aren&#39;t used any more.
Definition: dump.h:44
#define CS_DUMP_SHOW_DEFAULTS
Show the default value for the config item.
Definition: dump.h:41
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
const char * name
User-visible name.
Definition: set.h:63
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define DT_STRING
a string
Definition: types.h:41
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define IS_MAILBOX(x)
Definition: types.h:57
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:79
#define DT_MAILBOX
Don&#39;t perform path expansions.
Definition: types.h:48
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:499
char * data
Pointer to data.
Definition: buffer.h:35
#define CS_DUMP_SHOW_SYNONYMS
Show synonyms and the config items they&#39;re linked to.
Definition: dump.h:43
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
Subset of Config Items.
Dump all the config.
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_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void * data
User-supplied data.
Definition: hash.h:47
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
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
const char * name
Name of the type, e.g. "String".
Definition: set.h:91
const char * strkey
String key.
Definition: hash.h:36
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:32
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#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:636
The item stored in a Hash Table.
Definition: hash.h:43
Convenience wrapper for the library headers.
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:237
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
#define CS_DUMP_HIDE_NAME
Do not print the name of the config item.
Definition: dump.h:39
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30