NeoMutt  2020-06-26-89-g172cd3
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 <inttypes.h>
33 #include <pwd.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/utsname.h>
40 #include <unistd.h>
41 #include "mutt/lib.h"
42 #include "address/lib.h"
43 #include "config/lib.h"
44 #include "email/lib.h"
45 #include "core/lib.h"
46 #include "alias/lib.h"
47 #include "conn/lib.h"
48 #include "gui/lib.h"
49 #include "mutt.h"
50 #include "init.h"
51 #include "command_parse.h"
52 #include "context.h"
53 #include "functions.h"
54 #include "keymap.h"
55 #include "mutt_commands.h"
56 #include "mutt_globals.h"
57 #include "mutt_menu.h"
58 #include "mutt_parse.h"
59 #include "muttlib.h"
60 #include "myvar.h"
61 #include "options.h"
62 #include "protos.h"
63 #include "sort.h"
64 #include "autocrypt/lib.h"
65 #include "compress/lib.h"
66 #include "hcache/lib.h"
67 #include "history/lib.h"
68 #include "imap/lib.h"
69 #include "maildir/lib.h"
70 #include "mbox/lib.h"
71 #include "ncrypt/lib.h"
72 #include "nntp/lib.h"
73 #include "notmuch/lib.h"
74 #include "pop/lib.h"
75 #include "send/lib.h"
76 #include "store/lib.h"
77 #ifdef USE_SIDEBAR
78 #include "sidebar/lib.h"
79 #endif
80 
81 /* Initial string that starts completion. No telling how much the user has
82  * typed so far. Allocate 1024 just to be sure! */
83 static char UserTyped[1024] = { 0 };
84 
85 static int NumMatched = 0; /* Number of matches for completion */
86 static char Completed[256] = { 0 }; /* completed string (command or variable) */
87 static const char **Matches;
88 /* this is a lie until mutt_init runs: */
89 static int MatchesListsize = 512; // Enough space for all of the config items
90 
91 #ifdef USE_NOTMUCH
92 /* List of tags found in last call to mutt_nm_query_complete(). */
93 static char **nm_tags;
94 #endif
95 
96 bool config_init_main(struct ConfigSet *cs);
97 
102 static void matches_ensure_morespace(int current)
103 {
104  if (current <= (MatchesListsize - 2))
105  return;
106 
107  int base_space = 512; // Enough space for all of the config items
108  int extra_space = MatchesListsize - base_space;
109  extra_space *= 2;
110  const int space = base_space + extra_space;
111  mutt_mem_realloc(&Matches, space * sizeof(char *));
112  memset(&Matches[current + 1], 0, space - current);
113  MatchesListsize = space;
114 }
115 
125 static void candidate(char *user, const char *src, char *dest, size_t dlen)
126 {
127  if (!dest || !user || !src)
128  return;
129 
130  if (strstr(src, user) != src)
131  return;
132 
133  matches_ensure_morespace(NumMatched);
134  Matches[NumMatched++] = src;
135  if (dest[0] == '\0')
136  mutt_str_copy(dest, src, dlen);
137  else
138  {
139  int l;
140  for (l = 0; src[l] && src[l] == dest[l]; l++)
141  ; // do nothing
142 
143  dest[l] = '\0';
144  }
145 }
146 
147 #ifdef USE_NOTMUCH
148 
154 static int complete_all_nm_tags(const char *pt)
155 {
156  int tag_count_1 = 0;
157  int tag_count_2 = 0;
158 
159  NumMatched = 0;
160  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
161  memset(Matches, 0, MatchesListsize);
162  memset(Completed, 0, sizeof(Completed));
163 
165 
166  /* Work out how many tags there are. */
167  if (nm_get_all_tags(Context->mailbox, NULL, &tag_count_1) || (tag_count_1 == 0))
168  goto done;
169 
170  /* Free the old list, if any. */
171  if (nm_tags)
172  {
173  for (int i = 0; nm_tags[i]; i++)
174  FREE(&nm_tags[i]);
175  FREE(&nm_tags);
176  }
177  /* Allocate a new list, with sentinel. */
178  nm_tags = mutt_mem_malloc((tag_count_1 + 1) * sizeof(char *));
179  nm_tags[tag_count_1] = NULL;
180 
181  /* Get all the tags. */
182  if (nm_get_all_tags(Context->mailbox, nm_tags, &tag_count_2) || (tag_count_1 != tag_count_2))
183  {
184  FREE(&nm_tags);
185  nm_tags = NULL;
187  return -1;
188  }
189 
190  /* Put them into the completion machinery. */
191  for (int num = 0; num < tag_count_1; num++)
192  {
193  candidate(UserTyped, nm_tags[num], Completed, sizeof(Completed));
194  }
195 
196  matches_ensure_morespace(NumMatched);
197  Matches[NumMatched++] = UserTyped;
198 
199 done:
201  return 0;
202 }
203 #endif
204 
211 static int execute_commands(struct ListHead *p)
212 {
213  int rc = 0;
214  struct Buffer *err = mutt_buffer_pool_get();
215 
216  struct ListNode *np = NULL;
217  STAILQ_FOREACH(np, p, entries)
218  {
219  enum CommandResult rc2 = mutt_parse_rc_line(np->data, err);
220  if (rc2 == MUTT_CMD_ERROR)
221  mutt_error(_("Error in command line: %s"), mutt_b2s(err));
222  else if (rc2 == MUTT_CMD_WARNING)
223  mutt_warning(_("Warning in command line: %s"), mutt_b2s(err));
224 
225  if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
226  {
228  return -1;
229  }
230  }
232 
233  return rc;
234 }
235 
243 static char *find_cfg(const char *home, const char *xdg_cfg_home)
244 {
245  const char *names[] = {
246  "neomuttrc",
247  "muttrc",
248  NULL,
249  };
250 
251  const char *locations[][2] = {
252  { xdg_cfg_home, "neomutt/" },
253  { xdg_cfg_home, "mutt/" },
254  { home, ".neomutt/" },
255  { home, ".mutt/" },
256  { home, "." },
257  { NULL, NULL },
258  };
259 
260  for (int i = 0; locations[i][0] || locations[i][1]; i++)
261  {
262  if (!locations[i][0])
263  continue;
264 
265  for (int j = 0; names[j]; j++)
266  {
267  char buf[256];
268 
269  snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
270  if (access(buf, F_OK) == 0)
271  return mutt_str_dup(buf);
272  }
273  }
274 
275  return NULL;
276 }
277 
278 #ifndef DOMAIN
279 
284 static char *getmailname(void)
285 {
286  char *mailname = NULL;
287  static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
288 
289  for (size_t i = 0; i < mutt_array_size(mn_files); i++)
290  {
291  FILE *fp = mutt_file_fopen(mn_files[i], "r");
292  if (!fp)
293  continue;
294 
295  size_t len = 0;
296  mailname = mutt_file_read_line(NULL, &len, fp, NULL, 0);
297  mutt_file_fclose(&fp);
298  if (mailname && *mailname)
299  break;
300 
301  FREE(&mailname);
302  }
303 
304  return mailname;
305 }
306 #endif
307 
316 static bool get_hostname(struct ConfigSet *cs)
317 {
318  char *str = NULL;
319  struct utsname utsname;
320 
321  if (C_Hostname)
322  {
323  str = C_Hostname;
324  }
325  else
326  {
327  /* The call to uname() shouldn't fail, but if it does, the system is horribly
328  * broken, and the system's networking configuration is in an unreliable
329  * state. We should bail. */
330  if ((uname(&utsname)) == -1)
331  {
332  mutt_perror(_("unable to determine nodename via uname()"));
333  return false; // TEST09: can't test
334  }
335 
336  str = utsname.nodename;
337  }
338 
339  /* some systems report the FQDN instead of just the hostname */
340  char *dot = strchr(str, '.');
341  if (dot)
342  ShortHostname = mutt_strn_dup(str, dot - str);
343  else
345 
346  if (!C_Hostname)
347  {
348  /* now get FQDN. Use configured domain first, DNS next, then uname */
349 #ifdef DOMAIN
350  /* we have a compile-time domain name, use that for C_Hostname */
352  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), DOMAIN);
353 #else
354  C_Hostname = getmailname();
355  if (!C_Hostname)
356  {
357  struct Buffer *domain = mutt_buffer_pool_get();
358  if (getdnsdomainname(domain) == 0)
359  {
360  C_Hostname =
362  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), mutt_b2s(domain));
363  }
364  else
365  {
366  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
367  * in it, we can use the nodename as the FQDN. On hosts where DNS is
368  * not being used, e.g. small network that relies on hosts files, a
369  * short host name is all that is required for SMTP to work correctly.
370  * It could be wrong, but we've done the best we can, at this point the
371  * onus is on the user to provide the correct hostname if the nodename
372  * won't work in their network. */
373  C_Hostname = mutt_str_dup(utsname.nodename);
374  }
375  mutt_buffer_pool_release(&domain);
376  }
377 #endif
378  }
379  if (C_Hostname)
380  cs_str_initial_set(cs, "hostname", C_Hostname, NULL);
381 
382  return true;
383 }
384 
391 const struct Command *mutt_command_get(const char *s)
392 {
393  for (int i = 0; Commands[i].name; i++)
394  if (mutt_str_equal(s, Commands[i].name))
395  return &Commands[i];
396  return NULL;
397 }
398 
399 #ifdef USE_LUA
400 
407 void mutt_commands_apply(void *data, void (*application)(void *, const struct Command *))
408 {
409  for (int i = 0; Commands[i].name; i++)
410  application(data, &Commands[i]);
411 }
412 #endif
413 
422 int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
423 {
424  if (!dest || !tok)
425  return -1;
426 
427  char ch;
428  char qc = '\0'; /* quote char */
429  char *pc = NULL;
430 
431  mutt_buffer_reset(dest);
432 
433  SKIPWS(tok->dptr);
434  while ((ch = *tok->dptr))
435  {
436  if (qc == '\0')
437  {
438  if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
439  ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
440  ((ch == '+') && (flags & MUTT_TOKEN_PLUS)) ||
441  ((ch == '-') && (flags & MUTT_TOKEN_MINUS)) ||
442  ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
443  ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
444  ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
445  ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
446  {
447  break;
448  }
449  }
450 
451  tok->dptr++;
452 
453  if (ch == qc)
454  qc = 0; /* end of quote */
455  else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
456  qc = ch;
457  else if ((ch == '\\') && (qc != '\''))
458  {
459  if (tok->dptr[0] == '\0')
460  return -1; /* premature end of token */
461  switch (ch = *tok->dptr++)
462  {
463  case 'c':
464  case 'C':
465  if (tok->dptr[0] == '\0')
466  return -1; /* premature end of token */
467  mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
468  tok->dptr++;
469  break;
470  case 'e':
471  mutt_buffer_addch(dest, '\033'); // Escape
472  break;
473  case 'f':
474  mutt_buffer_addch(dest, '\f');
475  break;
476  case 'n':
477  mutt_buffer_addch(dest, '\n');
478  break;
479  case 'r':
480  mutt_buffer_addch(dest, '\r');
481  break;
482  case 't':
483  mutt_buffer_addch(dest, '\t');
484  break;
485  default:
486  if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
487  isdigit((unsigned char) tok->dptr[1]))
488  {
489  mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
490  tok->dptr += 2;
491  }
492  else
493  mutt_buffer_addch(dest, ch);
494  }
495  }
496  else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
497  {
498  if (tok->dptr[0] == '\0')
499  return -1; /* premature end of token */
500  ch = *tok->dptr++;
501  if (ch == '^')
502  mutt_buffer_addch(dest, ch);
503  else if (ch == '[')
504  mutt_buffer_addch(dest, '\033'); // Escape
505  else if (isalpha((unsigned char) ch))
506  mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
507  else
508  {
509  mutt_buffer_addch(dest, '^');
510  mutt_buffer_addch(dest, ch);
511  }
512  }
513  else if ((ch == '`') && (!qc || (qc == '"')))
514  {
515  FILE *fp = NULL;
516  pid_t pid;
517 
518  pc = tok->dptr;
519  do
520  {
521  pc = strpbrk(pc, "\\`");
522  if (pc)
523  {
524  /* skip any quoted chars */
525  if (*pc == '\\')
526  pc += 2;
527  }
528  } while (pc && (pc[0] != '`'));
529  if (!pc)
530  {
531  mutt_debug(LL_DEBUG1, "mismatched backticks\n");
532  return -1;
533  }
534  struct Buffer cmd;
535  mutt_buffer_init(&cmd);
536  *pc = '\0';
537  if (flags & MUTT_TOKEN_BACKTICK_VARS)
538  {
539  /* recursively extract tokens to interpolate variables */
540  mutt_extract_token(&cmd, tok,
541  MUTT_TOKEN_QUOTE | MUTT_TOKEN_SPACE | MUTT_TOKEN_COMMENT |
543  }
544  else
545  {
546  cmd.data = mutt_str_dup(tok->dptr);
547  }
548  *pc = '`';
549  pid = filter_create(cmd.data, NULL, &fp, NULL);
550  if (pid < 0)
551  {
552  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
553  FREE(&cmd.data);
554  return -1;
555  }
556  FREE(&cmd.data);
557 
558  tok->dptr = pc + 1;
559 
560  /* read line */
561  struct Buffer expn = mutt_buffer_make(0);
562  expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, NULL, 0);
563  mutt_file_fclose(&fp);
564  filter_wait(pid);
565 
566  /* if we got output, make a new string consisting of the shell output
567  * plus whatever else was left on the original line */
568  /* BUT: If this is inside a quoted string, directly add output to
569  * the token */
570  if (expn.data)
571  {
572  if (qc)
573  {
574  mutt_buffer_addstr(dest, expn.data);
575  }
576  else
577  {
578  struct Buffer *copy = mutt_buffer_pool_get();
579  mutt_buffer_fix_dptr(&expn);
580  mutt_buffer_copy(copy, &expn);
581  mutt_buffer_addstr(copy, tok->dptr);
582  mutt_buffer_copy(tok, copy);
583  tok->dptr = tok->data;
585  }
586  FREE(&expn.data);
587  }
588  }
589  else if ((ch == '$') && (!qc || (qc == '"')) &&
590  ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
591  {
592  const char *env = NULL;
593  char *var = NULL;
594 
595  if (tok->dptr[0] == '{')
596  {
597  pc = strchr(tok->dptr, '}');
598  if (pc)
599  {
600  var = mutt_strn_dup(tok->dptr + 1, pc - (tok->dptr + 1));
601  tok->dptr = pc + 1;
602 
603  if ((flags & MUTT_TOKEN_NOSHELL))
604  {
605  mutt_buffer_addch(dest, ch);
606  mutt_buffer_addch(dest, '{');
607  mutt_buffer_addstr(dest, var);
608  mutt_buffer_addch(dest, '}');
609  FREE(&var);
610  }
611  }
612  }
613  else
614  {
615  for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
616  ; // do nothing
617 
618  var = mutt_strn_dup(tok->dptr, pc - tok->dptr);
619  tok->dptr = pc;
620  }
621  if (var)
622  {
623  struct Buffer result;
624  mutt_buffer_init(&result);
625  int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
626 
627  if (CSR_RESULT(rc) == CSR_SUCCESS)
628  {
629  mutt_buffer_addstr(dest, result.data);
630  FREE(&result.data);
631  }
632  else if ((env = myvar_get(var)))
633  {
634  mutt_buffer_addstr(dest, env);
635  }
636  else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
637  {
638  mutt_buffer_addstr(dest, env);
639  }
640  else
641  {
642  mutt_buffer_addch(dest, ch);
643  mutt_buffer_addstr(dest, var);
644  }
645  FREE(&var);
646  }
647  }
648  else
649  mutt_buffer_addch(dest, ch);
650  }
651  mutt_buffer_addch(dest, 0); /* terminate the string */
652  SKIPWS(tok->dptr);
653  return 0;
654 }
655 
659 void mutt_opts_free(void)
660 {
662 
663  alias_shutdown();
664 #ifdef USE_SIDEBAR
665  sb_shutdown();
666 #endif
667 
668  mutt_regexlist_free(&Alternates);
672  mutt_regexlist_free(&UnAlternates);
675 
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);
689  mutt_list_free(&UserHeader);
690 
691  /* Lists of AttachMatch */
693  mutt_list_free_type(&AttachExclude, (list_free_t) mutt_attachmatch_free);
694  mutt_list_free_type(&InlineAllow, (list_free_t) mutt_attachmatch_free);
695  mutt_list_free_type(&InlineExclude, (list_free_t) mutt_attachmatch_free);
696 
698 
700  FREE(&HomeDir);
701  FREE(&LastFolder);
703  FREE(&Username);
704 
707 
709 
710  mutt_hist_free();
711  mutt_keys_free();
712 
714 }
715 
722 HookFlags mutt_get_hook_type(const char *name)
723 {
724  for (const struct Command *c = Commands; c->name; c++)
725  {
726  if (((c->parse == mutt_parse_hook) || (c->parse == mutt_parse_idxfmt_hook)) &&
727  mutt_istr_equal(c->name, name))
728  {
729  return c->data;
730  }
731  }
732  return MUTT_HOOK_NO_FLAGS;
733 }
734 
743 int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
744 {
745  int need_pause = 0;
746  int rc = 1;
747  struct Buffer err = mutt_buffer_make(256);
748  struct Buffer buf = mutt_buffer_make(256);
749 
751  alias_init();
754 
755  mutt_menu_init();
756 #ifdef USE_SIDEBAR
757  sb_init();
758 #endif
759 
760  snprintf(AttachmentMarker, sizeof(AttachmentMarker), "\033]9;%" PRIu64 "\a", // Escape
761  mutt_rand64());
762 
763  snprintf(ProtectedHeaderMarker, sizeof(ProtectedHeaderMarker), "\033]8;%lld\a", // Escape
764  (long long) mutt_date_epoch());
765 
766  /* "$spoolfile" precedence: config file, environment */
767  const char *p = mutt_str_getenv("MAIL");
768  if (!p)
769  p = mutt_str_getenv("MAILDIR");
770  if (!p)
771  {
772 #ifdef HOMESPOOL
773  mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
774 #else
775  mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
776 #endif
777  p = mutt_b2s(&buf);
778  }
779  cs_str_initial_set(cs, "spoolfile", p, NULL);
780  cs_str_reset(cs, "spoolfile", NULL);
781 
782  p = mutt_str_getenv("REPLYTO");
783  if (p)
784  {
785  struct Buffer token;
786 
787  mutt_buffer_printf(&buf, "Reply-To: %s", p);
788  mutt_buffer_init(&token);
789  parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
790  FREE(&token.data);
791  }
792 
793  p = mutt_str_getenv("EMAIL");
794  if (p)
795  {
796  cs_str_initial_set(cs, "from", p, NULL);
797  cs_str_reset(cs, "from", NULL);
798  }
799 
800  /* "$mailcap_path" precedence: config file, environment, code */
801  const char *env_mc = mutt_str_getenv("MAILCAPS");
802  if (env_mc)
803  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
804 
805  /* "$tmpdir" precedence: config file, environment, code */
806  const char *env_tmp = mutt_str_getenv("TMPDIR");
807  if (env_tmp)
808  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
809 
810  /* "$visual", "$editor" precedence: config file, environment, code */
811  const char *env_ed = mutt_str_getenv("VISUAL");
812  if (!env_ed)
813  env_ed = mutt_str_getenv("EDITOR");
814  if (env_ed)
815  {
816  cs_str_string_set(cs, "editor", env_ed, NULL);
817  cs_str_string_set(cs, "visual", env_ed, NULL);
818  }
819 
821  cs_str_initial_set(cs, "charset", C_Charset, NULL);
823 
824  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
825 
827 
828 #ifdef HAVE_GETSID
829  /* Unset suspend by default if we're the session leader */
830  if (getsid(0) == getpid())
831  C_Suspend = false;
832 #endif
833 
834  /* RFC2368, "4. Unsafe headers"
835  * The creator of a mailto URL can't expect the resolver of a URL to
836  * understand more than the "subject" and "body" headers. Clients that
837  * resolve mailto URLs into mail messages should be able to correctly
838  * create RFC822-compliant mail messages using the "subject" and "body"
839  * headers. */
840  add_to_stailq(&MailToAllow, "body");
841  add_to_stailq(&MailToAllow, "subject");
842  /* Cc, In-Reply-To, and References help with not breaking threading on
843  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
844  add_to_stailq(&MailToAllow, "cc");
845  add_to_stailq(&MailToAllow, "in-reply-to");
846  add_to_stailq(&MailToAllow, "references");
847 
848  if (STAILQ_EMPTY(&Muttrc))
849  {
850  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
851 
852  if (!xdg_cfg_home && HomeDir)
853  {
854  mutt_buffer_printf(&buf, "%s/.config", HomeDir);
855  xdg_cfg_home = mutt_b2s(&buf);
856  }
857 
858  char *config = find_cfg(HomeDir, xdg_cfg_home);
859  if (config)
860  {
861  mutt_list_insert_tail(&Muttrc, config);
862  }
863  }
864  else
865  {
866  struct ListNode *np = NULL;
867  STAILQ_FOREACH(np, &Muttrc, entries)
868  {
869  mutt_buffer_strcpy(&buf, np->data);
870  FREE(&np->data);
872  np->data = mutt_buffer_strdup(&buf);
873  if (access(np->data, F_OK))
874  {
875  mutt_perror(np->data);
876  goto done; // TEST10: neomutt -F missing
877  }
878  }
879  }
880 
881  if (!STAILQ_EMPTY(&Muttrc))
882  {
883  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
884  }
885 
886  /* Process the global rc file if it exists and the user hasn't explicitly
887  * requested not to via "-n". */
888  if (!skip_sys_rc)
889  {
890  do
891  {
893  break;
894 
895  mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
896  if (access(mutt_b2s(&buf), F_OK) == 0)
897  break;
898 
899  mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
900  if (access(mutt_b2s(&buf), F_OK) == 0)
901  break;
902 
903  mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
904  if (access(mutt_b2s(&buf), F_OK) == 0)
905  break;
906 
907  mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
908  } while (false);
909 
910  if (access(mutt_b2s(&buf), F_OK) == 0)
911  {
912  if (source_rc(mutt_b2s(&buf), &err) != 0)
913  {
914  mutt_error("%s", err.data);
915  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
916  }
917  }
918  }
919 
920  /* Read the user's initialization file. */
921  struct ListNode *np = NULL;
922  STAILQ_FOREACH(np, &Muttrc, entries)
923  {
924  if (np->data)
925  {
926  if (source_rc(np->data, &err) != 0)
927  {
928  mutt_error("%s", err.data);
929  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
930  }
931  }
932  }
933 
934  if (execute_commands(commands) != 0)
935  need_pause = 1; // TEST13: neomutt -e broken
936 
937  if (!get_hostname(cs))
938  goto done;
939 
940  if (!C_Realname)
941  {
942  struct passwd *pw = getpwuid(getuid());
943  if (pw)
944  {
945  char name[256];
946  C_Realname = mutt_str_dup(mutt_gecos_name(name, sizeof(name), pw));
947  }
948  }
949  cs_str_initial_set(cs, "realname", C_Realname, NULL);
950 
951  if (need_pause && !OptNoCurses)
952  {
954  if (mutt_any_key_to_continue(NULL) == 'q')
955  goto done; // TEST14: neomutt -e broken (press 'q')
956  }
957 
958  mutt_file_mkdir(C_Tmpdir, S_IRWXU);
959 
960  mutt_hist_init();
962 
963 #ifdef USE_NOTMUCH
964  if (C_VirtualSpoolfile)
965  {
966  /* Find the first virtual folder and open it */
967  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
969  struct MailboxNode *mp = STAILQ_FIRST(&ml);
970  if (mp)
971  cs_str_string_set(cs, "spoolfile", mailbox_path(mp->mailbox), NULL);
973  }
974 #endif
975  rc = 0;
976 
977 done:
978  mutt_buffer_dealloc(&err);
979  mutt_buffer_dealloc(&buf);
980  return rc;
981 }
982 
995  struct Buffer *token, struct Buffer *err)
996 {
997  if (mutt_buffer_len(line) == 0)
998  return 0;
999 
1000  int i;
1001  enum CommandResult rc = MUTT_CMD_SUCCESS;
1002 
1003  mutt_buffer_reset(err);
1004 
1005  /* Read from the beginning of line->data */
1006  line->dptr = line->data;
1007 
1008  SKIPWS(line->dptr);
1009  while (*line->dptr)
1010  {
1011  if (*line->dptr == '#')
1012  break; /* rest of line is a comment */
1013  if (*line->dptr == ';')
1014  {
1015  line->dptr++;
1016  continue;
1017  }
1019  for (i = 0; Commands[i].name; i++)
1020  {
1021  if (mutt_str_equal(token->data, Commands[i].name))
1022  {
1023  rc = Commands[i].parse(token, line, Commands[i].data, err);
1024  if (rc != MUTT_CMD_SUCCESS)
1025  { /* -1 Error, +1 Finish */
1026  goto finish; /* Propagate return code */
1027  }
1028  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) &Commands[i]);
1029  break; /* Continue with next command */
1030  }
1031  }
1032  if (!Commands[i].name)
1033  {
1034  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1035  rc = MUTT_CMD_ERROR;
1036  break; /* Ignore the rest of the line */
1037  }
1038  }
1039 finish:
1040  return rc;
1041 }
1042 
1049 enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
1050 {
1051  if (!line || (*line == '\0'))
1052  return MUTT_CMD_ERROR;
1053 
1054  struct Buffer *line_buffer = mutt_buffer_pool_get();
1055  struct Buffer *token = mutt_buffer_pool_get();
1056 
1057  mutt_buffer_strcpy(line_buffer, line);
1058 
1059  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1060 
1061  mutt_buffer_pool_release(&line_buffer);
1062  mutt_buffer_pool_release(&token);
1063  return rc;
1064 }
1065 
1072 int mutt_query_variables(struct ListHead *queries)
1073 {
1074  struct Buffer value = mutt_buffer_make(256);
1075  struct Buffer tmp = mutt_buffer_make(256);
1076  int rc = 0;
1077 
1078  struct ListNode *np = NULL;
1079  STAILQ_FOREACH(np, queries, entries)
1080  {
1081  mutt_buffer_reset(&value);
1082 
1083  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1084  if (!he)
1085  {
1086  rc = 1;
1087  continue;
1088  }
1089 
1090  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1091  if (CSR_RESULT(rv) != CSR_SUCCESS)
1092  {
1093  rc = 1;
1094  continue;
1095  }
1096 
1097  int type = DTYPE(he->type);
1098  if (type == DT_PATH)
1099  mutt_pretty_mailbox(value.data, value.dsize);
1100 
1101  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1102  {
1103  mutt_buffer_reset(&tmp);
1104  pretty_var(value.data, &tmp);
1105  mutt_buffer_strcpy(&value, tmp.data);
1106  }
1107 
1108  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL, CS_DUMP_NO_FLAGS, stdout);
1109  }
1110 
1111  mutt_buffer_dealloc(&value);
1112  mutt_buffer_dealloc(&tmp);
1113 
1114  return rc; // TEST16: neomutt -Q charset
1115 }
1116 
1126 int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
1127 {
1128  char *pt = buf;
1129  int num;
1130  int spaces; /* keep track of the number of leading spaces on the line */
1131  struct MyVar *myv = NULL;
1132 
1133  SKIPWS(buf);
1134  spaces = buf - pt;
1135 
1136  pt = buf + pos - spaces;
1137  while ((pt > buf) && !isspace((unsigned char) *pt))
1138  pt--;
1139 
1140  if (pt == buf) /* complete cmd */
1141  {
1142  /* first TAB. Collect all the matches */
1143  if (numtabs == 1)
1144  {
1145  NumMatched = 0;
1146  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1147  memset(Matches, 0, MatchesListsize);
1148  memset(Completed, 0, sizeof(Completed));
1149  for (num = 0; Commands[num].name; num++)
1150  candidate(UserTyped, Commands[num].name, Completed, sizeof(Completed));
1151  matches_ensure_morespace(NumMatched);
1152  Matches[NumMatched++] = UserTyped;
1153 
1154  /* All matches are stored. Longest non-ambiguous string is ""
1155  * i.e. don't change 'buf'. Fake successful return this time */
1156  if (UserTyped[0] == '\0')
1157  return 1;
1158  }
1159 
1160  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1161  return 0;
1162 
1163  /* NumMatched will _always_ be at least 1 since the initial
1164  * user-typed string is always stored */
1165  if ((numtabs == 1) && (NumMatched == 2))
1166  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1167  else if ((numtabs > 1) && (NumMatched > 2))
1168  {
1169  /* cycle through all the matches */
1170  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1171  }
1172 
1173  /* return the completed command */
1174  strncpy(buf, Completed, buflen - spaces);
1175  }
1176  else if (mutt_str_startswith(buf, "set") || mutt_str_startswith(buf, "unset") ||
1177  mutt_str_startswith(buf, "reset") || mutt_str_startswith(buf, "toggle"))
1178  { /* complete variables */
1179  static const char *const prefixes[] = { "no", "inv", "?", "&", 0 };
1180 
1181  pt++;
1182  /* loop through all the possible prefixes (no, inv, ...) */
1183  if (mutt_str_startswith(buf, "set"))
1184  {
1185  for (num = 0; prefixes[num]; num++)
1186  {
1187  if (mutt_str_startswith(pt, prefixes[num]))
1188  {
1189  pt += mutt_str_len(prefixes[num]);
1190  break;
1191  }
1192  }
1193  }
1194 
1195  /* first TAB. Collect all the matches */
1196  if (numtabs == 1)
1197  {
1198  NumMatched = 0;
1199  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1200  memset(Matches, 0, MatchesListsize);
1201  memset(Completed, 0, sizeof(Completed));
1202 
1203  struct HashElem *he = NULL;
1204  struct HashElem **list = get_elem_list(NeoMutt->sub->cs);
1205  for (size_t i = 0; list[i]; i++)
1206  {
1207  he = list[i];
1208  const int type = DTYPE(he->type);
1209 
1210  if ((type == DT_SYNONYM) || (type & DT_DEPRECATED))
1211  continue;
1212 
1213  candidate(UserTyped, he->key.strkey, Completed, sizeof(Completed));
1214  }
1215  FREE(&list);
1216 
1217  TAILQ_FOREACH(myv, &MyVars, entries)
1218  {
1219  candidate(UserTyped, myv->name, Completed, sizeof(Completed));
1220  }
1221  matches_ensure_morespace(NumMatched);
1222  Matches[NumMatched++] = UserTyped;
1223 
1224  /* All matches are stored. Longest non-ambiguous string is ""
1225  * i.e. don't change 'buf'. Fake successful return this time */
1226  if (UserTyped[0] == '\0')
1227  return 1;
1228  }
1229 
1230  if ((Completed[0] == 0) && UserTyped[0])
1231  return 0;
1232 
1233  /* NumMatched will _always_ be at least 1 since the initial
1234  * user-typed string is always stored */
1235  if ((numtabs == 1) && (NumMatched == 2))
1236  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1237  else if ((numtabs > 1) && (NumMatched > 2))
1238  {
1239  /* cycle through all the matches */
1240  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1241  }
1242 
1243  strncpy(pt, Completed, buf + buflen - pt - spaces);
1244  }
1245  else if (mutt_str_startswith(buf, "exec"))
1246  {
1247  const struct Binding *menu = km_get_table(CurrentMenu);
1248 
1249  if (!menu && (CurrentMenu != MENU_PAGER))
1250  menu = OpGeneric;
1251 
1252  pt++;
1253  /* first TAB. Collect all the matches */
1254  if (numtabs == 1)
1255  {
1256  NumMatched = 0;
1257  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1258  memset(Matches, 0, MatchesListsize);
1259  memset(Completed, 0, sizeof(Completed));
1260  for (num = 0; menu[num].name; num++)
1261  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1262  /* try the generic menu */
1263  if ((Completed[0] == '\0') && (CurrentMenu != MENU_PAGER))
1264  {
1265  menu = OpGeneric;
1266  for (num = 0; menu[num].name; num++)
1267  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1268  }
1269  matches_ensure_morespace(NumMatched);
1270  Matches[NumMatched++] = UserTyped;
1271 
1272  /* All matches are stored. Longest non-ambiguous string is ""
1273  * i.e. don't change 'buf'. Fake successful return this time */
1274  if (UserTyped[0] == '\0')
1275  return 1;
1276  }
1277 
1278  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1279  return 0;
1280 
1281  /* NumMatched will _always_ be at least 1 since the initial
1282  * user-typed string is always stored */
1283  if ((numtabs == 1) && (NumMatched == 2))
1284  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1285  else if ((numtabs > 1) && (NumMatched > 2))
1286  {
1287  /* cycle through all the matches */
1288  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1289  }
1290 
1291  strncpy(pt, Completed, buf + buflen - pt - spaces);
1292  }
1293  else
1294  return 0;
1295 
1296  return 1;
1297 }
1298 
1307 int mutt_label_complete(char *buf, size_t buflen, int numtabs)
1308 {
1309  char *pt = buf;
1310  int spaces; /* keep track of the number of leading spaces on the line */
1311 
1312  if (!Context || !Context->mailbox->label_hash)
1313  return 0;
1314 
1315  SKIPWS(buf);
1316  spaces = buf - pt;
1317 
1318  /* first TAB. Collect all the matches */
1319  if (numtabs == 1)
1320  {
1321  struct HashElem *entry = NULL;
1322  struct HashWalkState state = { 0 };
1323 
1324  NumMatched = 0;
1325  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1326  memset(Matches, 0, MatchesListsize);
1327  memset(Completed, 0, sizeof(Completed));
1328  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1329  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1330  matches_ensure_morespace(NumMatched);
1331  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1332  Matches[NumMatched++] = UserTyped;
1333 
1334  /* All matches are stored. Longest non-ambiguous string is ""
1335  * i.e. don't change 'buf'. Fake successful return this time */
1336  if (UserTyped[0] == '\0')
1337  return 1;
1338  }
1339 
1340  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1341  return 0;
1342 
1343  /* NumMatched will _always_ be at least 1 since the initial
1344  * user-typed string is always stored */
1345  if ((numtabs == 1) && (NumMatched == 2))
1346  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1347  else if ((numtabs > 1) && (NumMatched > 2))
1348  {
1349  /* cycle through all the matches */
1350  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1351  }
1352 
1353  /* return the completed label */
1354  strncpy(buf, Completed, buflen - spaces);
1355 
1356  return 1;
1357 }
1358 
1359 #ifdef USE_NOTMUCH
1360 
1371 bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
1372 {
1373  char *pt = buf;
1374  int spaces;
1375 
1376  SKIPWS(buf);
1377  spaces = buf - pt;
1378 
1379  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1380  if (pt)
1381  {
1382  pt += 4;
1383  if (numtabs == 1)
1384  {
1385  /* First TAB. Collect all the matches */
1387 
1388  /* All matches are stored. Longest non-ambiguous string is ""
1389  * i.e. don't change 'buf'. Fake successful return this time. */
1390  if (UserTyped[0] == '\0')
1391  return true;
1392  }
1393 
1394  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1395  return false;
1396 
1397  /* NumMatched will _always_ be at least 1 since the initial
1398  * user-typed string is always stored */
1399  if ((numtabs == 1) && (NumMatched == 2))
1400  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1401  else if ((numtabs > 1) && (NumMatched > 2))
1402  {
1403  /* cycle through all the matches */
1404  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1405  }
1406 
1407  /* return the completed query */
1408  strncpy(pt, Completed, buf + buflen - pt - spaces);
1409  }
1410  else
1411  return false;
1412 
1413  return true;
1414 }
1415 #endif
1416 
1417 #ifdef USE_NOTMUCH
1418 
1428 bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
1429 {
1430  if (!buf)
1431  return false;
1432 
1433  char *pt = buf;
1434 
1435  /* Only examine the last token */
1436  char *last_space = strrchr(buf, ' ');
1437  if (last_space)
1438  pt = (last_space + 1);
1439 
1440  /* Skip the +/- */
1441  if ((pt[0] == '+') || (pt[0] == '-'))
1442  pt++;
1443 
1444  if (numtabs == 1)
1445  {
1446  /* First TAB. Collect all the matches */
1448 
1449  /* All matches are stored. Longest non-ambiguous string is ""
1450  * i.e. don't change 'buf'. Fake successful return this time. */
1451  if (UserTyped[0] == '\0')
1452  return true;
1453  }
1454 
1455  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1456  return false;
1457 
1458  /* NumMatched will _always_ be at least 1 since the initial
1459  * user-typed string is always stored */
1460  if ((numtabs == 1) && (NumMatched == 2))
1461  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1462  else if ((numtabs > 1) && (NumMatched > 2))
1463  {
1464  /* cycle through all the matches */
1465  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1466  }
1467 
1468  /* return the completed query */
1469  strncpy(pt, Completed, buf + buflen - pt);
1470 
1471  return true;
1472 }
1473 #endif
1474 
1481 int mutt_var_value_complete(char *buf, size_t buflen, int pos)
1482 {
1483  char *pt = buf;
1484 
1485  if (buf[0] == '\0')
1486  return 0;
1487 
1488  SKIPWS(buf);
1489  const int spaces = buf - pt;
1490 
1491  pt = buf + pos - spaces;
1492  while ((pt > buf) && !isspace((unsigned char) *pt))
1493  pt--;
1494  pt++; /* move past the space */
1495  if (*pt == '=') /* abort if no var before the '=' */
1496  return 0;
1497 
1498  if (mutt_str_startswith(buf, "set"))
1499  {
1500  const char *myvarval = NULL;
1501  char var[256];
1502  mutt_str_copy(var, pt, sizeof(var));
1503  /* ignore the trailing '=' when comparing */
1504  int vlen = mutt_str_len(var);
1505  if (vlen == 0)
1506  return 0;
1507 
1508  var[vlen - 1] = '\0';
1509 
1510  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1511  if (!he)
1512  {
1513  myvarval = myvar_get(var);
1514  if (myvarval)
1515  {
1516  struct Buffer pretty = mutt_buffer_make(256);
1517  pretty_var(myvarval, &pretty);
1518  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1519  mutt_buffer_dealloc(&pretty);
1520  return 1;
1521  }
1522  return 0; /* no such variable. */
1523  }
1524  else
1525  {
1526  struct Buffer value = mutt_buffer_make(256);
1527  struct Buffer pretty = mutt_buffer_make(256);
1528  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1529  if (CSR_RESULT(rc) == CSR_SUCCESS)
1530  {
1531  pretty_var(value.data, &pretty);
1532  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1533  mutt_buffer_dealloc(&value);
1534  mutt_buffer_dealloc(&pretty);
1535  return 0;
1536  }
1537  mutt_buffer_dealloc(&value);
1538  mutt_buffer_dealloc(&pretty);
1539  return 1;
1540  }
1541  }
1542  return 0;
1543 }
1544 
1550 struct ConfigSet *init_config(size_t size)
1551 {
1552  typedef bool (*config_init_t)(struct ConfigSet * cs);
1553 
1554  static config_init_t config_list[] = {
1560  };
1561 
1562  struct ConfigSet *cs = cs_new(size);
1563 
1564  // Define the config types
1565  address_init(cs);
1566  bool_init(cs);
1567  enum_init(cs);
1568  long_init(cs);
1569  mbtable_init(cs);
1570  number_init(cs);
1571  path_init(cs);
1572  quad_init(cs);
1573  regex_init(cs);
1574  slist_init(cs);
1575  sort_init(cs);
1576  string_init(cs);
1577 
1578  for (size_t i = 0; config_list[i]; i++)
1579  {
1580  if (!config_list[i](cs))
1581  {
1582  cs_free(&cs);
1583  return NULL;
1584  }
1585  }
1586 
1587  return cs;
1588 }
1589 
1593 int charset_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1594  intptr_t value, struct Buffer *err)
1595 {
1596  if (value == 0)
1597  return CSR_SUCCESS;
1598 
1599  const char *str = (const char *) value;
1600 
1601  if ((strcmp(cdef->name, "charset") == 0) && strchr(str, ':'))
1602  {
1604  err, _("'charset' must contain exactly one character set name"));
1605  return CSR_ERR_INVALID;
1606  }
1607 
1608  int rc = CSR_SUCCESS;
1609  bool strict = (strcmp(cdef->name, "send_charset") == 0);
1610  char *q = NULL;
1611  char *s = mutt_str_dup(str);
1612 
1613  for (char *p = strtok_r(s, ":", &q); p; p = strtok_r(NULL, ":", &q))
1614  {
1615  if (*p == '\0')
1616  continue;
1617  if (!mutt_ch_check_charset(p, strict))
1618  {
1619  rc = CSR_ERR_INVALID;
1620  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, p);
1621  break;
1622  }
1623  }
1624 
1625  FREE(&s);
1626  return rc;
1627 }
1628 
1629 #ifdef USE_HCACHE
1630 
1633 int hcache_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1634  intptr_t value, struct Buffer *err)
1635 {
1636  if (value == 0)
1637  return CSR_SUCCESS;
1638 
1639  const char *str = (const char *) value;
1640 
1641  if (store_is_valid_backend(str))
1642  return CSR_SUCCESS;
1643 
1644  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, str);
1645  return CSR_ERR_INVALID;
1646 }
1647 
1648 #ifdef USE_HCACHE_COMPRESSION
1649 
1652 int compress_method_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 (compress_get_ops(str))
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 }
1669 int compress_level_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1670  intptr_t value, struct Buffer *err)
1671 {
1673  {
1674  mutt_buffer_printf(err, _("Set option %s before setting %s"),
1675  "header_cache_compress_method", cdef->name);
1676  return CSR_ERR_INVALID;
1677  }
1678 
1680  if (!cops)
1681  {
1682  mutt_buffer_printf(err, _("Invalid value for option %s: %s"),
1683  "header_cache_compress_method", C_HeaderCacheCompressMethod);
1684  return CSR_ERR_INVALID;
1685  }
1686 
1687  if ((value < cops->min_level) || (value > cops->max_level))
1688  {
1689  // L10N: This applies to the "$header_cache_compress_level" config variable.
1690  // It shows the minimum and maximum values, e.g. 'between 1 and 22'
1691  mutt_buffer_printf(err, _("Option %s must be between %d and %d inclusive"),
1692  cdef->name, cops->min_level, cops->max_level);
1693  return CSR_ERR_INVALID;
1694  }
1695 
1696  return CSR_SUCCESS;
1697 }
1698 #endif /* USE_HCACHE_COMPRESSION */
1699 #endif /* USE_HCACHE */
1700 
1704 int pager_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1705  intptr_t value, struct Buffer *err)
1706 {
1707  if (CurrentMenu == MENU_PAGER)
1708  {
1709  mutt_buffer_printf(err, _("Option %s may not be set or reset from the pager"),
1710  cdef->name);
1711  return CSR_ERR_INVALID;
1712  }
1713 
1714  return CSR_SUCCESS;
1715 }
1716 
1720 int multipart_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1721  intptr_t value, struct Buffer *err)
1722 {
1723  if (value == 0)
1724  return CSR_SUCCESS;
1725 
1726  const char *str = (const char *) value;
1727 
1728  if (mutt_str_equal(str, "inline") || mutt_str_equal(str, "info"))
1729  return CSR_SUCCESS;
1730 
1731  mutt_buffer_printf(err, _("Invalid value for option %s: %s"), cdef->name, str);
1732  return CSR_ERR_INVALID;
1733 }
1734 
1738 int reply_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
1739  intptr_t value, struct Buffer *err)
1740 {
1741  if (pager_validator(cs, cdef, value, err) != CSR_SUCCESS)
1742  return CSR_ERR_INVALID;
1743 
1744  if (!OptAttachMsg)
1745  return CSR_SUCCESS;
1746 
1747  mutt_buffer_printf(err, _("Option %s may not be set when in attach-message mode"),
1748  cdef->name);
1749  return CSR_ERR_INVALID;
1750 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
Convenience wrapper for the gui headers.
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:585
#define mutt_warning(...)
Definition: logging.h:82
struct ConfigSet * init_config(size_t size)
Initialise the config system.
Definition: init.c:1550
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:196
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:52
union HashKey key
Key representing the data.
Definition: hash.h:46
bool config_init_mbox(struct ConfigSet *cs)
Register mbox config variables.
Definition: config.c:48
Container for lots of config items.
Definition: set.h:227
void quad_init(struct ConfigSet *cs)
Register the Quad-option config type.
Definition: quad.c:184
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:182
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
#define mutt_perror(...)
Definition: logging.h:85
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:33
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:64
#define CSR_RESULT(x)
Definition: set.h:52
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
struct ReplaceList SubjectRegexList
List of regexes to tidy the view of the email&#39;s subject.
Definition: globals.c:53
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.
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:81
Autocrypt end-to-end encryption.
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition: init.c:284
Convenience wrapper for the send headers.
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:597
static int NumMatched
Definition: init.c:85
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
struct ListHead InlineAllow
List of inline types to counted.
Definition: mutt_parse.c:40
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;hook&#39; family of commands - Implements Command::parse()
Definition: hook.c:85
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
int mutt_label_complete(char *buf, size_t buflen, int numtabs)
Complete a label name.
Definition: init.c:1307
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
bool config_init_imap(struct ConfigSet *cs)
Register imap config variables.
Definition: config.c:93
void mutt_list_free_type(struct ListHead *h, list_free_t fn)
Free a List of type.
Definition: list.c:144
Cursor to iterate through a Hash Table.
Definition: hash.h:119
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:258
bool config_init_send(struct ConfigSet *cs)
Register send config variables.
Definition: config.c:226
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:76
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
HookFlags mutt_get_hook_type(const char *name)
Find a hook by name.
Definition: init.c:722
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:49
bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1428
bool config_init_conn(struct ConfigSet *cs)
Register conn config variables.
Definition: config.c:123
String manipulation buffer.
Definition: buffer.h:33
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: init.c:211
short max_level
Maximum compression level.
Definition: lib.h:59
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1049
WHERE char * C_Realname
Config: Real name of the user.
Definition: mutt_globals.h:108
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:341
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:651
#define _(a)
Definition: message.h:28
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:307
bool config_init_autocrypt(struct ConfigSet *cs)
Register autocrypt config variables.
Definition: config.c:59
int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete a command name.
Definition: init.c:1126
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:50
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:667
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
Definition: charset.c:818
static char ** nm_tags
Definition: init.c:93
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
A user-callable command.
Definition: mutt_commands.h:44
const char * name
Name of the command.
Definition: mutt_commands.h:46
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: mutt_globals.h:94
void sort_init(struct ConfigSet *cs)
Register the Sort config type.
Definition: sort.c:369
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:289
int compress_level_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "header_cache_compress_level" config variable - Implements ConfigDef::validator() ...
Definition: init.c:1669
Index panel (list of emails)
Definition: keymap.h:78
A Command has been executed, Command.
Definition: notify_type.h:35
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:1003
bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1371
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:168
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:63
bool config_init_nntp(struct ConfigSet *cs)
Register nntp config variables.
Definition: config.c:86
void enum_init(struct ConfigSet *cs)
Register the Enumeration config type.
Definition: enum.c:190
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: init.c:243
bool config_init_pop(struct ConfigSet *cs)
Register pop config variables.
Definition: config.c:67
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:446
Container for Accounts, Notifications.
Definition: neomutt.h:36
const struct Command * mutt_command_get(const char *s)
Get a Command by its name.
Definition: init.c:391
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
int charset_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "charset" config variable - Implements ConfigDef::validator()
Definition: init.c:1593
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
Convenience wrapper for the config headers.
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Function to parse a command.
Definition: mutt_commands.h:56
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:357
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:50
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:996
Email Address Handling.
Assorted sorting methods.
WHERE char ProtectedHeaderMarker[256]
Unique ANSI string to mark protected headers in an email.
Definition: mutt_globals.h:48
API for the header cache compression.
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:53
bool config_init_hcache(struct ConfigSet *cs)
Register hcache config variables.
Definition: config.c:73
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:460
#define mutt_array_size(x)
Definition: memory.h:33
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:98
Pager pager (email viewer)
Definition: keymap.h:79
int mutt_query_variables(struct ListHead *queries)
Implement the -Q command line flag.
Definition: init.c:1072
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_hist_read_file(void)
Read the History from a file.
Definition: history.c:568
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: mutt_globals.h:78
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
Header cache multiplexor.
struct Mailbox * mailbox
Definition: context.h:50
Many unsorted constants and some structs.
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:553
void clear_source_stack(void)
Free memory from the stack used for the souce command.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:875
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
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
const char * name
name of the function
Definition: keymap.h:120
#define SKIPWS(ch)
Definition: string2.h:46
void mbtable_init(struct ConfigSet *cs)
Register the MbTable config type.
Definition: mbtable.c:281
bool config_init_maildir(struct ConfigSet *cs)
Register maildir config variables.
Definition: config.c:61
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:86
#define MUTT_TOKEN_NOSHELL
Don&#39;t expand environment variables.
Definition: mutt.h:79
void slist_init(struct ConfigSet *cs)
Register the Slist config type.
Definition: slist.c:238
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 ConfigDef::validator() ...
Definition: init.c:1633
bool config_init_main(struct ConfigSet *cs)
Register main config variables.
Definition: mutt_config.c:305
const char * name
User-visible name.
Definition: set.h:65
Email Aliases.
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:661
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:45
Usenet network mailbox type; talk to an NNTP server.
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:35
int(* sort_t)(const void *a, const void *b)
Prototype for a function to compare two emails.
Definition: sort.h:48
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
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:64
#define mutt_b2s(buf)
Definition: buffer.h:41
Read/write command history from/to a file.
#define MUTT_TOKEN_QUOTE
Don&#39;t interpret quotes.
Definition: mutt.h:74
Prototypes for many functions.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1700
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:72
struct ListHead InlineExclude
List of inline types to ignore.
Definition: mutt_parse.c:41
Notmuch virtual mailbox type.
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:743
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:165
WHERE bool C_Suspend
Config: Allow the user to suspend NeoMutt using &#39;^Z&#39;.
Definition: mutt_globals.h:167
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:38
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:43
static int MatchesListsize
Definition: init.c:89
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:1644
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:102
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:128
Functions to parse commands in a config file.
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:422
WHERE char AttachmentMarker[256]
Unique ANSI string to mark PGP messages in an email.
Definition: mutt_globals.h:47
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:79
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#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 ConfigDef::validator() ...
Definition: init.c:1704
char * dptr
Current read/write position.
Definition: buffer.h:36
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:51
#define MUTT_TOKEN_SPACE
Don&#39;t treat whitespace as a term.
Definition: mutt.h:73
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:47
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:316
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:304
POP network mailbox.
void address_init(struct ConfigSet *cs)
Register the Address config type.
Definition: address.c:236
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 ConfigDef::validator()
Definition: init.c:1738
GUI present the user with a selectable list.
API for encryption/signing of emails.
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:38
void string_init(struct ConfigSet *cs)
Register the String config type.
Definition: string.c:226
int nm_get_all_tags(struct Mailbox *m, char **tag_list, int *tag_count)
Fill a list with all notmuch tags.
Definition: notmuch.c:2066
char * mutt_ch_get_langinfo_charset(void)
Get the user&#39;s choice of character set.
Definition: charset.c:462
#define MUTT_TOKEN_PLUS
Treat &#39;+&#39; as a special.
Definition: mutt.h:81
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:994
bool config_init_ncrypt(struct ConfigSet *cs)
Register ncrypt config variables.
Definition: config.c:220
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:522
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
Definition: color.h:129
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:447
void mutt_opts_free(void)
clean up before quitting
Definition: init.c:659
Maildir local mailbox type.
bool config_init_notmuch(struct ConfigSet *cs)
Register notmuch config variables.
Definition: config.c:79
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:56
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:172
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:158
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
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:54
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 ConfigDef::validator() ...
Definition: init.c:1720
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition: muttlib.c:1499
void long_init(struct ConfigSet *cs)
Register the Long config type.
Definition: long.c:239
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:395
#define MUTT_TOKEN_SEMICOLON
Don&#39;t treat ; as special.
Definition: mutt.h:77
#define IS_SPACE(ch)
Definition: string2.h:38
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:602
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:44
struct ListHead AttachExclude
List of attachment types to be ignored.
Definition: mutt_parse.c:39
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:154
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
Key value store.
Success: Command worked.
Definition: mutt_commands.h:37
char * data
String.
Definition: list.h:36
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
Definitions of user functions.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:46
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:362
static char UserTyped[1024]
Definition: init.c:83
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:721
Header Cache Compression API.
Definition: lib.h:55
const char * strkey
String key.
Definition: hash.h:36
#define mutt_error(...)
Definition: logging.h:84
int compress_method_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "header_cache_compress_method" config variable - Implements ConfigDef::validator() ...
Definition: init.c:1652
#define MUTT_TOKEN_MINUS
Treat &#39;-&#39; as a special.
Definition: mutt.h:82
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
static const char ** Matches
Definition: init.c:87
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:55
Connection Library.
void regex_init(struct ConfigSet *cs)
Register the Regex config type.
Definition: regex.c:302
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:51
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1265
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:78
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#define FREE(x)
Definition: memory.h:40
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;my_hdr&#39; command - Implements Command::parse()
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:374
bool store_is_valid_backend(const char *str)
Is the string a valid Store backend.
Definition: store.c:129
enum CommandResult mutt_parse_idxfmt_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;index-format-hook&#39; command - Implements Command::parse()
Definition: hook.c:351
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:44
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash Table.
Definition: hash.c:479
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
The item stored in a Hash Table.
Definition: hash.h:43
#define MUTT_TOKEN_EQUAL
Treat &#39;=&#39; as a special.
Definition: mutt.h:71
short min_level
Minimum compression level.
Definition: lib.h:58
List of Mailboxes.
Definition: mailbox.h:145
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_attachmatch_free(struct AttachMatch **ptr)
Free an AttachMatch - Implements list_free_t.
Definition: mutt_parse.c:240
uint16_t TokenFlags
Flags for mutt_extract_token(), e.g. MUTT_TOKEN_EQUAL.
Definition: mutt.h:69
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:55
int getdnsdomainname(struct Buffer *domain)
Lookup the host&#39;s name using DNS.
Definition: getdomain.c:44
const char * mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:925
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
int const char int line
Definition: acutest.h:617
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:60
A List node for strings.
Definition: list.h:34
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:48
Handling of personal config (&#39;my&#39; variables)
struct ListHead AttachAllow
List of attachment types to be counted.
Definition: mutt_parse.c:38
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:75
#define STAILQ_FIRST(head)
Definition: queue.h:347
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:424
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:97
Mapping between a user key and a function.
Definition: keymap.h:118
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30
bool config_init_history(struct ConfigSet *cs)
Register history config variables.
Definition: config.c:55
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:169
const struct Command Commands[]
Definition: mutt_commands.c:50
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:125
bool C_VirtualSpoolfile
Config: (notmuch) Use the first virtual mailbox as a spool file.
Definition: config.c:50
void path_init(struct ConfigSet *cs)
Register the Path config type.
Definition: path.c:248
void mutt_commands_apply(void *data, void(*application)(void *, const struct Command *))
Run a callback function on every Command.
Definition: init.c:407
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
#define MUTT_TOKEN_QUESTION
Treat &#39;?&#39; as a special.
Definition: mutt.h:80
void(* list_free_t)(void **ptr)
Prototype for a function to free List data.
Definition: list.h:45
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:147
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:137
int mutt_var_value_complete(char *buf, size_t buflen, int pos)
Complete a variable/value.
Definition: init.c:1481