NeoMutt  2020-06-26-89-g172cd3
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  return;
117 
118  if (he->type == DT_SYNONYM)
119  {
120  const struct ConfigDef *cdef = he->data;
121  const char *syn = (const char *) cdef->initial;
122  fprintf(fp, "# synonym: %s -> %s\n", name, syn);
123  return;
124  }
125 
126  bool show_name = !(flags & CS_DUMP_HIDE_NAME);
127  bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
128 
129  if (show_name && show_value)
130  fprintf(fp, "set ");
131  if (show_name)
132  fprintf(fp, "%s", name);
133  if (show_name && show_value)
134  fprintf(fp, " = ");
135  if (show_value)
136  fprintf(fp, "%s", value->data);
137  if (show_name || show_value)
138  fprintf(fp, "\n");
139 
140  if (flags & CS_DUMP_SHOW_DEFAULTS)
141  {
142  const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
143  if (cst)
144  fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
145  }
146 }
147 
154 bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
155 {
156  if (!cs)
157  return false;
158 
159  struct HashElem *he = NULL;
160 
161  struct HashElem **list = get_elem_list(cs);
162  if (!list)
163  return false; /* LCOV_EXCL_LINE */
164 
165  bool result = true;
166 
167  struct Buffer value = mutt_buffer_make(256);
168  struct Buffer initial = mutt_buffer_make(256);
169  struct Buffer tmp = mutt_buffer_make(256);
170 
171  for (size_t i = 0; list[i]; i++)
172  {
173  mutt_buffer_reset(&value);
174  mutt_buffer_reset(&initial);
175  he = list[i];
176  const int type = DTYPE(he->type);
177 
178  if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
179  continue;
180 
181  if ((he->type & DT_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
182  continue;
183 
184  // if ((type == DT_DISABLED) && !(flags & CS_DUMP_SHOW_DISABLED))
185  // continue;
186 
187  if (type != DT_SYNONYM)
188  {
189  /* If necessary, get the current value */
190  if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
191  (flags & CS_DUMP_SHOW_DEFAULTS))
192  {
193  int rc = cs_he_string_get(cs, he, &value);
194  if (CSR_RESULT(rc) != CSR_SUCCESS)
195  {
196  result = false; /* LCOV_EXCL_LINE */
197  break; /* LCOV_EXCL_LINE */
198  }
199 
200  const struct ConfigDef *cdef = he->data;
201  if ((type == DT_STRING) && IS_SENSITIVE(*cdef) &&
202  (flags & CS_DUMP_HIDE_SENSITIVE) && !mutt_buffer_is_empty(&value))
203  {
204  mutt_buffer_reset(&value);
205  mutt_buffer_addstr(&value, "***");
206  }
207 
208  if (((type == DT_PATH) || IS_MAILBOX(he)) && (value.data[0] == '/'))
209  mutt_pretty_mailbox(value.data, value.dsize);
210 
211  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
212  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
213  {
214  mutt_buffer_reset(&tmp);
215  pretty_var(value.data, &tmp);
216  mutt_buffer_strcpy(&value, tmp.data);
217  }
218  }
219 
220  /* If necessary, get the default value */
221  if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
222  {
223  int rc = cs_he_initial_get(cs, he, &initial);
224  if (CSR_RESULT(rc) != CSR_SUCCESS)
225  {
226  result = false; /* LCOV_EXCL_LINE */
227  break; /* LCOV_EXCL_LINE */
228  }
229 
230  if (((type == DT_PATH) || IS_MAILBOX(he)) && !(he->type & DT_MAILBOX))
231  mutt_pretty_mailbox(initial.data, initial.dsize);
232 
233  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
234  (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
235  {
236  mutt_buffer_reset(&tmp);
237  pretty_var(initial.data, &tmp);
238  mutt_buffer_strcpy(&initial, tmp.data);
239  }
240  }
241  }
242 
243  dump_config_neo(cs, he, &value, &initial, flags, fp);
244  }
245 
246  FREE(&list);
247  mutt_buffer_dealloc(&value);
248  mutt_buffer_dealloc(&initial);
249  mutt_buffer_dealloc(&tmp);
250 
251  return result;
252 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
union HashKey key
Key representing the data.
Definition: hash.h:46
Type definition for a config item.
Definition: set.h:88
Container for lots of config items.
Definition: set.h:227
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 CSR_RESULT(x)
Definition: set.h:52
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:64
#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:68
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:63
#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
#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:106
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:65
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:35
#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
A collection of config items.
#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
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
Subset of Config Items.
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
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:486
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:154
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:620
void * data
User-supplied data.
Definition: hash.h:47
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
const struct ConfigSetType * cs_get_type_def(const struct ConfigSet *cs, unsigned int type)
Get the definition for a type.
Definition: set.c:229
const char * name
Name of the type, e.g. "String".
Definition: set.h:90
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
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#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:43
Convenience wrapper for the library headers.
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