NeoMutt  2022-04-29-323-g5fcc6c
Teaching an old dog new tricks
DOXYGEN
init.c File Reference

Config/command parsing. More...

#include "config.h"
#include <ctype.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "init.h"
#include "color/lib.h"
#include "history/lib.h"
#include "notmuch/lib.h"
#include "command_parse.h"
#include "hook.h"
#include "keymap.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "mutt_lua.h"
#include "menu/lib.h"
#include "muttlib.h"
#include "myvar.h"
#include "options.h"
#include "protos.h"
#include "sidebar/lib.h"
#include "compmbox/lib.h"
#include "imap/lib.h"
+ Include dependency graph for init.c:

Go to the source code of this file.

Functions

static int execute_commands (struct ListHead *p)
 Execute a set of NeoMutt commands. More...
 
static char * find_cfg (const char *home, const char *xdg_cfg_home)
 Find a config file. More...
 
static char * getmailname (void)
 Try to retrieve the FQDN from mailname files. More...
 
static bool get_hostname (struct ConfigSet *cs)
 Find the Fully-Qualified Domain Name. More...
 
int mutt_extract_token (struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
 Extract one token from a string. More...
 
void mutt_opts_free (void)
 Clean up before quitting. More...
 
int mutt_init (struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
 Initialise NeoMutt. More...
 
enum CommandResult mutt_parse_rc_buffer (struct Buffer *line, struct Buffer *token, struct Buffer *err)
 Parse a line of user config. More...
 
enum CommandResult mutt_parse_rc_line (const char *line, struct Buffer *err)
 Parse a line of user config. More...
 
int mutt_query_variables (struct ListHead *queries, bool show_docs)
 Implement the -Q command line flag. More...
 

Detailed Description

Config/command parsing.

Authors
  • Michael R. Elkins
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file init.c.

Function Documentation

◆ execute_commands()

static int execute_commands ( struct ListHead *  p)
static

Execute a set of NeoMutt commands.

Parameters
pList of command strings
Return values
0Success, all the commands succeeded
-1Error

Definition at line 81 of file init.c.

82{
83 int rc = 0;
84 struct Buffer *err = mutt_buffer_pool_get();
85
86 struct ListNode *np = NULL;
87 STAILQ_FOREACH(np, p, entries)
88 {
89 enum CommandResult rc2 = mutt_parse_rc_line(np->data, err);
90 if (rc2 == MUTT_CMD_ERROR)
91 mutt_error(_("Error in command line: %s"), mutt_buffer_string(err));
92 else if (rc2 == MUTT_CMD_WARNING)
93 mutt_warning(_("Warning in command line: %s"), mutt_buffer_string(err));
94
95 if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
96 {
98 return -1;
99 }
100 }
102
103 return rc;
104}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
CommandResult
Error codes for command_t parse functions.
Definition: command.h:34
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:35
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:36
#define mutt_warning(...)
Definition: logging.h:85
#define mutt_error(...)
Definition: logging.h:87
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:893
#define _(a)
Definition: message.h:28
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
String manipulation buffer.
Definition: buffer.h:34
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_cfg()

static char * find_cfg ( const char *  home,
const char *  xdg_cfg_home 
)
static

Find a config file.

Parameters
homeUser's home directory
xdg_cfg_homeXDG home directory
Return values
ptrSuccess, first matching directory
NULLError, no matching directories

Definition at line 113 of file init.c.

114{
115 const char *names[] = {
116 "neomuttrc",
117 "muttrc",
118 NULL,
119 };
120
121 const char *locations[][2] = {
122 { xdg_cfg_home, "neomutt/" },
123 { xdg_cfg_home, "mutt/" },
124 { home, ".neomutt/" },
125 { home, ".mutt/" },
126 { home, "." },
127 { NULL, NULL },
128 };
129
130 for (int i = 0; locations[i][0] || locations[i][1]; i++)
131 {
132 if (!locations[i][0])
133 continue;
134
135 for (int j = 0; names[j]; j++)
136 {
137 char buf[256] = { 0 };
138
139 snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
140 if (access(buf, F_OK) == 0)
141 return mutt_str_dup(buf);
142 }
143 }
144
145 return NULL;
146}
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getmailname()

static char * getmailname ( void  )
static

Try to retrieve the FQDN from mailname files.

Return values
ptrHeap allocated string with the FQDN
NULLNo valid mailname file could be read

Definition at line 154 of file init.c.

155{
156 char *mailname = NULL;
157 static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
158
159 for (size_t i = 0; i < mutt_array_size(mn_files); i++)
160 {
161 FILE *fp = mutt_file_fopen(mn_files[i], "r");
162 if (!fp)
163 continue;
164
165 size_t len = 0;
166 mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
167 mutt_file_fclose(&fp);
168 if (mailname && *mailname)
169 break;
170
171 FREE(&mailname);
172 }
173
174 return mailname;
175}
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:736
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:151
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
#define FREE(x)
Definition: memory.h:43
#define mutt_array_size(x)
Definition: memory.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_hostname()

static bool get_hostname ( struct ConfigSet cs)
static

Find the Fully-Qualified Domain Name.

Return values
trueSuccess
falseError, failed to find any name

Use several methods to try to find the Fully-Qualified domain name of this host. If the user has already configured a hostname, this function will use it.

Definition at line 186 of file init.c.

187{
188 const char *short_host = NULL;
189 struct utsname utsname = { 0 };
190
191 const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
192 if (c_hostname)
193 {
194 short_host = c_hostname;
195 }
196 else
197 {
198 /* The call to uname() shouldn't fail, but if it does, the system is horribly
199 * broken, and the system's networking configuration is in an unreliable
200 * state. We should bail. */
201 if ((uname(&utsname)) == -1)
202 {
203 mutt_perror(_("unable to determine nodename via uname()"));
204 return false; // TEST09: can't test
205 }
206
207 short_host = utsname.nodename;
208 }
209
210 /* some systems report the FQDN instead of just the hostname */
211 char *dot = strchr(short_host, '.');
212 if (dot)
213 ShortHostname = mutt_strn_dup(short_host, dot - short_host);
214 else
215 ShortHostname = mutt_str_dup(short_host);
216
217 // All the code paths from here alloc memory for the fqdn
218 char *fqdn = mutt_str_dup(c_hostname);
219 if (!fqdn)
220 {
221 mutt_debug(LL_DEBUG1, "Setting $hostname\n");
222 /* now get FQDN. Use configured domain first, DNS next, then uname */
223#ifdef DOMAIN
224 /* we have a compile-time domain name, use that for `$hostname` */
226 sprintf((char *) fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
227#else
228 fqdn = getmailname();
229 if (!fqdn)
230 {
231 struct Buffer *domain = mutt_buffer_pool_get();
232 if (getdnsdomainname(domain) == 0)
233 {
235 sprintf((char *) fqdn, "%s.%s", NONULL(ShortHostname), mutt_buffer_string(domain));
236 }
237 else
238 {
239 /* DNS failed, use the nodename. Whether or not the nodename had a '.'
240 * in it, we can use the nodename as the FQDN. On hosts where DNS is
241 * not being used, e.g. small network that relies on hosts files, a
242 * short host name is all that is required for SMTP to work correctly.
243 * It could be wrong, but we've done the best we can, at this point the
244 * onus is on the user to provide the correct hostname if the nodename
245 * won't work in their network. */
246 fqdn = mutt_str_dup(utsname.nodename);
247 }
249 mutt_debug(LL_DEBUG1, "Hostname: %s\n", NONULL(fqdn));
250 }
251#endif
252 }
253
254 if (fqdn)
255 {
256 cs_str_initial_set(cs, "hostname", fqdn, NULL);
257 cs_str_reset(cs, "hostname", NULL);
258 FREE(&fqdn);
259 }
260
261 return true;
262}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int getdnsdomainname(struct Buffer *result)
Lookup the host's name using DNS.
Definition: getdomain.c:122
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition: init.c:154
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:451
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:458
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:393
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_extract_token()

int mutt_extract_token ( struct Buffer dest,
struct Buffer tok,
TokenFlags  flags 
)

Extract one token from a string.

Parameters
destBuffer for the result
tokBuffer containing tokens
flagsFlags, see TokenFlags
Return values
0Success
-1Error

Definition at line 272 of file init.c.

273{
274 if (!dest || !tok)
275 return -1;
276
277 char ch;
278 char qc = '\0'; /* quote char */
279 char *pc = NULL;
280
281 /* Some callers used to rely on the (bad) assumption that dest->data would be
282 * non-NULL after calling this function. Perhaps I've missed a few cases, or
283 * a future caller might make the same mistake. */
284 if (!dest->data)
285 mutt_buffer_alloc(dest, 256);
286
287 mutt_buffer_reset(dest);
288
289 SKIPWS(tok->dptr);
290 while ((ch = *tok->dptr))
291 {
292 if (qc == '\0')
293 {
294 if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
295 ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
296 ((ch == '+') && (flags & MUTT_TOKEN_PLUS)) ||
297 ((ch == '-') && (flags & MUTT_TOKEN_MINUS)) ||
298 ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
299 ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
300 ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
301 ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
302 {
303 break;
304 }
305 }
306
307 tok->dptr++;
308
309 if (ch == qc)
310 qc = 0; /* end of quote */
311 else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
312 qc = ch;
313 else if ((ch == '\\') && (qc != '\''))
314 {
315 if (tok->dptr[0] == '\0')
316 return -1; /* premature end of token */
317 switch (ch = *tok->dptr++)
318 {
319 case 'c':
320 case 'C':
321 if (tok->dptr[0] == '\0')
322 return -1; /* premature end of token */
323 mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
324 tok->dptr++;
325 break;
326 case 'e':
327 mutt_buffer_addch(dest, '\033'); // Escape
328 break;
329 case 'f':
330 mutt_buffer_addch(dest, '\f');
331 break;
332 case 'n':
333 mutt_buffer_addch(dest, '\n');
334 break;
335 case 'r':
336 mutt_buffer_addch(dest, '\r');
337 break;
338 case 't':
339 mutt_buffer_addch(dest, '\t');
340 break;
341 default:
342 if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
343 isdigit((unsigned char) tok->dptr[1]))
344 {
345 mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
346 tok->dptr += 2;
347 }
348 else
349 mutt_buffer_addch(dest, ch);
350 }
351 }
352 else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
353 {
354 if (tok->dptr[0] == '\0')
355 return -1; /* premature end of token */
356 ch = *tok->dptr++;
357 if (ch == '^')
358 mutt_buffer_addch(dest, ch);
359 else if (ch == '[')
360 mutt_buffer_addch(dest, '\033'); // Escape
361 else if (isalpha((unsigned char) ch))
362 mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
363 else
364 {
365 mutt_buffer_addch(dest, '^');
366 mutt_buffer_addch(dest, ch);
367 }
368 }
369 else if ((ch == '`') && (!qc || (qc == '"')))
370 {
371 FILE *fp = NULL;
372 pid_t pid;
373
374 pc = tok->dptr;
375 do
376 {
377 pc = strpbrk(pc, "\\`");
378 if (pc)
379 {
380 /* skip any quoted chars */
381 if (*pc == '\\')
382 pc += 2;
383 }
384 } while (pc && (pc[0] != '`'));
385 if (!pc)
386 {
387 mutt_debug(LL_DEBUG1, "mismatched backticks\n");
388 return -1;
389 }
390 struct Buffer cmd;
391 mutt_buffer_init(&cmd);
392 *pc = '\0';
393 if (flags & MUTT_TOKEN_BACKTICK_VARS)
394 {
395 /* recursively extract tokens to interpolate variables */
396 mutt_extract_token(&cmd, tok,
399 }
400 else
401 {
402 cmd.data = mutt_str_dup(tok->dptr);
403 }
404 *pc = '`';
405 pid = filter_create(cmd.data, NULL, &fp, NULL);
406 if (pid < 0)
407 {
408 mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
409 FREE(&cmd.data);
410 return -1;
411 }
412
413 tok->dptr = pc + 1;
414
415 /* read line */
416 struct Buffer expn = mutt_buffer_make(0);
417 expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, NULL, MUTT_RL_NO_FLAGS);
418 mutt_file_fclose(&fp);
419 int rc = filter_wait(pid);
420 if (rc != 0)
421 mutt_debug(LL_DEBUG1, "backticks exited code %d for command: %s\n", rc,
422 mutt_buffer_string(&cmd));
423 FREE(&cmd.data);
424
425 /* if we got output, make a new string consisting of the shell output
426 * plus whatever else was left on the original line */
427 /* BUT: If this is inside a quoted string, directly add output to
428 * the token */
429 if (expn.data)
430 {
431 if (qc)
432 {
433 mutt_buffer_addstr(dest, expn.data);
434 }
435 else
436 {
437 struct Buffer *copy = mutt_buffer_pool_get();
439 mutt_buffer_copy(copy, &expn);
440 mutt_buffer_addstr(copy, tok->dptr);
441 mutt_buffer_copy(tok, copy);
442 mutt_buffer_seek(tok, 0);
444 }
445 FREE(&expn.data);
446 }
447 }
448 else if ((ch == '$') && (!qc || (qc == '"')) &&
449 ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
450 {
451 const char *env = NULL;
452 char *var = NULL;
453
454 if (tok->dptr[0] == '{')
455 {
456 pc = strchr(tok->dptr, '}');
457 if (pc)
458 {
459 var = mutt_strn_dup(tok->dptr + 1, pc - (tok->dptr + 1));
460 tok->dptr = pc + 1;
461
462 if ((flags & MUTT_TOKEN_NOSHELL))
463 {
464 mutt_buffer_addch(dest, ch);
465 mutt_buffer_addch(dest, '{');
466 mutt_buffer_addstr(dest, var);
467 mutt_buffer_addch(dest, '}');
468 FREE(&var);
469 }
470 }
471 }
472 else
473 {
474 for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
475 ; // do nothing
476
477 var = mutt_strn_dup(tok->dptr, pc - tok->dptr);
478 tok->dptr = pc;
479 }
480 if (var)
481 {
482 struct Buffer result;
483 mutt_buffer_init(&result);
484 int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
485
486 if (CSR_RESULT(rc) == CSR_SUCCESS)
487 {
488 mutt_buffer_addstr(dest, result.data);
489 FREE(&result.data);
490 }
491 else if ((env = myvar_get(var)))
492 {
493 mutt_buffer_addstr(dest, env);
494 }
495 else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
496 {
497 mutt_buffer_addstr(dest, env);
498 }
499 else
500 {
501 mutt_buffer_addch(dest, ch);
502 mutt_buffer_addstr(dest, var);
503 }
504 FREE(&var);
505 }
506 }
507 else
508 mutt_buffer_addch(dest, ch);
509 }
510 mutt_buffer_addch(dest, 0); /* terminate the string */
511 SKIPWS(tok->dptr);
512 return 0;
513}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:275
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:52
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:189
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:483
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:272
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:927
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:69
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:75
#define MUTT_TOKEN_MINUS
Treat '-' as a special.
Definition: mutt.h:79
#define MUTT_TOKEN_PLUS
Treat '+' as a special.
Definition: mutt.h:78
#define MUTT_TOKEN_COMMENT
Don't reap comments.
Definition: mutt.h:73
#define MUTT_TOKEN_QUOTE
Don't interpret quotes.
Definition: mutt.h:71
#define MUTT_TOKEN_NOSHELL
Don't expand environment variables.
Definition: mutt.h:76
#define MUTT_TOKEN_SPACE
Don't treat whitespace as a term.
Definition: mutt.h:70
#define MUTT_TOKEN_SEMICOLON
Don't treat ; as special.
Definition: mutt.h:74
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:72
#define MUTT_TOKEN_EQUAL
Treat '=' as a special.
Definition: mutt.h:68
#define MUTT_TOKEN_QUESTION
Treat '?' as a special.
Definition: mutt.h:77
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:92
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define IS_SPACE(ch)
Definition: string2.h:38
#define SKIPWS(ch)
Definition: string2.h:46
char * dptr
Current read/write position.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:370
+ Here is the call graph for this function:

◆ mutt_opts_free()

void mutt_opts_free ( void  )

Clean up before quitting.

Definition at line 518 of file init.c.

519{
521
523#ifdef USE_SIDEBAR
524 sb_shutdown();
525#endif
526
532
535
536 /* Lists of strings */
546
548
550 FREE(&HomeDir);
553 FREE(&Username);
554
556
558
561
564}
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:687
void mutt_colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:71
void clear_source_stack(void)
Free memory from the stack used for the source command.
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:43
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:40
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:42
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:41
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:37
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:35
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:36
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:102
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:438
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:367
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:37
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1668
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:174
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:467
void mutt_commands_free(void)
Free Commands array.
char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:55
struct ListHead MimeLookupList
List of mime types that that shouldn't use the mailcap entry.
Definition: mutt_globals.h:63
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition: mutt_globals.h:60
struct ListHead AutoViewList
List of mime types to auto view.
Definition: mutt_globals.h:61
char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
struct ListHead UserHeader
List of custom headers to add to outgoing emails.
Definition: mutt_globals.h:66
struct ListHead Muttrc
List of config files to read.
Definition: mutt_globals.h:64
char * Username
User's login name.
Definition: mutt_globals.h:52
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: mutt_globals.h:62
void sb_shutdown(void)
Clean up the Sidebar.
Definition: sidebar.c:208
void driver_tags_cleanup(void)
Deinitialize structures used for tags.
Definition: tags.c:230
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_init()

int mutt_init ( struct ConfigSet cs,
bool  skip_sys_rc,
struct ListHead *  commands 
)

Initialise NeoMutt.

Parameters
csConfig Set
skip_sys_rcIf true, don't read the system config file
commandsList of config commands to execute
Return values
0Success
1Error

Definition at line 574 of file init.c.

575{
576 int need_pause = 0;
577 int rc = 1;
578 struct Buffer err = mutt_buffer_make(256);
579 struct Buffer buf = mutt_buffer_make(256);
580
582 alias_init();
584#ifdef USE_COMP_MBOX
586#endif
587#ifdef USE_IMAP
588 imap_init();
589#endif
590#ifdef USE_LUA
592#endif
594
595 menu_init();
596#ifdef USE_SIDEBAR
597 sb_init();
598#endif
599#ifdef USE_NOTMUCH
600 nm_init();
601#endif
602
603 /* "$spool_file" precedence: config file, environment */
604 const char *p = mutt_str_getenv("MAIL");
605 if (!p)
606 p = mutt_str_getenv("MAILDIR");
607 if (!p)
608 {
609#ifdef HOMESPOOL
610 mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
611#else
612 mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
613#endif
614 p = mutt_buffer_string(&buf);
615 }
616 cs_str_initial_set(cs, "spool_file", p, NULL);
617 cs_str_reset(cs, "spool_file", NULL);
618
619 p = mutt_str_getenv("REPLYTO");
620 if (p)
621 {
622 struct Buffer token;
623
624 mutt_buffer_printf(&buf, "Reply-To: %s", p);
625 mutt_buffer_init(&token);
626 parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
627 FREE(&token.data);
628 }
629
630 p = mutt_str_getenv("EMAIL");
631 if (p)
632 {
633 cs_str_initial_set(cs, "from", p, NULL);
634 cs_str_reset(cs, "from", NULL);
635 }
636
637 /* "$mailcap_path" precedence: config file, environment, code */
638 const char *env_mc = mutt_str_getenv("MAILCAPS");
639 if (env_mc)
640 cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
641
642 /* "$tmpdir" precedence: config file, environment, code */
643 const char *env_tmp = mutt_str_getenv("TMPDIR");
644 if (env_tmp)
645 cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
646
647 /* "$visual", "$editor" precedence: config file, environment, code */
648 const char *env_ed = mutt_str_getenv("VISUAL");
649 if (!env_ed)
650 env_ed = mutt_str_getenv("EDITOR");
651 if (!env_ed)
652 env_ed = "vi";
653 cs_str_initial_set(cs, "editor", env_ed, NULL);
654
655 const char *const c_editor = cs_subset_string(NeoMutt->sub, "editor");
656 if (!c_editor)
657 cs_str_reset(cs, "editor", NULL);
658
659 const char *charset = mutt_ch_get_langinfo_charset();
660 cs_str_initial_set(cs, "charset", charset, NULL);
661 cs_str_reset(cs, "charset", NULL);
662 mutt_ch_set_charset(charset);
663 FREE(&charset);
664
665#ifdef HAVE_GETSID
666 /* Unset suspend by default if we're the session leader */
667 if (getsid(0) == getpid())
668 cs_subset_str_native_set(NeoMutt->sub, "suspend", false, NULL);
669#endif
670
671 /* RFC2368, "4. Unsafe headers"
672 * The creator of a mailto URL can't expect the resolver of a URL to
673 * understand more than the "subject" and "body" headers. Clients that
674 * resolve mailto URLs into mail messages should be able to correctly
675 * create RFC822-compliant mail messages using the "subject" and "body"
676 * headers. */
677 add_to_stailq(&MailToAllow, "body");
678 add_to_stailq(&MailToAllow, "subject");
679 /* Cc, In-Reply-To, and References help with not breaking threading on
680 * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
682 add_to_stailq(&MailToAllow, "in-reply-to");
683 add_to_stailq(&MailToAllow, "references");
684
685 if (STAILQ_EMPTY(&Muttrc))
686 {
687 const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
688
689 if (!xdg_cfg_home && HomeDir)
690 {
691 mutt_buffer_printf(&buf, "%s/.config", HomeDir);
692 xdg_cfg_home = mutt_buffer_string(&buf);
693 }
694
695 char *config = find_cfg(HomeDir, xdg_cfg_home);
696 if (config)
697 {
699 }
700 }
701 else
702 {
703 struct ListNode *np = NULL;
704 STAILQ_FOREACH(np, &Muttrc, entries)
705 {
706 mutt_buffer_strcpy(&buf, np->data);
707 FREE(&np->data);
709 np->data = mutt_buffer_strdup(&buf);
710 if (access(np->data, F_OK))
711 {
712 mutt_perror(np->data);
713 goto done; // TEST10: neomutt -F missing
714 }
715 }
716 }
717
718 if (!STAILQ_EMPTY(&Muttrc))
719 {
720 cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
721 }
722
723 /* Process the global rc file if it exists and the user hasn't explicitly
724 * requested not to via "-n". */
725 if (!skip_sys_rc)
726 {
727 do
728 {
730 break;
731
732 mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
733 if (access(mutt_buffer_string(&buf), F_OK) == 0)
734 break;
735
736 mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
737 if (access(mutt_buffer_string(&buf), F_OK) == 0)
738 break;
739
740 mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
741 if (access(mutt_buffer_string(&buf), F_OK) == 0)
742 break;
743
744 mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
745 } while (false);
746
747 if (access(mutt_buffer_string(&buf), F_OK) == 0)
748 {
749 if (source_rc(mutt_buffer_string(&buf), &err) != 0)
750 {
751 mutt_error("%s", err.data);
752 need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
753 }
754 }
755 }
756
757 /* Read the user's initialization file. */
758 struct ListNode *np = NULL;
759 STAILQ_FOREACH(np, &Muttrc, entries)
760 {
761 if (np->data)
762 {
763 if (source_rc(np->data, &err) != 0)
764 {
765 mutt_error("%s", err.data);
766 need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
767 }
768 }
769 }
770
771 if (execute_commands(commands) != 0)
772 need_pause = 1; // TEST13: neomutt -e broken
773
774 if (!get_hostname(cs))
775 goto done;
776
777 {
778 char name[256] = { 0 };
779 const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
780 if (!c_real_name)
781 {
782 struct passwd *pw = getpwuid(getuid());
783 if (pw)
784 c_real_name = mutt_gecos_name(name, sizeof(name), pw);
785 }
786 cs_str_initial_set(cs, "real_name", c_real_name, NULL);
787 cs_str_reset(cs, "real_name", NULL);
788 }
789
790 if (need_pause && !OptNoCurses)
791 {
793 if (mutt_any_key_to_continue(NULL) == 'q')
794 goto done; // TEST14: neomutt -e broken (press 'q')
795 }
796
797 const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
798 mutt_file_mkdir(c_tmpdir, S_IRWXU);
799
802
803#ifdef USE_NOTMUCH
804 const bool c_virtual_spool_file = cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
805 if (c_virtual_spool_file)
806 {
807 /* Find the first virtual folder and open it */
808 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
810 struct MailboxNode *mp = STAILQ_FIRST(&ml);
811 if (mp)
812 cs_str_string_set(cs, "spool_file", mailbox_path(mp->mailbox), NULL);
814 }
815#endif
816 rc = 0;
817
818done:
821 return rc;
822}
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:679
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:389
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:70
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:387
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:946
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:90
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition: logging.c:440
void mutt_hist_read_file(void)
Read the History from a file.
Definition: history.c:593
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:465
void imap_init(void)
Setup feature commands.
Definition: imap.c:84
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: init.c:113
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: init.c:81
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition: init.c:186
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:346
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
void menu_init(void)
Initialise all the Menus.
Definition: menu.c:74
char * mutt_ch_get_langinfo_charset(void)
Get the user's choice of character set.
Definition: charset.c:461
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:1002
void mutt_commands_init(void)
Initialize commands array and register default commands.
struct CommandArray commands
void mutt_lua_init(void)
Setup feature commands.
Definition: mutt_lua.c:469
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:361
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1719
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition: muttlib.c:1510
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
void nm_init(void)
Setup feature commands.
Definition: notmuch.c:99
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:44
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_EMPTY(head)
Definition: queue.h:348
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:595
void sb_init(void)
Set up the Sidebar.
Definition: sidebar.c:196
List of Mailboxes.
Definition: mailbox.h:153
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
void driver_tags_init(void)
Initialize structures used for tags.
Definition: tags.c:218
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_rc_buffer()

enum CommandResult mutt_parse_rc_buffer ( struct Buffer line,
struct Buffer token,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineconfig line to read
tokenscratch buffer to be used by parser
errwhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

The reason for token is to avoid having to allocate and deallocate a lot of memory if we are parsing many lines. the caller can pass in the memory to use, which avoids having to create new space for every call to this function.

Definition at line 835 of file init.c.

837{
838 if (mutt_buffer_len(line) == 0)
839 return 0;
840
842
844
845 /* Read from the beginning of line->data */
846 mutt_buffer_seek(line, 0);
847
848 SKIPWS(line->dptr);
849 while (*line->dptr)
850 {
851 if (*line->dptr == '#')
852 break; /* rest of line is a comment */
853 if (*line->dptr == ';')
854 {
855 line->dptr++;
856 continue;
857 }
859
860 struct Command *cmd = NULL;
861 size_t size = mutt_commands_array(&cmd);
862 size_t i;
863 for (i = 0; i < size; i++)
864 {
865 if (mutt_str_equal(token->data, cmd[i].name))
866 {
867 mutt_debug(LL_DEBUG1, "NT_COMMAND: %s\n", cmd[i].name);
868 rc = cmd[i].parse(token, line, cmd[i].data, err);
869 if ((rc == MUTT_CMD_WARNING) || (rc == MUTT_CMD_ERROR) || (rc == MUTT_CMD_FINISH))
870 goto finish; /* Propagate return code */
871
872 notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
873 break; /* Continue with next command */
874 }
875 }
876 if (i == size)
877 {
878 mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
879 rc = MUTT_CMD_ERROR;
880 break; /* Ignore the rest of the line */
881 }
882 }
883finish:
884 return rc;
885}
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_FINISH
Finish: Stop processing this file.
Definition: command.h:38
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:67
size_t mutt_commands_array(struct Command **first)
Get Commands array.
@ NT_COMMAND
A Command has been executed, Command.
Definition: notify_type.h:42
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Definition: command.h:63
intptr_t data
Data or flags to pass to the command.
Definition: command.h:65
const char * name
Name of the command.
Definition: command.h:50
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_rc_line()

enum CommandResult mutt_parse_rc_line ( const char *  line,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineConfig line to read
errWhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 893 of file init.c.

894{
895 if (!line || (*line == '\0'))
896 return MUTT_CMD_ERROR;
897
898 struct Buffer *line_buffer = mutt_buffer_pool_get();
899 struct Buffer *token = mutt_buffer_pool_get();
900
901 mutt_buffer_strcpy(line_buffer, line);
902
903 enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
904
905 mutt_buffer_pool_release(&line_buffer);
907 return rc;
908}
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:835
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_query_variables()

int mutt_query_variables ( struct ListHead *  queries,
bool  show_docs 
)

Implement the -Q command line flag.

Parameters
queriesList of query strings
show_docsIf true, show one-liner docs for the config item
Return values
0Success, all queries exist
1Error

Definition at line 917 of file init.c.

918{
919 struct Buffer value = mutt_buffer_make(256);
920 struct Buffer tmp = mutt_buffer_make(256);
921 int rc = 0;
922
923 struct ListNode *np = NULL;
924 STAILQ_FOREACH(np, queries, entries)
925 {
926 mutt_buffer_reset(&value);
927
928 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
929 if (!he)
930 {
931 mutt_warning(_("No such variable: %s"), np->data);
932 rc = 1;
933 continue;
934 }
935
936 if (he->type & DT_DEPRECATED)
937 {
938 mutt_warning(_("Config variable '%s' is deprecated"), np->data);
939 rc = 1;
940 continue;
941 }
942
943 int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
944 if (CSR_RESULT(rv) != CSR_SUCCESS)
945 {
946 rc = 1;
947 continue;
948 }
949
950 int type = DTYPE(he->type);
951 if (type == DT_PATH)
952 mutt_pretty_mailbox(value.data, value.dsize);
953
954 if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
955 {
956 mutt_buffer_reset(&tmp);
957 pretty_var(value.data, &tmp);
958 mutt_buffer_strcpy(&value, tmp.data);
959 }
960
961 dump_config_neo(NeoMutt->sub->cs, he, &value, NULL,
962 show_docs ? CS_DUMP_SHOW_DOCS : CS_DUMP_NO_FLAGS, stdout);
963 }
964
965 mutt_buffer_dealloc(&value);
967
968 return rc; // TEST16: neomutt -Q charset
969}
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:522
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
The item stored in a Hash Table.
Definition: hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:354
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:179
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
#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 DT_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:77
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_NUMBER
a number
Definition: types.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function: