NeoMutt  2019-12-07
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 <stdlib.h>
33 #include "mutt/mutt.h"
34 #include "dump.h"
35 #include "set.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 '\n':
57  len += mutt_buffer_addstr(buf, "\\n");
58  break;
59  case '\r':
60  len += mutt_buffer_addstr(buf, "\\r");
61  break;
62  case '\t':
63  len += mutt_buffer_addstr(buf, "\\t");
64  break;
65  default:
66  if ((*src == '\\') || (*src == '"'))
67  len += mutt_buffer_addch(buf, '\\');
68  len += mutt_buffer_addch(buf, src[0]);
69  }
70  }
71  return len;
72 }
73 
80 size_t pretty_var(const char *str, struct Buffer *buf)
81 {
82  if (!buf || !str)
83  return 0;
84 
85  int len = 0;
86 
87  len += mutt_buffer_addch(buf, '"');
88  len += escape_string(buf, str);
89  len += mutt_buffer_addch(buf, '"');
90 
91  return len;
92 }
93 
102 int elem_list_sort(const void *a, const void *b)
103 {
104  if (!a || !b)
105  return 0;
106 
107  const struct HashElem *hea = *(struct HashElem const *const *) a;
108  const struct HashElem *heb = *(struct HashElem const *const *) b;
109 
110  return mutt_str_strcasecmp(hea->key.strkey, heb->key.strkey);
111 }
112 
118 struct HashElem **get_elem_list(struct ConfigSet *cs)
119 {
120  if (!cs)
121  return NULL;
122 
123  struct HashElem **list = mutt_mem_calloc(1024, sizeof(struct HashElem *));
124  size_t index = 0;
125 
126  struct HashWalkState walk = { 0 };
127  struct HashElem *he = NULL;
128 
129  while ((he = mutt_hash_walk(cs->hash, &walk)))
130  {
131  list[index++] = he;
132  if (index == 1022)
133  break; /* LCOV_EXCL_LINE */
134  }
135 
136  qsort(list, index, sizeof(struct HashElem *), elem_list_sort);
137 
138  return list;
139 }
140 
150 void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
151  struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
152 {
153  if (!he || !value || !fp)
154  return;
155 
156  const char *name = he->key.strkey;
157 
158  if ((flags & CS_DUMP_ONLY_CHANGED) &&
159  (!initial || (mutt_str_strcmp(value->data, initial->data) == 0)))
160  return;
161 
162  if (he->type == DT_SYNONYM)
163  {
164  const struct ConfigDef *cdef = he->data;
165  const char *syn = (const char *) cdef->initial;
166  fprintf(fp, "# synonym: %s -> %s\n", name, syn);
167  return;
168  }
169 
170  bool show_name = !(flags & CS_DUMP_HIDE_NAME);
171  bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
172 
173  if (show_name && show_value)
174  fprintf(fp, "set ");
175  if (show_name)
176  fprintf(fp, "%s", name);
177  if (show_name && show_value)
178  fprintf(fp, " = ");
179  if (show_value)
180  fprintf(fp, "%s", value->data);
181  if (show_name || show_value)
182  fprintf(fp, "\n");
183 
184  if (flags & CS_DUMP_SHOW_DEFAULTS)
185  {
186  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
187  if (cst)
188  fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
189  }
190 }
191 
198 bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
199 {
200  if (!cs)
201  return false;
202 
203  struct HashElem *he = NULL;
204 
205  struct HashElem **list = get_elem_list(cs);
206  if (!list)
207  return false; /* LCOV_EXCL_LINE */
208 
209  bool result = true;
210 
211  struct Buffer value = mutt_buffer_make(256);
212  struct Buffer initial = mutt_buffer_make(256);
213  struct Buffer tmp = mutt_buffer_make(256);
214 
215  for (size_t i = 0; list[i]; i++)
216  {
217  mutt_buffer_reset(&value);
218  mutt_buffer_reset(&initial);
219  he = list[i];
220  const int type = DTYPE(he->type);
221 
222  if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
223  continue;
224 
225  if ((he->type & DT_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
226  continue;
227 
228  // if ((type == DT_DISABLED) && !(flags & CS_DUMP_SHOW_DISABLED))
229  // continue;
230 
231  if (type != DT_SYNONYM)
232  {
233  /* If necessary, get the current value */
234  if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
235  (flags & CS_DUMP_SHOW_DEFAULTS))
236  {
237  int rc = cs_he_string_get(cs, he, &value);
238  if (CSR_RESULT(rc) != CSR_SUCCESS)
239  {
240  result = false; /* LCOV_EXCL_LINE */
241  break; /* LCOV_EXCL_LINE */
242  }
243 
244  const struct ConfigDef *cdef = he->data;
245  if ((type == DT_STRING) && IS_SENSITIVE(*cdef) &&
246  (flags & CS_DUMP_HIDE_SENSITIVE) && !mutt_buffer_is_empty(&value))
247  {
248  mutt_buffer_reset(&value);
249  mutt_buffer_addstr(&value, "***");
250  }
251 
252  if (IS_PATH(he) && (value.data[0] == '/'))
253  mutt_pretty_mailbox(value.data, value.dsize);
254 
255  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
256  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
257  {
258  mutt_buffer_reset(&tmp);
259  pretty_var(value.data, &tmp);
260  mutt_buffer_strcpy(&value, tmp.data);
261  }
262  }
263 
264  /* If necessary, get the default value */
265  if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
266  {
267  int rc = cs_he_initial_get(cs, he, &initial);
268  if (CSR_RESULT(rc) != CSR_SUCCESS)
269  {
270  result = false; /* LCOV_EXCL_LINE */
271  break; /* LCOV_EXCL_LINE */
272  }
273 
274  if (IS_PATH(he) && !(he->type & DT_MAILBOX))
275  mutt_pretty_mailbox(initial.data, initial.dsize);
276 
277  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
278  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
279  {
280  mutt_buffer_reset(&tmp);
281  pretty_var(initial.data, &tmp);
282  mutt_buffer_strcpy(&initial, tmp.data);
283  }
284  }
285  }
286 
287  dump_config_neo(cs, he, &value, &initial, flags, fp);
288  }
289 
290  FREE(&list);
291  mutt_buffer_dealloc(&value);
292  mutt_buffer_dealloc(&initial);
293  mutt_buffer_dealloc(&tmp);
294 
295  return result;
296 }
union HashKey key
Definition: hash.h:45
Type definition for a config item.
Definition: set.h:168
Container for lots of config items.
Definition: set.h:187
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Hash * hash
HashTable storing the config items.
Definition: set.h:189
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 IS_PATH(x)
Definition: types.h:55
#define CSR_RESULT(x)
Definition: set.h:62
#define CS_DUMP_ONLY_CHANGED
Only show config that the user has changed.
Definition: dump.h:36
#define CS_DUMP_NO_ESCAPING
Do not escape special chars, or quote the string.
Definition: dump.h:38
intptr_t initial
Initial value.
Definition: set.h:158
Cursor to iterate through a Hash Table.
Definition: hash.h:96
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:54
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: dump.c:118
#define CS_DUMP_HIDE_VALUE
Do not print the value of the config item.
Definition: dump.h:40
Config item definition.
Definition: set.h:153
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:43
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#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 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:150
const char * name
Definition: pgpmicalg.c:46
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:46
#define DT_STRING
a string
Definition: types.h:40
A collection of config items.
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:77
#define DT_MAILBOX
Don&#39;t perform path expansions.
Definition: types.h:47
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
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:628
Dump all the config.
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:513
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
int elem_list_sort(const void *a, const void *b)
Sort two HashElem pointers to config.
Definition: dump.c:102
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:198
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
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:650
void * data
Definition: hash.h:46
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:80
struct HashElem * mutt_hash_walk(const struct Hash *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash table.
Definition: hash.c:503
#define DT_SYNONYM
synonym for another variable
Definition: types.h:41
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:239
const char * name
Name of the type, e.g. "String".
Definition: set.h:170
const char * strkey
Definition: hash.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:32
int type
Definition: hash.h:44
#define FREE(x)
Definition: memory.h:40
size_t escape_string(struct Buffer *buf, const char *src)
Write a string to a buffer, escaping special characters.
Definition: dump.c:46
The item stored in a Hash Table.
Definition: hash.h:42
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
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615