NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
init.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <ctype.h>
32 #include <errno.h>
33 #include <inttypes.h>
34 #include <limits.h>
35 #include <pwd.h>
36 #include <regex.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <sys/utsname.h>
43 #include <unistd.h>
44 #include "mutt/lib.h"
45 #include "address/lib.h"
46 #include "config/lib.h"
47 #include "email/lib.h"
48 #include "core/lib.h"
49 #include "conn/lib.h"
50 #include "gui/lib.h"
51 #include "mutt.h"
52 #include "init.h"
53 #include "alias.h"
54 #include "command_parse.h"
55 #include "context.h"
56 #include "functions.h"
57 #include "globals.h"
58 #include "keymap.h"
59 #include "monitor.h"
60 #include "mutt_commands.h"
61 #include "mutt_config.h"
62 #include "mutt_menu.h"
63 #include "mutt_parse.h"
64 #include "muttlib.h"
65 #include "mx.h"
66 #include "myvar.h"
67 #include "options.h"
68 #include "protos.h"
69 #include "sidebar.h"
70 #include "sort.h"
71 #include "version.h"
72 #ifdef USE_HCACHE
73 #include "hcache/lib.h"
74 #endif
75 #ifdef USE_NOTMUCH
76 #include "notmuch/lib.h"
77 #endif
78 #ifdef USE_IMAP
79 #include "imap/lib.h"
80 #endif
81 #ifdef ENABLE_NLS
82 #include <libintl.h>
83 #endif
84 
85 /* Initial string that starts completion. No telling how much the user has
86  * typed so far. Allocate 1024 just to be sure! */
87 static char UserTyped[1024] = { 0 };
88 
89 static int NumMatched = 0; /* Number of matches for completion */
90 static char Completed[256] = { 0 }; /* completed string (command or variable) */
91 static const char **Matches;
92 /* this is a lie until mutt_init runs: */
93 static int MatchesListsize = 512; // Enough space for all of the config items
94 
95 #ifdef USE_NOTMUCH
96 /* List of tags found in last call to mutt_nm_query_complete(). */
97 static char **nm_tags;
98 #endif
99 
104 static void matches_ensure_morespace(int current)
105 {
106  if (current <= (MatchesListsize - 2))
107  return;
108 
109  int base_space = 512; // Enough space for all of the config items
110  int extra_space = MatchesListsize - base_space;
111  extra_space *= 2;
112  const int space = base_space + extra_space;
113  mutt_mem_realloc(&Matches, space * sizeof(char *));
114  memset(&Matches[current + 1], 0, space - current);
115  MatchesListsize = space;
116 }
117 
127 static void candidate(char *user, const char *src, char *dest, size_t dlen)
128 {
129  if (!dest || !user || !src)
130  return;
131 
132  if (strstr(src, user) != src)
133  return;
134 
136  Matches[NumMatched++] = src;
137  if (dest[0] == '\0')
138  mutt_str_strfcpy(dest, src, dlen);
139  else
140  {
141  int l;
142  for (l = 0; src[l] && src[l] == dest[l]; l++)
143  ;
144  dest[l] = '\0';
145  }
146 }
147 
148 #ifdef USE_NOTMUCH
149 
155 static int complete_all_nm_tags(const char *pt)
156 {
157  int tag_count_1 = 0;
158  int tag_count_2 = 0;
159 
160  NumMatched = 0;
161  mutt_str_strfcpy(UserTyped, pt, sizeof(UserTyped));
162  memset(Matches, 0, MatchesListsize);
163  memset(Completed, 0, sizeof(Completed));
164 
166 
167  /* Work out how many tags there are. */
168  if (nm_get_all_tags(Context->mailbox, NULL, &tag_count_1) || (tag_count_1 == 0))
169  goto done;
170 
171  /* Free the old list, if any. */
172  if (nm_tags)
173  {
174  for (int i = 0; nm_tags[i]; i++)
175  FREE(&nm_tags[i]);
176  FREE(&nm_tags);
177  }
178  /* Allocate a new list, with sentinel. */
179  nm_tags = mutt_mem_malloc((tag_count_1 + 1) * sizeof(char *));
180  nm_tags[tag_count_1] = NULL;
181 
182  /* Get all the tags. */
183  if (nm_get_all_tags(Context->mailbox, nm_tags, &tag_count_2) || (tag_count_1 != tag_count_2))
184  {
185  FREE(&nm_tags);
186  nm_tags = NULL;
188  return -1;
189  }
190 
191  /* Put them into the completion machinery. */
192  for (int num = 0; num < tag_count_1; num++)
193  {
194  candidate(UserTyped, nm_tags[num], Completed, sizeof(Completed));
195  }
196 
199 
200 done:
202  return 0;
203 }
204 #endif
205 
212 static int execute_commands(struct ListHead *p)
213 {
214  int rc = 0;
215  struct Buffer *err = mutt_buffer_pool_get();
216  struct Buffer *token = mutt_buffer_pool_get();
217 
218  struct ListNode *np = NULL;
219  STAILQ_FOREACH(np, p, entries)
220  {
221  enum CommandResult rc2 = mutt_parse_rc_line(np->data, token, err);
222  if (rc2 == MUTT_CMD_ERROR)
223  mutt_error(_("Error in command line: %s"), mutt_b2s(err));
224  else if (rc2 == MUTT_CMD_WARNING)
225  mutt_warning(_("Warning in command line: %s"), mutt_b2s(err));
226 
227  if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
228  {
229  mutt_buffer_pool_release(&token);
231  return -1;
232  }
233  }
234  mutt_buffer_pool_release(&token);
236 
237  return rc;
238 }
239 
247 static char *find_cfg(const char *home, const char *xdg_cfg_home)
248 {
249  const char *names[] = {
250  "neomuttrc",
251  "muttrc",
252  NULL,
253  };
254 
255  const char *locations[][2] = {
256  { xdg_cfg_home, "neomutt/" },
257  { xdg_cfg_home, "mutt/" },
258  { home, ".neomutt/" },
259  { home, ".mutt/" },
260  { home, "." },
261  { NULL, NULL },
262  };
263 
264  for (int i = 0; locations[i][0] || locations[i][1]; i++)
265  {
266  if (!locations[i][0])
267  continue;
268 
269  for (int j = 0; names[j]; j++)
270  {
271  char buf[256];
272 
273  snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
274  if (access(buf, F_OK) == 0)
275  return mutt_str_strdup(buf);
276  }
277  }
278 
279  return NULL;
280 }
281 
282 #ifndef DOMAIN
283 
288 static char *getmailname(void)
289 {
290  char *mailname = NULL;
291  static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
292 
293  for (size_t i = 0; i < mutt_array_size(mn_files); i++)
294  {
295  FILE *fp = mutt_file_fopen(mn_files[i], "r");
296  if (!fp)
297  continue;
298 
299  size_t len = 0;
300  mailname = mutt_file_read_line(NULL, &len, fp, NULL, 0);
301  mutt_file_fclose(&fp);
302  if (mailname && *mailname)
303  break;
304 
305  FREE(&mailname);
306  }
307 
308  return mailname;
309 }
310 #endif
311 
320 static bool get_hostname(struct ConfigSet *cs)
321 {
322  char *str = NULL;
323  struct utsname utsname;
324 
325  if (C_Hostname)
326  {
327  str = C_Hostname;
328  }
329  else
330  {
331  /* The call to uname() shouldn't fail, but if it does, the system is horribly
332  * broken, and the system's networking configuration is in an unreliable
333  * state. We should bail. */
334  if ((uname(&utsname)) == -1)
335  {
336  mutt_perror(_("unable to determine nodename via uname()"));
337  return false; // TEST09: can't test
338  }
339 
340  str = utsname.nodename;
341  }
342 
343  /* some systems report the FQDN instead of just the hostname */
344  char *dot = strchr(str, '.');
345  if (dot)
347  else
349 
350  if (!C_Hostname)
351  {
352  /* now get FQDN. Use configured domain first, DNS next, then uname */
353 #ifdef DOMAIN
354  /* we have a compile-time domain name, use that for C_Hostname */
355  C_Hostname =
357  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), DOMAIN);
358 #else
359  C_Hostname = getmailname();
360  if (!C_Hostname)
361  {
362  char buffer[1024];
363  if (getdnsdomainname(buffer, sizeof(buffer)) == 0)
364  {
365  C_Hostname = mutt_mem_malloc(mutt_str_strlen(buffer) +
367  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), buffer);
368  }
369  else
370  {
371  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
372  * in it, we can use the nodename as the FQDN. On hosts where DNS is
373  * not being used, e.g. small network that relies on hosts files, a
374  * short host name is all that is required for SMTP to work correctly.
375  * It could be wrong, but we've done the best we can, at this point the
376  * onus is on the user to provide the correct hostname if the nodename
377  * won't work in their network. */
378  C_Hostname = mutt_str_strdup(utsname.nodename);
379  }
380  }
381 #endif
382  }
383  if (C_Hostname)
384  cs_str_initial_set(cs, "hostname", C_Hostname, NULL);
385 
386  return true;
387 }
388 
395 const struct Command *mutt_command_get(const char *s)
396 {
397  for (int i = 0; Commands[i].name; i++)
398  if (mutt_str_strcmp(s, Commands[i].name) == 0)
399  return &Commands[i];
400  return NULL;
401 }
402 
403 #ifdef USE_LUA
404 
411 void mutt_commands_apply(void *data, void (*application)(void *, const struct Command *))
412 {
413  for (int i = 0; Commands[i].name; i++)
414  application(data, &Commands[i]);
415 }
416 #endif
417 
426 int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
427 {
428  if (!dest || !tok)
429  return -1;
430 
431  char ch;
432  char qc = '\0'; /* quote char */
433  char *pc = NULL;
434 
435  mutt_buffer_reset(dest);
436 
437  SKIPWS(tok->dptr);
438  while ((ch = *tok->dptr))
439  {
440  if (qc == '\0')
441  {
442  if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
443  ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
444  ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
445  ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
446  ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
447  ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
448  {
449  break;
450  }
451  }
452 
453  tok->dptr++;
454 
455  if (ch == qc)
456  qc = 0; /* end of quote */
457  else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
458  qc = ch;
459  else if ((ch == '\\') && (qc != '\''))
460  {
461  if (tok->dptr[0] == '\0')
462  return -1; /* premature end of token */
463  switch (ch = *tok->dptr++)
464  {
465  case 'c':
466  case 'C':
467  if (tok->dptr[0] == '\0')
468  return -1; /* premature end of token */
469  mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
470  tok->dptr++;
471  break;
472  case 'e':
473  mutt_buffer_addch(dest, '\033'); // Escape
474  break;
475  case 'f':
476  mutt_buffer_addch(dest, '\f');
477  break;
478  case 'n':
479  mutt_buffer_addch(dest, '\n');
480  break;
481  case 'r':
482  mutt_buffer_addch(dest, '\r');
483  break;
484  case 't':
485  mutt_buffer_addch(dest, '\t');
486  break;
487  default:
488  if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
489  isdigit((unsigned char) tok->dptr[1]))
490  {
491  mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
492  tok->dptr += 2;
493  }
494  else
495  mutt_buffer_addch(dest, ch);
496  }
497  }
498  else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
499  {
500  if (tok->dptr[0] == '\0')
501  return -1; /* premature end of token */
502  ch = *tok->dptr++;
503  if (ch == '^')
504  mutt_buffer_addch(dest, ch);
505  else if (ch == '[')
506  mutt_buffer_addch(dest, '\033'); // Escape
507  else if (isalpha((unsigned char) ch))
508  mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
509  else
510  {
511  mutt_buffer_addch(dest, '^');
512  mutt_buffer_addch(dest, ch);
513  }
514  }
515  else if ((ch == '`') && (!qc || (qc == '"')))
516  {
517  FILE *fp = NULL;
518  pid_t pid;
519  int line = 0;
520 
521  pc = tok->dptr;
522  do
523  {
524  pc = strpbrk(pc, "\\`");
525  if (pc)
526  {
527  /* skip any quoted chars */
528  if (*pc == '\\')
529  pc += 2;
530  }
531  } while (pc && (pc[0] != '`'));
532  if (!pc)
533  {
534  mutt_debug(LL_DEBUG1, "mismatched backticks\n");
535  return -1;
536  }
537  struct Buffer cmd;
538  mutt_buffer_init(&cmd);
539  *pc = '\0';
540  if (flags & MUTT_TOKEN_BACKTICK_VARS)
541  {
542  /* recursively extract tokens to interpolate variables */
543  mutt_extract_token(&cmd, tok,
544  MUTT_TOKEN_QUOTE | MUTT_TOKEN_SPACE | MUTT_TOKEN_COMMENT |
546  }
547  else
548  {
549  cmd.data = mutt_str_strdup(tok->dptr);
550  }
551  *pc = '`';
552  pid = filter_create(cmd.data, NULL, &fp, NULL);
553  if (pid < 0)
554  {
555  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
556  FREE(&cmd.data);
557  return -1;
558  }
559  FREE(&cmd.data);
560 
561  tok->dptr = pc + 1;
562 
563  /* read line */
564  struct Buffer expn = mutt_buffer_make(0);
565  expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, &line, 0);
566  mutt_file_fclose(&fp);
567  filter_wait(pid);
568 
569  /* if we got output, make a new string consisting of the shell output
570  * plus whatever else was left on the original line */
571  /* BUT: If this is inside a quoted string, directly add output to
572  * the token */
573  if (expn.data)
574  {
575  if (qc)
576  {
577  mutt_buffer_addstr(dest, expn.data);
578  }
579  else
580  {
581  struct Buffer *copy = mutt_buffer_pool_get();
582  mutt_buffer_fix_dptr(&expn);
583  mutt_buffer_copy(copy, &expn);
584  mutt_buffer_addstr(copy, tok->dptr);
585  mutt_buffer_copy(tok, copy);
586  tok->dptr = tok->data;
588  }
589  FREE(&expn.data);
590  }
591  }
592  else if ((ch == '$') && (!qc || (qc == '"')) &&
593  ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
594  {
595  const char *env = NULL;
596  char *var = NULL;
597 
598  if (tok->dptr[0] == '{')
599  {
600  pc = strchr(tok->dptr, '}');
601  if (pc)
602  {
603  var = mutt_str_substr_dup(tok->dptr + 1, pc);
604  tok->dptr = pc + 1;
605 
606  if ((flags & MUTT_TOKEN_NOSHELL))
607  {
608  mutt_buffer_addch(dest, ch);
609  mutt_buffer_addch(dest, '{');
610  mutt_buffer_addstr(dest, var);
611  mutt_buffer_addch(dest, '}');
612  FREE(&var);
613  }
614  }
615  }
616  else
617  {
618  for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
619  ;
620  var = mutt_str_substr_dup(tok->dptr, pc);
621  tok->dptr = pc;
622  }
623  if (var)
624  {
625  struct Buffer result;
626  mutt_buffer_init(&result);
627  int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
628 
629  if (CSR_RESULT(rc) == CSR_SUCCESS)
630  {
631  mutt_buffer_addstr(dest, result.data);
632  FREE(&result.data);
633  }
634  else if ((env = myvar_get(var)))
635  {
636  mutt_buffer_addstr(dest, env);
637  }
638  else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
639  {
640  mutt_buffer_addstr(dest, env);
641  }
642  else
643  {
644  mutt_buffer_addch(dest, ch);
645  mutt_buffer_addstr(dest, var);
646  }
647  FREE(&var);
648  }
649  }
650  else
651  mutt_buffer_addch(dest, ch);
652  }
653  mutt_buffer_addch(dest, 0); /* terminate the string */
654  SKIPWS(tok->dptr);
655  return 0;
656 }
657 
661 void mutt_opts_free(void)
662 {
664 
665  mutt_aliaslist_free(&Aliases);
666 
667  mutt_regexlist_free(&Alternates);
671  mutt_regexlist_free(&UnAlternates);
674 
679 
680  /* Lists of strings */
681  mutt_list_free(&AlternativeOrderList);
682  mutt_list_free(&AutoViewList);
683  mutt_list_free(&HeaderOrderList);
686  mutt_list_free(&MimeLookupList);
687  mutt_list_free(&Muttrc);
688 #ifdef USE_SIDEBAR
689  mutt_list_free(&SidebarWhitelist);
690 #endif
692  mutt_list_free(&UserHeader);
693 
694  /* Lists of AttachMatch */
696  mutt_list_free_type(&AttachExclude, (list_free_t) mutt_attachmatch_free);
697  mutt_list_free_type(&InlineAllow, (list_free_t) mutt_attachmatch_free);
698  mutt_list_free_type(&InlineExclude, (list_free_t) mutt_attachmatch_free);
699 
701 
703  FREE(&HomeDir);
704  FREE(&LastFolder);
706  FREE(&Username);
707 
710 
712 
713  mutt_hist_free();
714  mutt_keys_free();
715 
717 }
718 
726 {
727  for (const struct Command *c = Commands; c->name; c++)
728  {
729  if (((c->func == mutt_parse_hook) || (c->func == mutt_parse_idxfmt_hook)) &&
730  (mutt_str_strcasecmp(c->name, name) == 0))
731  {
732  return c->data;
733  }
734  }
735  return MUTT_HOOK_NO_FLAGS;
736 }
737 
746 int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
747 {
748  char buf[1024];
749  int need_pause = 0;
750  int rc = 1;
751  struct Buffer err = mutt_buffer_make(256);
752 
754  /* reverse alias keys need to be strdup'ed because of idna conversions */
759 
760  mutt_menu_init();
761 
762  snprintf(AttachmentMarker, sizeof(AttachmentMarker), "\033]9;%" PRIu64 "\a", // Escape
763  mutt_rand64());
764 
765  snprintf(ProtectedHeaderMarker, sizeof(ProtectedHeaderMarker), "\033]8;%lld\a", // Escape
766  (long long) mutt_date_epoch());
767 
768  /* "$spoolfile" precedence: config file, environment */
769  const char *p = mutt_str_getenv("MAIL");
770  if (!p)
771  p = mutt_str_getenv("MAILDIR");
772  if (!p)
773  {
774 #ifdef HOMESPOOL
775  mutt_path_concat(buf, NONULL(HomeDir), MAILPATH, sizeof(buf));
776 #else
777  mutt_path_concat(buf, MAILPATH, NONULL(Username), sizeof(buf));
778 #endif
779  p = buf;
780  }
781  cs_str_initial_set(cs, "spoolfile", p, NULL);
782  cs_str_reset(cs, "spoolfile", NULL);
783 
784  p = mutt_str_getenv("REPLYTO");
785  if (p)
786  {
787  struct Buffer tmp, token;
788 
789  snprintf(buf, sizeof(buf), "Reply-To: %s", p);
790 
791  mutt_buffer_init(&tmp);
792  tmp.data = buf;
793  tmp.dptr = buf;
794  tmp.dsize = mutt_str_strlen(buf);
795 
796  mutt_buffer_init(&token);
797  parse_my_hdr(&token, &tmp, 0, &err); /* adds to UserHeader */
798  FREE(&token.data);
799  }
800 
801  p = mutt_str_getenv("EMAIL");
802  if (p)
803  {
804  cs_str_initial_set(cs, "from", p, NULL);
805  cs_str_reset(cs, "from", NULL);
806  }
807 
808  /* "$mailcap_path" precedence: config file, environment, code */
809  const char *env_mc = mutt_str_getenv("MAILCAPS");
810  if (env_mc)
811  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
812 
813  /* "$tmpdir" precedence: config file, environment, code */
814  const char *env_tmp = mutt_str_getenv("TMPDIR");
815  if (env_tmp)
816  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
817 
818  /* "$visual", "$editor" precedence: config file, environment, code */
819  const char *env_ed = mutt_str_getenv("VISUAL");
820  if (!env_ed)
821  env_ed = mutt_str_getenv("EDITOR");
822  if (env_ed)
823  {
824  cs_str_string_set(cs, "editor", env_ed, NULL);
825  cs_str_string_set(cs, "visual", env_ed, NULL);
826  }
827 
829  cs_str_initial_set(cs, "charset", C_Charset, NULL);
831 
832  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
833 
835 
836 #ifdef HAVE_GETSID
837  /* Unset suspend by default if we're the session leader */
838  if (getsid(0) == getpid())
839  C_Suspend = false;
840 #endif
841 
842  /* RFC2368, "4. Unsafe headers"
843  * The creator of a mailto URL can't expect the resolver of a URL to
844  * understand more than the "subject" and "body" headers. Clients that
845  * resolve mailto URLs into mail messages should be able to correctly
846  * create RFC822-compliant mail messages using the "subject" and "body"
847  * headers. */
848  add_to_stailq(&MailToAllow, "body");
849  add_to_stailq(&MailToAllow, "subject");
850  /* Cc, In-Reply-To, and References help with not breaking threading on
851  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
852  add_to_stailq(&MailToAllow, "cc");
853  add_to_stailq(&MailToAllow, "in-reply-to");
854  add_to_stailq(&MailToAllow, "references");
855 
856  if (STAILQ_EMPTY(&Muttrc))
857  {
858  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
859 
860  if (!xdg_cfg_home && HomeDir)
861  {
862  snprintf(buf, sizeof(buf), "%s/.config", HomeDir);
863  xdg_cfg_home = buf;
864  }
865 
866  char *config = find_cfg(HomeDir, xdg_cfg_home);
867  if (config)
868  {
869  mutt_list_insert_tail(&Muttrc, config);
870  }
871  }
872  else
873  {
874  struct ListNode *np = NULL;
875  STAILQ_FOREACH(np, &Muttrc, entries)
876  {
877  mutt_str_strfcpy(buf, np->data, sizeof(buf));
878  FREE(&np->data);
879  mutt_expand_path(buf, sizeof(buf));
880  np->data = mutt_str_strdup(buf);
881  if (access(np->data, F_OK))
882  {
883  mutt_perror(np->data);
884  goto done; // TEST10: neomutt -F missing
885  }
886  }
887  }
888 
889  if (!STAILQ_EMPTY(&Muttrc))
890  {
891  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
892  }
893 
894  /* Process the global rc file if it exists and the user hasn't explicitly
895  * requested not to via "-n". */
896  if (!skip_sys_rc)
897  {
898  do
899  {
900  if (mutt_set_xdg_path(XDG_CONFIG_DIRS, buf, sizeof(buf)))
901  break;
902 
903  snprintf(buf, sizeof(buf), "%s/neomuttrc", SYSCONFDIR);
904  if (access(buf, F_OK) == 0)
905  break;
906 
907  snprintf(buf, sizeof(buf), "%s/Muttrc", SYSCONFDIR);
908  if (access(buf, F_OK) == 0)
909  break;
910 
911  snprintf(buf, sizeof(buf), "%s/neomuttrc", PKGDATADIR);
912  if (access(buf, F_OK) == 0)
913  break;
914 
915  snprintf(buf, sizeof(buf), "%s/Muttrc", PKGDATADIR);
916  } while (false);
917 
918  if (access(buf, F_OK) == 0)
919  {
920  if (source_rc(buf, &err) != 0)
921  {
922  mutt_error("%s", err.data);
923  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
924  }
925  }
926  }
927 
928  /* Read the user's initialization file. */
929  struct ListNode *np = NULL;
930  STAILQ_FOREACH(np, &Muttrc, entries)
931  {
932  if (np->data)
933  {
934  if (source_rc(np->data, &err) != 0)
935  {
936  mutt_error("%s", err.data);
937  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
938  }
939  }
940  }
941 
942  if (execute_commands(commands) != 0)
943  need_pause = 1; // TEST13: neomutt -e broken
944 
945  if (!get_hostname(cs))
946  goto done;
947 
948  if (!C_Realname)
949  {
950  struct passwd *pw = getpwuid(getuid());
951  if (pw)
952  {
953  char name[256];
954  C_Realname = mutt_str_strdup(mutt_gecos_name(name, sizeof(name), pw));
955  }
956  }
957  cs_str_initial_set(cs, "realname", C_Realname, NULL);
958 
959  if (need_pause && !OptNoCurses)
960  {
962  if (mutt_any_key_to_continue(NULL) == 'q')
963  goto done; // TEST14: neomutt -e broken (press 'q')
964  }
965 
966  mutt_file_mkdir(C_Tmpdir, S_IRWXU);
967 
968  mutt_hist_init();
970 
971 #ifdef USE_NOTMUCH
972  if (C_VirtualSpoolfile)
973  {
974  /* Find the first virtual folder and open it */
975  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_NOTMUCH);
976  struct MailboxNode *mp = STAILQ_FIRST(&ml);
977  if (mp)
978  cs_str_string_set(cs, "spoolfile", mailbox_path(mp->mailbox), NULL);
980  }
981 #endif
982  rc = 0;
983 
984 done:
985  FREE(&err.data);
986  return rc;
987 }
988 
1001 enum CommandResult mutt_parse_rc_line(/* const */ char *line,
1002  struct Buffer *token, struct Buffer *err)
1003 {
1004  if (!line || !*line)
1005  return 0;
1006 
1007  int i;
1008  enum CommandResult rc = MUTT_CMD_SUCCESS;
1009 
1010  struct Buffer expn = mutt_buffer_make(128);
1011  mutt_buffer_addstr(&expn, line);
1012  expn.dptr = expn.data;
1013 
1014  *err->data = 0;
1015 
1016  SKIPWS(expn.dptr);
1017  while (*expn.dptr != '\0')
1018  {
1019  if (*expn.dptr == '#')
1020  break; /* rest of line is a comment */
1021  if (*expn.dptr == ';')
1022  {
1023  expn.dptr++;
1024  continue;
1025  }
1026  mutt_extract_token(token, &expn, MUTT_TOKEN_NO_FLAGS);
1027  for (i = 0; Commands[i].name; i++)
1028  {
1029  if (mutt_str_strcmp(token->data, Commands[i].name) == 0)
1030  {
1031  rc = Commands[i].func(token, &expn, Commands[i].data, err);
1032  if (rc != MUTT_CMD_SUCCESS)
1033  { /* -1 Error, +1 Finish */
1034  goto finish; /* Propagate return code */
1035  }
1036  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) &Commands[i]);
1037  break; /* Continue with next command */
1038  }
1039  }
1040  if (!Commands[i].name)
1041  {
1042  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1043  rc = MUTT_CMD_ERROR;
1044  break; /* Ignore the rest of the line */
1045  }
1046  }
1047 finish:
1048  mutt_buffer_dealloc(&expn);
1049  return rc;
1050 }
1051 
1058 int mutt_query_variables(struct ListHead *queries)
1059 {
1060  struct Buffer value = mutt_buffer_make(256);
1061  struct Buffer tmp = mutt_buffer_make(256);
1062  int rc = 0;
1063 
1064  struct ListNode *np = NULL;
1065  STAILQ_FOREACH(np, queries, entries)
1066  {
1067  mutt_buffer_reset(&value);
1068 
1069  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1070  if (!he)
1071  {
1072  rc = 1;
1073  continue;
1074  }
1075 
1076  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1077  if (CSR_RESULT(rv) != CSR_SUCCESS)
1078  {
1079  rc = 1;
1080  continue;
1081  }
1082 
1083  int type = DTYPE(he->type);
1084  if (IS_PATH(he) && !(he->type & DT_MAILBOX))
1085  mutt_pretty_mailbox(value.data, value.dsize);
1086 
1087  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1088  {
1089  mutt_buffer_reset(&tmp);
1090  pretty_var(value.data, &tmp);
1091  mutt_buffer_strcpy(&value, tmp.data);
1092  }
1093 
1094  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL, CS_DUMP_NO_FLAGS, stdout);
1095  }
1096 
1097  mutt_buffer_dealloc(&value);
1098  mutt_buffer_dealloc(&tmp);
1099 
1100  return rc; // TEST16: neomutt -Q charset
1101 }
1102 
1109 enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
1110 {
1111  switch (opt)
1112  {
1113  case MUTT_YES:
1114  case MUTT_NO:
1115  return opt;
1116 
1117  default:
1118  opt = mutt_yesorno(prompt, (opt == MUTT_ASKYES) ? MUTT_YES : MUTT_NO);
1120  return opt;
1121  }
1122 
1123  /* not reached */
1124 }
1125 
1135 int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
1136 {
1137  char *pt = buf;
1138  int num;
1139  int spaces; /* keep track of the number of leading spaces on the line */
1140  struct MyVar *myv = NULL;
1141 
1142  SKIPWS(buf);
1143  spaces = buf - pt;
1144 
1145  pt = buf + pos - spaces;
1146  while ((pt > buf) && !isspace((unsigned char) *pt))
1147  pt--;
1148 
1149  if (pt == buf) /* complete cmd */
1150  {
1151  /* first TAB. Collect all the matches */
1152  if (numtabs == 1)
1153  {
1154  NumMatched = 0;
1155  mutt_str_strfcpy(UserTyped, pt, sizeof(UserTyped));
1156  memset(Matches, 0, MatchesListsize);
1157  memset(Completed, 0, sizeof(Completed));
1158  for (num = 0; Commands[num].name; num++)
1162 
1163  /* All matches are stored. Longest non-ambiguous string is ""
1164  * i.e. don't change 'buf'. Fake successful return this time */
1165  if (UserTyped[0] == '\0')
1166  return 1;
1167  }
1168 
1169  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1170  return 0;
1171 
1172  /* NumMatched will _always_ be at least 1 since the initial
1173  * user-typed string is always stored */
1174  if ((numtabs == 1) && (NumMatched == 2))
1175  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1176  else if ((numtabs > 1) && (NumMatched > 2))
1177  {
1178  /* cycle through all the matches */
1179  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1180  }
1181 
1182  /* return the completed command */
1183  strncpy(buf, Completed, buflen - spaces);
1184  }
1185  else if (mutt_str_startswith(buf, "set", CASE_MATCH) ||
1186  mutt_str_startswith(buf, "unset", CASE_MATCH) ||
1187  mutt_str_startswith(buf, "reset", CASE_MATCH) ||
1188  mutt_str_startswith(buf, "toggle", CASE_MATCH))
1189  { /* complete variables */
1190  static const char *const prefixes[] = { "no", "inv", "?", "&", 0 };
1191 
1192  pt++;
1193  /* loop through all the possible prefixes (no, inv, ...) */
1194  if (mutt_str_startswith(buf, "set", CASE_MATCH))
1195  {
1196  for (num = 0; prefixes[num]; num++)
1197  {
1198  if (mutt_str_startswith(pt, prefixes[num], CASE_MATCH))
1199  {
1200  pt += mutt_str_strlen(prefixes[num]);
1201  break;
1202  }
1203  }
1204  }
1205 
1206  /* first TAB. Collect all the matches */
1207  if (numtabs == 1)
1208  {
1209  NumMatched = 0;
1210  mutt_str_strfcpy(UserTyped, pt, sizeof(UserTyped));
1211  memset(Matches, 0, MatchesListsize);
1212  memset(Completed, 0, sizeof(Completed));
1213  for (num = 0; MuttVars[num].name; num++)
1215  TAILQ_FOREACH(myv, &MyVars, entries)
1216  {
1217  candidate(UserTyped, myv->name, Completed, sizeof(Completed));
1218  }
1221 
1222  /* All matches are stored. Longest non-ambiguous string is ""
1223  * i.e. don't change 'buf'. Fake successful return this time */
1224  if (UserTyped[0] == '\0')
1225  return 1;
1226  }
1227 
1228  if ((Completed[0] == 0) && UserTyped[0])
1229  return 0;
1230 
1231  /* NumMatched will _always_ be at least 1 since the initial
1232  * user-typed string is always stored */
1233  if ((numtabs == 1) && (NumMatched == 2))
1234  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1235  else if ((numtabs > 1) && (NumMatched > 2))
1236  {
1237  /* cycle through all the matches */
1238  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1239  }
1240 
1241  strncpy(pt, Completed, buf + buflen - pt - spaces);
1242  }
1243  else if (mutt_str_startswith(buf, "exec", CASE_MATCH))
1244  {
1245  const struct Binding *menu = km_get_table(CurrentMenu);
1246 
1247  if (!menu && (CurrentMenu != MENU_PAGER))
1248  menu = OpGeneric;
1249 
1250  pt++;
1251  /* first TAB. Collect all the matches */
1252  if (numtabs == 1)
1253  {
1254  NumMatched = 0;
1255  mutt_str_strfcpy(UserTyped, pt, sizeof(UserTyped));
1256  memset(Matches, 0, MatchesListsize);
1257  memset(Completed, 0, sizeof(Completed));
1258  for (num = 0; menu[num].name; num++)
1259  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1260  /* try the generic menu */
1261  if ((Completed[0] == '\0') && (CurrentMenu != MENU_PAGER))
1262  {
1263  menu = OpGeneric;
1264  for (num = 0; menu[num].name; num++)
1265  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1266  }
1269 
1270  /* All matches are stored. Longest non-ambiguous string is ""
1271  * i.e. don't change 'buf'. Fake successful return this time */
1272  if (UserTyped[0] == '\0')
1273  return 1;
1274  }
1275 
1276  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1277  return 0;
1278 
1279  /* NumMatched will _always_ be at least 1 since the initial
1280  * user-typed string is always stored */
1281  if ((numtabs == 1) && (NumMatched == 2))
1282  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1283  else if ((numtabs > 1) && (NumMatched > 2))
1284  {
1285  /* cycle through all the matches */
1286  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1287  }
1288 
1289  strncpy(pt, Completed, buf + buflen - pt - spaces);
1290  }
1291  else
1292  return 0;
1293 
1294  return 1;
1295 }
1296 
1305 int mutt_label_complete(char *buf, size_t buflen, int numtabs)
1306 {
1307  char *pt = buf;
1308  int spaces; /* keep track of the number of leading spaces on the line */
1309 
1310  if (!Context || !Context->mailbox->label_hash)
1311  return 0;
1312 
1313  SKIPWS(buf);
1314  spaces = buf - pt;
1315 
1316  /* first TAB. Collect all the matches */
1317  if (numtabs == 1)
1318  {
1319  struct HashElem *entry = NULL;
1320  struct HashWalkState state = { 0 };
1321 
1322  NumMatched = 0;
1323  mutt_str_strfcpy(UserTyped, buf, sizeof(UserTyped));
1324  memset(Matches, 0, MatchesListsize);
1325  memset(Completed, 0, sizeof(Completed));
1326  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1327  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1329  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_str_strcasecmp);
1331 
1332  /* All matches are stored. Longest non-ambiguous string is ""
1333  * i.e. don't change 'buf'. Fake successful return this time */
1334  if (UserTyped[0] == '\0')
1335  return 1;
1336  }
1337 
1338  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1339  return 0;
1340 
1341  /* NumMatched will _always_ be at least 1 since the initial
1342  * user-typed string is always stored */
1343  if ((numtabs == 1) && (NumMatched == 2))
1344  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1345  else if ((numtabs > 1) && (NumMatched > 2))
1346  {
1347  /* cycle through all the matches */
1348  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1349  }
1350 
1351  /* return the completed label */
1352  strncpy(buf, Completed, buflen - spaces);
1353 
1354  return 1;
1355 }
1356 
1357 #ifdef USE_NOTMUCH
1358 
1369 bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
1370 {
1371  char *pt = buf;
1372  int spaces;
1373 
1374  SKIPWS(buf);
1375  spaces = buf - pt;
1376 
1377  pt = (char *) mutt_str_rstrnstr((char *) buf, pos, "tag:");
1378  if (pt)
1379  {
1380  pt += 4;
1381  if (numtabs == 1)
1382  {
1383  /* First TAB. Collect all the matches */
1385 
1386  /* All matches are stored. Longest non-ambiguous string is ""
1387  * i.e. don't change 'buf'. Fake successful return this time. */
1388  if (UserTyped[0] == '\0')
1389  return true;
1390  }
1391 
1392  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1393  return false;
1394 
1395  /* NumMatched will _always_ be at least 1 since the initial
1396  * user-typed string is always stored */
1397  if ((numtabs == 1) && (NumMatched == 2))
1398  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1399  else if ((numtabs > 1) && (NumMatched > 2))
1400  {
1401  /* cycle through all the matches */
1402  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1403  }
1404 
1405  /* return the completed query */
1406  strncpy(pt, Completed, buf + buflen - pt - spaces);
1407  }
1408  else
1409  return false;
1410 
1411  return true;
1412 }
1413 #endif
1414 
1415 #ifdef USE_NOTMUCH
1416 
1426 bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
1427 {
1428  if (!buf)
1429  return false;
1430 
1431  char *pt = buf;
1432 
1433  /* Only examine the last token */
1434  char *last_space = strrchr(buf, ' ');
1435  if (last_space)
1436  pt = (last_space + 1);
1437 
1438  /* Skip the +/- */
1439  if ((pt[0] == '+') || (pt[0] == '-'))
1440  pt++;
1441 
1442  if (numtabs == 1)
1443  {
1444  /* First TAB. Collect all the matches */
1446 
1447  /* All matches are stored. Longest non-ambiguous string is ""
1448  * i.e. don't change 'buf'. Fake successful return this time. */
1449  if (UserTyped[0] == '\0')
1450  return true;
1451  }
1452 
1453  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1454  return false;
1455 
1456  /* NumMatched will _always_ be at least 1 since the initial
1457  * user-typed string is always stored */
1458  if ((numtabs == 1) && (NumMatched == 2))
1459  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1460  else if ((numtabs > 1) && (NumMatched > 2))
1461  {
1462  /* cycle through all the matches */
1463  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1464  }
1465 
1466  /* return the completed query */
1467  strncpy(pt, Completed, buf + buflen - pt);
1468 
1469  return true;
1470 }
1471 #endif
1472 
1479 int mutt_var_value_complete(char *buf, size_t buflen, int pos)
1480 {
1481  char *pt = buf;
1482 
1483  if (buf[0] == '\0')
1484  return 0;
1485 
1486  SKIPWS(buf);
1487  const int spaces = buf - pt;
1488 
1489  pt = buf + pos - spaces;
1490  while ((pt > buf) && !isspace((unsigned char) *pt))
1491  pt--;
1492  pt++; /* move past the space */
1493  if (*pt == '=') /* abort if no var before the '=' */
1494  return 0;
1495 
1496  if (mutt_str_startswith(buf, "set", CASE_MATCH))
1497  {
1498  const char *myvarval = NULL;
1499  char var[256];
1500  mutt_str_strfcpy(var, pt, sizeof(var));
1501  /* ignore the trailing '=' when comparing */
1502  int vlen = mutt_str_strlen(var);
1503  if (vlen == 0)
1504  return 0;
1505 
1506  var[vlen - 1] = '\0';
1507 
1508  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1509  if (!he)
1510  {
1511  myvarval = myvar_get(var);
1512  if (myvarval)
1513  {
1514  struct Buffer pretty = mutt_buffer_make(256);
1515  pretty_var(myvarval, &pretty);
1516  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1517  mutt_buffer_dealloc(&pretty);
1518  return 1;
1519  }
1520  return 0; /* no such variable. */
1521  }
1522  else
1523  {
1524  struct Buffer value = mutt_buffer_make(256);
1525  struct Buffer pretty = mutt_buffer_make(256);
1526  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1527  if (CSR_RESULT(rc) == CSR_SUCCESS)
1528  {
1529  pretty_var(value.data, &pretty);
1530  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1531  mutt_buffer_dealloc(&value);
1532  mutt_buffer_dealloc(&pretty);
1533  return 0;
1534  }
1535  mutt_buffer_dealloc(&value);
1536  mutt_buffer_dealloc(&pretty);
1537  return 1;
1538  }
1539  }
1540  return 0;
1541 }
1542 
1548 struct ConfigSet *init_config(size_t size)
1549 {
1550  struct ConfigSet *cs = cs_new(size);
1551 
1552  address_init(cs);
1553  bool_init(cs);
1554  enum_init(cs);
1555  long_init(cs);
1556  mbtable_init(cs);
1557  number_init(cs);
1558  quad_init(cs);
1559  regex_init(cs);
1560  slist_init(cs);
1561  sort_init(cs);
1562  string_init(cs);
1563 
1564  if (!cs_register_variables(cs, MuttVars, 0))
1565  {
1566  mutt_error("cs_register_variables() failed");
1567  cs_free(&cs);
1568  return NULL;
1569  }
1570 
1571  return cs;
1572 }
1573 
1577 int charset_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1578  intptr_t value, struct Buffer *err)
1579 {
1580  if (value == 0)
1581  return CSR_SUCCESS;
1582 
1583  const char *str = (const char *) value;
1584 
1585  if ((strcmp(cdef->name, "charset") == 0) && strchr(str, ':'))
1586  {
1588  err, _("'charset' must contain exactly one character set name"));
1589  return CSR_ERR_INVALID;
1590  }
1591 
1592  int rc = CSR_SUCCESS;
1593  bool strict = (strcmp(cdef->name, "send_charset") == 0);
1594  char *q = NULL;
1595  char *s = mutt_str_strdup(str);
1596 
1597  for (char *p = strtok_r(s, ":", &q); p; p = strtok_r(NULL, ":", &q))
1598  {
1599  if (!*p)
1600  continue;
1601  if (!mutt_ch_check_charset(p, strict))
1602  {
1603  rc = CSR_ERR_INVALID;
1604  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, p);
1605  break;
1606  }
1607  }
1608 
1609  FREE(&s);
1610  return rc;
1611 }
1612 
1613 #ifdef USE_HCACHE
1614 
1617 int hcache_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1618  intptr_t value, struct Buffer *err)
1619 {
1620  if (value == 0)
1621  return CSR_SUCCESS;
1622 
1623  const char *str = (const char *) value;
1624 
1626  return CSR_SUCCESS;
1627 
1628  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, str);
1629  return CSR_ERR_INVALID;
1630 }
1631 #endif
1632 
1636 int pager_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1637  intptr_t value, struct Buffer *err)
1638 {
1639  if (CurrentMenu == MENU_PAGER)
1640  {
1641  mutt_buffer_printf(err, _("Option %s may not be set or reset from the pager"),
1642  cdef->name);
1643  return CSR_ERR_INVALID;
1644  }
1645 
1646  return CSR_SUCCESS;
1647 }
1648 
1652 int multipart_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1653  intptr_t value, struct Buffer *err)
1654 {
1655  if (value == 0)
1656  return CSR_SUCCESS;
1657 
1658  const char *str = (const char *) value;
1659 
1660  if ((mutt_str_strcmp(str, "inline") == 0) || (mutt_str_strcmp(str, "info") == 0))
1661  return CSR_SUCCESS;
1662 
1663  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, str);
1664  return CSR_ERR_INVALID;
1665 }
1666 
1670 int reply_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1671  intptr_t value, struct Buffer *err)
1672 {
1673  if (pager_validator(cs, cdef, value, err) != CSR_SUCCESS)
1674  return CSR_ERR_INVALID;
1675 
1676  if (!OptAttachMsg)
1677  return CSR_SUCCESS;
1678 
1679  mutt_buffer_printf(err, _("Option %s may not be set when in attach-message mode"),
1680  cdef->name);
1681  return CSR_ERR_INVALID;
1682 }
1683 
1687 int wrapheaders_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1688  intptr_t value, struct Buffer *err)
1689 {
1690  if ((value >= 78) && (value <= 998)) // Recommendation from RFC5233
1691  return CSR_SUCCESS;
1692 
1693  // L10N: This applies to the "$wrap_headers" config variable
1694  mutt_buffer_printf(err, _("Option %s must between 78 and 998 inclusive"), cdef->name);
1695  return CSR_ERR_INVALID;
1696 }
Convenience wrapper for the gui headers.
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
WHERE char * Username
User&#39;s login name.
Definition: globals.h:52
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
#define mutt_warning(...)
Definition: logging.h:82
struct ConfigSet * init_config(size_t size)
Initialise the config system.
Definition: init.c:1548
The "current" mailbox.
Definition: context.h:36
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:191
char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
Join a directory name and a filename.
Definition: path.c:348
union HashKey key
Definition: hash.h:45
Container for lots of config items.
Definition: set.h:168
void quad_init(struct ConfigSet *cs)
Register the Quad-option config type.
Definition: quad.c:192
Manage keymappings.
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Miscellaneous email parsing routines.
void bool_init(struct ConfigSet *cs)
Register the Bool config type.
Definition: bool.c:190
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
IMAP network mailbox.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define DT_LONG
a number (long)
Definition: types.h:33
intptr_t data
Data or flags to pass to the command.
Definition: mutt_commands.h:58
#define IS_PATH(x)
Definition: types.h:55
#define mutt_perror(...)
Definition: logging.h:85
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:33
void mutt_aliaslist_free(struct AliasList *a_list)
Free a List of Aliases.
Definition: alias.c:762
#define CSR_RESULT(x)
Definition: set.h:53
Config/command parsing.
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Error: Can&#39;t help the user.
Definition: mutt_commands.h:35
Structs that make up an email.
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
The "currently-open" mailbox.
struct Hash * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:38
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition: init.c:288
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:592
static int NumMatched
Definition: init.c:89
struct ListHead InlineAllow
List of inline types to counted.
Definition: mutt_parse.c:41
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:1109
int mutt_label_complete(char *buf, size_t buflen, int numtabs)
Complete a label name.
Definition: init.c:1305
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:135
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: email_globals.c:44
void mutt_list_free_type(struct ListHead *h, list_free_t fn)
Free a List of type.
Definition: list.c:145
Cursor to iterate through a Hash Table.
Definition: hash.h:96
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:450
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void number_init(struct ConfigSet *cs)
Register the Number config type.
Definition: number.c:192
command_t func
Function to parse the command.
Definition: mutt_commands.h:57
WHERE char AttachmentMarker[256]
Unique ANSI string to mark PGP messages in an email.
Definition: globals.h:46
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:82
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
HookFlags mutt_get_hook_type(const char *name)
Find a hook by name.
Definition: init.c:725
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: globals.h:82
bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1426
struct ListHead MailToAllow
List of permitted fields in a mailto: uri.
Definition: email_globals.c:47
String manipulation buffer.
Definition: buffer.h:33
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: init.c:212
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:339
WHERE struct Hash * TagFormats
Hash table of tag-formats (tag -> format string)
Definition: globals.h:60
#define _(a)
Definition: message.h:28
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:307
int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete a command name.
Definition: init.c:1135
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:664
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
Definition: charset.c:812
static char ** nm_tags
Definition: init.c:97
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
A user-callable command.
Definition: mutt_commands.h:54
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:55
const char * name
Name of the command.
Definition: mutt_commands.h:56
void sort_init(struct ConfigSet *cs)
Register the Sort config type.
Definition: sort.c:381
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
Index panel (list of emails)
Definition: keymap.h:77
A Command has been executed.
Definition: notify_type.h:33
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:997
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: email_globals.c:46
bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1369
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:166
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
uint32_t HookFlags
Flags for mutt_parse_hook(), e.g. MUTT_FOLDER_HOOK.
Definition: hook.h:43
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:357
char * name
Name of user variable.
Definition: myvar.h:33
Config item definition.
Definition: set.h:134
void enum_init(struct ConfigSet *cs)
Register the Enumeration config type.
Definition: enum.c:218
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: init.c:247
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:36
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:447
Container for Accounts, Notifications.
Definition: neomutt.h:35
const struct Command * mutt_command_get(const char *s)
Get a Command by its name.
Definition: init.c:395
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:43
Representation of a single alias to an email address.
int charset_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "charset" config variable - Implements cs_validator()
Definition: init.c:1577
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
Convenience wrapper for the config headers.
Hundreds of global variables to back the user variables.
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:355
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1071
Email Address Handling.
Assorted sorting methods.
Ask the user, defaulting to &#39;Yes&#39;.
Definition: quad.h:42
Some miscellaneous functions.
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:454
#define mutt_array_size(x)
Definition: memory.h:33
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:75
Pager pager (email viewer)
Definition: keymap.h:78
int mutt_query_variables(struct ListHead *queries)
Implement the -Q command line flag.
Definition: init.c:1058
size_t dsize
Length of data.
Definition: buffer.h:37
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:132
void mutt_hist_read_file(void)
Read the History from a file.
Definition: history.c:584
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:49
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:103
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:376
Header cache multiplexor.
struct Mailbox * mailbox
Definition: context.h:50
Many unsorted constants and some structs.
API for mailboxes.
void clear_source_stack(void)
Free memory from the stack used for the souce command.
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err)
Parse the &#39;hook&#39; family of commands - Implements command_t.
Definition: hook.c:85
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:873
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:113
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
const char * name
Definition: pgpmicalg.c:46
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:157
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:55
Convenience wrapper for the core headers.
A user-set variable.
Definition: myvar.h:31
struct MyVarList MyVars
List of all the user&#39;s custom config variables.
Definition: myvar.c:34
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
Definitions of config variables.
const char * name
name of the function
Definition: keymap.h:116
#define SKIPWS(ch)
Definition: string2.h:47
void mbtable_init(struct ConfigSet *cs)
Register the MbTable config type.
Definition: mbtable.c:293
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
static char Completed[256]
Definition: init.c:90
#define MUTT_TOKEN_NOSHELL
Don&#39;t expand environment variables.
Definition: mutt.h:85
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:54
void slist_init(struct ConfigSet *cs)
Register the Slist config type.
Definition: slist.c:267
int hcache_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "header_cache_backend" config variable - Implements cs_validator()
Definition: init.c:1617
const char * name
User-visible name.
Definition: set.h:136
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:37
int(* sort_t)(const void *a, const void *b)
typedef sort_t - Prototype for a function to compare two emails
Definition: sort.h:48
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
#define mutt_b2s(buf)
Definition: buffer.h:41
#define MUTT_TOKEN_QUOTE
Don&#39;t interpret quotes.
Definition: mutt.h:80
Prototypes for many functions.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1801
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:78
const char * line
Definition: common.c:36
struct ListHead InlineExclude
List of inline types to ignore.
Definition: mutt_parse.c:42
Notmuch virtual mailbox type.
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:746
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition: hash.h:77
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:40
static int MatchesListsize
Definition: init.c:93
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:45
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1599
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:104
Functions to parse commands in a config file.
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:426
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define DT_MAILBOX
Don&#39;t perform path expansions.
Definition: types.h:47
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
int pager_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Check for config variables that can&#39;t be set from the pager - Implements cs_validator() ...
Definition: init.c:1636
char * dptr
Current read/write position.
Definition: buffer.h:36
#define MUTT_TOKEN_SPACE
Don&#39;t treat whitespace as a term.
Definition: mutt.h:79
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: email_globals.c:50
char * data
Pointer to data.
Definition: buffer.h:35
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition: init.c:320
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
struct Hash * mutt_hash_new(size_t nelem, HashFlags flags)
Create a new Hash table (with string keys)
Definition: hash.c:275
void address_init(struct ConfigSet *cs)
Register the Address config type.
Definition: address.c:249
Definitions of NeoMutt commands.
int reply_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "reply_regex" config variable - Implements cs_validator()
Definition: init.c:1670
GUI present the user with a selectable list.
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: email_globals.c:52
void string_init(struct ConfigSet *cs)
Register the String config type.
Definition: string.c:240
int nm_get_all_tags(struct Mailbox *m, char **tag_list, int *tag_count)
Fill a list with all notmuch tags.
char * mutt_ch_get_langinfo_charset(void)
Get the user&#39;s choice of character set.
Definition: charset.c:456
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:626
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
Display version and copyright about NeoMutt.
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
bool mutt_hcache_is_valid_backend(const char *s)
Is the string a valid hcache backend.
Definition: hcache.c:496
Definition: color.h:130
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:462
void mutt_opts_free(void)
clean up before quitting
Definition: init.c:661
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:169
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:155
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:554
enum CommandResult mutt_parse_idxfmt_hook(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err)
Parse the &#39;index-format-hook&#39; command - Implements command_t.
Definition: hook.c:354
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int mutt_set_xdg_path(enum XdgType type, char *buf, size_t bufsize)
Find an XDG path or its fallback.
Definition: muttlib.c:1598
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:73
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
WHERE char ProtectedHeaderMarker[256]
Unique ANSI string to mark protected headers in an email.
Definition: globals.h:47
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
int multipart_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "show_multipart_alternative" config variable - Implements cs_validator() ...
Definition: init.c:1652
void long_init(struct ConfigSet *cs)
Register the Long config type.
Definition: long.c:173
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:391
#define MUTT_TOKEN_SEMICOLON
Don&#39;t treat ; as special.
Definition: mutt.h:83
#define IS_SPACE(ch)
Definition: string2.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:138
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:59
void mutt_colors_free(struct Colors **ptr)
Free all the colours.
Definition: color.c:355
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:578
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:80
struct ListHead AttachExclude
List of attachment types to be ignored.
Definition: mutt_parse.c:40
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:155
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
void mutt_commands_apply(void *data, void(*application)(void *, const struct Command *))
Success: Command worked.
Definition: mutt_commands.h:37
char * data
String.
Definition: list.h:35
Definitions of user functions.
WHERE bool C_Suspend
Config: Allow the user to suspend NeoMutt using &#39;^Z&#39;.
Definition: globals.h:256
Log at debug level 1.
Definition: logging.h:40
Warning: Help given to the user.
Definition: mutt_commands.h:36
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user&#39;s real name in /etc/passwd.
Definition: muttlib.c:380
static char UserTyped[1024]
Definition: init.c:87
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err)
Parse the &#39;my_hdr&#39; command - Implements command_t.
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
const char * strkey
Definition: hash.h:35
#define mutt_error(...)
Definition: logging.h:84
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:55
static const char ** Matches
Definition: init.c:91
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
Connection Library.
void regex_init(struct ConfigSet *cs)
Register the Regex config type.
Definition: regex.c:315
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1221
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:84
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: nm_db.c:304
int type
Definition: hash.h:44
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
#define FREE(x)
Definition: memory.h:40
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:111
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:44
Monitor files for changes.
#define STAILQ_EMPTY(head)
Definition: queue.h:345
int wrapheaders_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "wrap_headers" config variable - Implements cs_validator()
Definition: init.c:1687
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: email_globals.c:51
The item stored in a Hash Table.
Definition: hash.h:42
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:47
#define MUTT_TOKEN_EQUAL
Treat &#39;=&#39; as a special.
Definition: mutt.h:77
bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], int flags)
Register a set of config items.
Definition: set.c:276
List of Mailboxes.
Definition: mailbox.h:144
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:138
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:38
void mutt_attachmatch_free(struct AttachMatch **ptr)
Free an AttachMatch - Implements list_free_t.
Definition: mutt_parse.c:241
uint16_t TokenFlags
Flags for mutt_extract_token(), e.g. MUTT_TOKEN_EQUAL.
Definition: mutt.h:75
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:55
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:76
Convenience wrapper for the library headers.
void mutt_hash_free(struct Hash **ptr)
Free a hash table.
Definition: hash.c:471
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
A List node for strings.
Definition: list.h:33
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
XDG system dir: /etc/xdg.
Definition: protos.h:50
Handling of personal config (&#39;my&#39; variables)
struct ListHead AttachAllow
List of attachment types to be counted.
Definition: mutt_parse.c:39
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:602
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:81
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: email_globals.c:43
#define STAILQ_FIRST(head)
Definition: queue.h:347
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:439
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:74
struct ListHead Ignore
List of header patterns to ignore.
Definition: email_globals.c:45
Mapping between a user key and a function.
Definition: keymap.h:114
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30
int getdnsdomainname(char *buf, size_t buflen)
Lookup the host&#39;s name using DNS.
Definition: getdomain.c:45
struct Hash * label_hash
Hash table for x-labels.
Definition: mailbox.h:128
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: nm_db.c:289
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:170
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
const struct Command Commands[]
Definition: mutt_commands.c:42
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:127
struct ConfigDef MuttVars[]
Definition: mutt_config.c:87
enum CommandResult mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1001
const char * mutt_str_rstrnstr(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:961
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:76
#define MUTT_TOKEN_QUESTION
Treat &#39;?&#39; as a special.
Definition: mutt.h:86
void(* list_free_t)(void **ptr)
typedef list_free_t - Prototype for a function to free List data
Definition: list.h:44
WHERE bool C_VirtualSpoolfile
Config: (notmuch) Use the first virtual mailbox as a spool file.
Definition: globals.h:288
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:146
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: email_globals.c:49
struct ReplaceList SubjectRegexList
List of regexes to tidy the view of the email&#39;s subject.
Definition: email_globals.c:53
int mutt_var_value_complete(char *buf, size_t buflen, int pos)
Complete a variable/value.
Definition: init.c:1479