NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
command_parse.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <assert.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include "mutt/lib.h"
40 #include "address/lib.h"
41 #include "config/lib.h"
42 #include "email/lib.h"
43 #include "core/lib.h"
44 #include "gui/lib.h"
45 #include "mutt.h"
46 #include "command_parse.h"
47 #include "imap/lib.h"
48 #include "menu/lib.h"
49 #include "init.h"
50 #include "keymap.h"
51 #include "monitor.h"
52 #include "mutt_commands.h"
53 #include "mutt_globals.h"
54 #include "muttlib.h"
55 #include "mx.h"
56 #include "myvar.h"
57 #include "options.h"
58 #include "version.h"
59 #ifdef ENABLE_NLS
60 #include <libintl.h>
61 #endif
62 
63 /* LIFO designed to contain the list of config files that have been sourced and
64  * avoid cyclic sourcing */
66 
67 #define MAX_ERRS 128
68 
73 {
77 };
78 
85 static bool is_function(const char *name)
86 {
87  for (size_t i = 0; MenuNames[i].name; i++)
88  {
89  const struct Binding *b = km_get_table(MenuNames[i].value);
90  if (!b)
91  continue;
92 
93  for (int j = 0; b[j].name; j++)
94  if (mutt_str_equal(name, b[j].name))
95  return true;
96  }
97  return false;
98 }
99 
109 int parse_grouplist(struct GroupList *gl, struct Buffer *buf, struct Buffer *s,
110  struct Buffer *err)
111 {
112  while (mutt_istr_equal(buf->data, "-group"))
113  {
114  if (!MoreArgs(s))
115  {
116  mutt_buffer_strcpy(err, _("-group: no group name"));
117  return -1;
118  }
119 
121 
123 
124  if (!MoreArgs(s))
125  {
126  mutt_buffer_strcpy(err, _("out of arguments"));
127  return -1;
128  }
129 
131  }
132 
133  return 0;
134 }
135 
142 int source_rc(const char *rcfile_path, struct Buffer *err)
143 {
144  int lineno = 0, rc = 0, warnings = 0;
145  enum CommandResult line_rc;
146  struct Buffer *token = NULL, *linebuf = NULL;
147  char *line = NULL;
148  char *currentline = NULL;
149  char rcfile[PATH_MAX];
150  size_t linelen = 0;
151  pid_t pid;
152 
153  mutt_str_copy(rcfile, rcfile_path, sizeof(rcfile));
154 
155  size_t rcfilelen = mutt_str_len(rcfile);
156  if (rcfilelen == 0)
157  return -1;
158 
159  bool ispipe = rcfile[rcfilelen - 1] == '|';
160 
161  if (!ispipe)
162  {
163  struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
164  if (!mutt_path_to_absolute(rcfile, np ? NONULL(np->data) : ""))
165  {
166  mutt_error(_("Error: Can't build path of '%s'"), rcfile_path);
167  return -1;
168  }
169 
170  STAILQ_FOREACH(np, &MuttrcStack, entries)
171  {
172  if (mutt_str_equal(np->data, rcfile))
173  {
174  break;
175  }
176  }
177  if (np)
178  {
179  mutt_error(_("Error: Cyclic sourcing of configuration file '%s'"), rcfile);
180  return -1;
181  }
182 
184  }
185 
186  mutt_debug(LL_DEBUG2, "Reading configuration file '%s'\n", rcfile);
187 
188  FILE *fp = mutt_open_read(rcfile, &pid);
189  if (!fp)
190  {
191  mutt_buffer_printf(err, "%s: %s", rcfile, strerror(errno));
192  return -1;
193  }
194 
195  token = mutt_buffer_pool_get();
196  linebuf = mutt_buffer_pool_get();
197 
198  while ((line = mutt_file_read_line(line, &linelen, fp, &lineno, MUTT_RL_CONT)) != NULL)
199  {
200  const char *const c_config_charset =
201  cs_subset_string(NeoMutt->sub, "config_charset");
202  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
203  const bool conv = c_config_charset && c_charset;
204  if (conv)
205  {
206  currentline = mutt_str_dup(line);
207  if (!currentline)
208  continue;
209  mutt_ch_convert_string(&currentline, c_config_charset, c_charset, MUTT_ICONV_NO_FLAGS);
210  }
211  else
212  currentline = line;
213 
214  mutt_buffer_strcpy(linebuf, currentline);
215 
216  mutt_buffer_reset(err);
217  line_rc = mutt_parse_rc_buffer(linebuf, token, err);
218  if (line_rc == MUTT_CMD_ERROR)
219  {
220  mutt_error(_("Error in %s, line %d: %s"), rcfile, lineno, err->data);
221  if (--rc < -MAX_ERRS)
222  {
223  if (conv)
224  FREE(&currentline);
225  break;
226  }
227  }
228  else if (line_rc == MUTT_CMD_WARNING)
229  {
230  /* Warning */
231  mutt_warning(_("Warning in %s, line %d: %s"), rcfile, lineno, err->data);
232  warnings++;
233  }
234  else if (line_rc == MUTT_CMD_FINISH)
235  {
236  break; /* Found "finish" command */
237  }
238  else
239  {
240  if (rc < 0)
241  rc = -1;
242  }
243  if (conv)
244  FREE(&currentline);
245  }
246 
247  FREE(&line);
248  mutt_file_fclose(&fp);
249  if (pid != -1)
250  filter_wait(pid);
251 
252  if (rc)
253  {
254  /* the neomuttrc source keyword */
255  mutt_buffer_reset(err);
256  mutt_buffer_printf(err, (rc >= -MAX_ERRS) ? _("source: errors in %s") : _("source: reading aborted due to too many errors in %s"),
257  rcfile);
258  rc = -1;
259  }
260  else
261  {
262  /* Don't alias errors with warnings */
263  if (warnings > 0)
264  {
265  mutt_buffer_printf(err, ngettext("source: %d warning in %s", "source: %d warnings in %s", warnings),
266  warnings, rcfile);
267  rc = -2;
268  }
269  }
270 
271  if (!ispipe && !STAILQ_EMPTY(&MuttrcStack))
272  {
273  struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
274  STAILQ_REMOVE_HEAD(&MuttrcStack, entries);
275  FREE(&np->data);
276  FREE(&np);
277  }
278 
279  mutt_buffer_pool_release(&token);
280  mutt_buffer_pool_release(&linebuf);
281  return rc;
282 }
283 
287 enum CommandResult parse_cd(struct Buffer *buf, struct Buffer *s, intptr_t data,
288  struct Buffer *err)
289 {
292  if (mutt_buffer_len(buf) == 0)
293  {
294  if (HomeDir)
296  else
297  {
298  mutt_buffer_printf(err, _("%s: too few arguments"), "cd");
299  return MUTT_CMD_ERROR;
300  }
301  }
302 
303  if (chdir(mutt_buffer_string(buf)) != 0)
304  {
305  mutt_buffer_printf(err, "cd: %s", strerror(errno));
306  return MUTT_CMD_ERROR;
307  }
308 
309  return MUTT_CMD_SUCCESS;
310 }
311 
315 enum CommandResult parse_echo(struct Buffer *buf, struct Buffer *s,
316  intptr_t data, struct Buffer *err)
317 {
318  if (!MoreArgs(s))
319  {
320  mutt_buffer_printf(err, _("%s: too few arguments"), "echo");
321  return MUTT_CMD_WARNING;
322  }
324  OptForceRefresh = true;
325  mutt_message("%s", buf->data);
326  OptForceRefresh = false;
327  mutt_sleep(0);
328 
329  return MUTT_CMD_SUCCESS;
330 }
331 
339 enum CommandResult parse_finish(struct Buffer *buf, struct Buffer *s,
340  intptr_t data, struct Buffer *err)
341 {
342  if (MoreArgs(s))
343  {
344  mutt_buffer_printf(err, _("%s: too many arguments"), "finish");
345  return MUTT_CMD_WARNING;
346  }
347 
348  return MUTT_CMD_FINISH;
349 }
350 
354 enum CommandResult parse_group(struct Buffer *buf, struct Buffer *s,
355  intptr_t data, struct Buffer *err)
356 {
357  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
358  enum GroupState state = GS_NONE;
359 
360  do
361  {
363  if (parse_grouplist(&gl, buf, s, err) == -1)
364  goto bail;
365 
366  if ((data == MUTT_UNGROUP) && mutt_istr_equal(buf->data, "*"))
367  {
369  goto out;
370  }
371 
372  if (mutt_istr_equal(buf->data, "-rx"))
373  state = GS_RX;
374  else if (mutt_istr_equal(buf->data, "-addr"))
375  state = GS_ADDR;
376  else
377  {
378  switch (state)
379  {
380  case GS_NONE:
381  mutt_buffer_printf(err, _("%sgroup: missing -rx or -addr"),
382  (data == MUTT_UNGROUP) ? "un" : "");
383  goto warn;
384 
385  case GS_RX:
386  if ((data == MUTT_GROUP) &&
387  (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0))
388  {
389  goto bail;
390  }
391  else if ((data == MUTT_UNGROUP) &&
392  (mutt_grouplist_remove_regex(&gl, buf->data) < 0))
393  {
394  goto bail;
395  }
396  break;
397 
398  case GS_ADDR:
399  {
400  char *estr = NULL;
401  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
402  mutt_addrlist_parse2(&al, buf->data);
403  if (TAILQ_EMPTY(&al))
404  goto bail;
405  if (mutt_addrlist_to_intl(&al, &estr))
406  {
407  mutt_buffer_printf(err, _("%sgroup: warning: bad IDN '%s'"),
408  (data == 1) ? "un" : "", estr);
409  mutt_addrlist_clear(&al);
410  FREE(&estr);
411  goto bail;
412  }
413  if (data == MUTT_GROUP)
414  mutt_grouplist_add_addrlist(&gl, &al);
415  else if (data == MUTT_UNGROUP)
417  mutt_addrlist_clear(&al);
418  break;
419  }
420  }
421  }
422  } while (MoreArgs(s));
423 
424 out:
426  return MUTT_CMD_SUCCESS;
427 
428 bail:
430  return MUTT_CMD_ERROR;
431 
432 warn:
434  return MUTT_CMD_WARNING;
435 }
436 
450 enum CommandResult parse_ifdef(struct Buffer *buf, struct Buffer *s,
451  intptr_t data, struct Buffer *err)
452 {
454 
455  // is the item defined as:
456  bool res = cs_subset_lookup(NeoMutt->sub, buf->data) // a variable?
457  || feature_enabled(buf->data) // a compiled-in feature?
458  || is_function(buf->data) // a function?
459  || mutt_command_get(buf->data) // a command?
460  || myvar_get(buf->data) // a my_ variable?
461  || mutt_str_getenv(buf->data); // an environment variable?
462 
463  if (!MoreArgs(s))
464  {
465  mutt_buffer_printf(err, _("%s: too few arguments"), (data ? "ifndef" : "ifdef"));
466  return MUTT_CMD_WARNING;
467  }
469 
470  /* ifdef KNOWN_SYMBOL or ifndef UNKNOWN_SYMBOL */
471  if ((res && (data == 0)) || (!res && (data == 1)))
472  {
473  enum CommandResult rc = mutt_parse_rc_line(buf->data, err);
474  if (rc == MUTT_CMD_ERROR)
475  {
476  mutt_error(_("Error: %s"), err->data);
477  return MUTT_CMD_ERROR;
478  }
479  return rc;
480  }
481  return MUTT_CMD_SUCCESS;
482 }
483 
487 enum CommandResult parse_ignore(struct Buffer *buf, struct Buffer *s,
488  intptr_t data, struct Buffer *err)
489 {
490  do
491  {
494  add_to_stailq(&Ignore, buf->data);
495  } while (MoreArgs(s));
496 
497  return MUTT_CMD_SUCCESS;
498 }
499 
503 enum CommandResult parse_lists(struct Buffer *buf, struct Buffer *s,
504  intptr_t data, struct Buffer *err)
505 {
506  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
507 
508  do
509  {
511 
512  if (parse_grouplist(&gl, buf, s, err) == -1)
513  goto bail;
514 
516 
517  if (mutt_regexlist_add(&MailLists, buf->data, REG_ICASE, err) != 0)
518  goto bail;
519 
520  if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
521  goto bail;
522  } while (MoreArgs(s));
523 
525  return MUTT_CMD_SUCCESS;
526 
527 bail:
529  return MUTT_CMD_ERROR;
530 }
531 
537 enum CommandResult parse_mailboxes(struct Buffer *buf, struct Buffer *s,
538  intptr_t data, struct Buffer *err)
539 {
540  while (MoreArgs(s))
541  {
542  struct Mailbox *m = mailbox_new();
543 
544  if (data & MUTT_NAMED)
545  {
546  // This may be empty, e.g. `named-mailboxes "" +inbox`
548  m->name = mutt_buffer_strdup(buf);
549  }
550 
552  if (mutt_buffer_is_empty(buf))
553  {
554  /* Skip empty tokens. */
555  mailbox_free(&m);
556  continue;
557  }
558 
559  mutt_buffer_strcpy(&m->pathbuf, buf->data);
560  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
561  /* int rc = */ mx_path_canon2(m, c_folder);
562 
563  if (m->type <= MUTT_UNKNOWN)
564  {
565  mutt_error("Unknown Mailbox: %s", m->realpath);
566  mailbox_free(&m);
567  return MUTT_CMD_ERROR;
568  }
569 
570  bool new_account = false;
571  struct Account *a = mx_ac_find(m);
572  if (!a)
573  {
574  a = account_new(NULL, NeoMutt->sub);
575  a->type = m->type;
576  new_account = true;
577  }
578 
579  if (!new_account)
580  {
581  struct Mailbox *m_old = mx_mbox_find(a, m->realpath);
582  if (m_old)
583  {
584  const bool show = (m_old->flags == MB_HIDDEN);
585  if (show)
586  {
587  m_old->flags = MB_NORMAL;
588  m_old->gen = mailbox_gen();
589  }
590 
591  const bool rename = (data & MUTT_NAMED) && !mutt_str_equal(m_old->name, m->name);
592  if (rename)
593  {
594  mutt_str_replace(&m_old->name, m->name);
595  }
596 
597  mailbox_free(&m);
598  continue;
599  }
600  }
601 
602  if (!mx_ac_add(a, m))
603  {
604  //error
605  mailbox_free(&m);
606  if (new_account)
607  {
608  cs_subset_free(&a->sub);
609  FREE(&a->name);
610  notify_free(&a->notify);
611  FREE(&a);
612  }
613  continue;
614  }
615  if (new_account)
616  {
618  }
619 
620 #ifdef USE_INOTIFY
621  mutt_monitor_add(m);
622 #endif
623  }
624  return MUTT_CMD_SUCCESS;
625 }
626 
630 enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s,
631  intptr_t data, struct Buffer *err)
632 {
634  char *p = strpbrk(buf->data, ": \t");
635  if (!p || (*p != ':'))
636  {
637  mutt_buffer_strcpy(err, _("invalid header field"));
638  return MUTT_CMD_WARNING;
639  }
640 
641  struct EventHeader ev_h = { buf->data };
642  struct ListNode *n = header_find(&UserHeader, buf->data);
643 
644  if (n)
645  {
646  header_update(n, buf->data);
647  mutt_debug(LL_NOTIFY, "NT_HEADER_CHANGE: %s\n", buf->data);
649  }
650  else
651  {
652  header_add(&UserHeader, buf->data);
653  mutt_debug(LL_NOTIFY, "NT_HEADER_ADD: %s\n", buf->data);
655  }
656 
657  return MUTT_CMD_SUCCESS;
658 }
659 
665 enum CommandResult parse_set(struct Buffer *buf, struct Buffer *s,
666  intptr_t data, struct Buffer *err)
667 {
668  /* The order must match `enum MuttSetCommand` */
669  static const char *set_commands[] = { "set", "toggle", "unset", "reset" };
670 
671  int rc = 0;
672 
673  while (MoreArgs(s))
674  {
675  bool prefix = false;
676  bool query = false;
677  bool inv = (data == MUTT_SET_INV);
678  bool reset = (data == MUTT_SET_RESET);
679  bool unset = (data == MUTT_SET_UNSET);
680 
681  if (*s->dptr == '?')
682  {
683  prefix = true;
684  query = true;
685  s->dptr++;
686  }
687  else if (mutt_str_startswith(s->dptr, "no"))
688  {
689  prefix = true;
690  unset = !unset;
691  s->dptr += 2;
692  }
693  else if (mutt_str_startswith(s->dptr, "inv"))
694  {
695  prefix = true;
696  inv = !inv;
697  s->dptr += 3;
698  }
699  else if (*s->dptr == '&')
700  {
701  prefix = true;
702  reset = true;
703  s->dptr++;
704  }
705 
706  if (prefix && (data != MUTT_SET_SET))
707  {
708  mutt_buffer_printf(err, _("Can't use 'inv', 'no', '&' or '?' with the '%s' command"),
709  set_commands[data]);
710  return MUTT_CMD_WARNING;
711  }
712 
713  /* get the variable name */
715 
716  bool bq = false;
717  bool equals = false;
718  bool increment = false;
719  bool decrement = false;
720 
721  struct HashElem *he = NULL;
722  bool my = mutt_str_startswith(buf->data, "my_");
723  if (!my)
724  {
725  he = cs_subset_lookup(NeoMutt->sub, buf->data);
726  if (!he)
727  {
728  if (reset && mutt_str_equal(buf->data, "all"))
729  {
730  struct HashElem **list = get_elem_list(NeoMutt->sub->cs);
731  if (!list)
732  return MUTT_CMD_ERROR;
733 
734  for (size_t i = 0; list[i]; i++)
735  cs_subset_he_reset(NeoMutt->sub, list[i], NULL);
736 
737  FREE(&list);
738  break;
739  }
740  else
741  {
742  mutt_buffer_printf(err, _("%s: unknown variable"), buf->data);
743  return MUTT_CMD_ERROR;
744  }
745  }
746 
747  // Use the correct name if a synonym is used
748  mutt_buffer_strcpy(buf, he->key.strkey);
749 
750  bq = ((DTYPE(he->type) == DT_BOOL) || (DTYPE(he->type) == DT_QUAD));
751  }
752 
753  if (*s->dptr == '?')
754  {
755  if (prefix)
756  {
757  mutt_buffer_printf(err,
758  _("Can't use a prefix when querying a variable"));
759  return MUTT_CMD_WARNING;
760  }
761 
762  if (reset || unset || inv)
763  {
764  mutt_buffer_printf(err, _("Can't query a variable with the '%s' command"),
765  set_commands[data]);
766  return MUTT_CMD_WARNING;
767  }
768 
769  query = true;
770  s->dptr++;
771  }
772  else if (*s->dptr == '+' || *s->dptr == '-')
773  {
774  if (prefix)
775  {
777  err,
778  _("Can't use prefix when incrementing or decrementing a variable"));
779  return MUTT_CMD_WARNING;
780  }
781 
782  if (reset || unset || inv)
783  {
784  mutt_buffer_printf(err, _("Can't set a variable with the '%s' command"),
785  set_commands[data]);
786  return MUTT_CMD_WARNING;
787  }
788  if (*s->dptr == '+')
789  increment = true;
790  else
791  decrement = true;
792 
793  if (my && decrement)
794  {
795  mutt_buffer_printf(err, _("Can't decrement a my_ variable"), set_commands[data]);
796  return MUTT_CMD_WARNING;
797  }
798  s->dptr++;
799  if (*s->dptr == '=')
800  {
801  equals = true;
802  s->dptr++;
803  }
804  }
805  else if (*s->dptr == '=')
806  {
807  if (prefix)
808  {
809  mutt_buffer_printf(err, _("Can't use prefix when setting a variable"));
810  return MUTT_CMD_WARNING;
811  }
812 
813  if (reset || unset || inv)
814  {
815  mutt_buffer_printf(err, _("Can't set a variable with the '%s' command"),
816  set_commands[data]);
817  return MUTT_CMD_WARNING;
818  }
819 
820  equals = true;
821  s->dptr++;
822  }
823 
824  if (!bq && (inv || (unset && prefix)))
825  {
826  if (data == MUTT_SET_SET)
827  {
828  mutt_buffer_printf(err, _("Prefixes 'no' and 'inv' may only be used "
829  "with bool/quad variables"));
830  }
831  else
832  {
833  mutt_buffer_printf(err, _("Command '%s' can only be used with bool/quad variables"),
834  set_commands[data]);
835  }
836  return MUTT_CMD_WARNING;
837  }
838 
839  if (reset)
840  {
841  // mutt_buffer_printf(err, "ACT24 reset variable %s", buf->data);
842  if (he)
843  {
844  rc = cs_subset_he_reset(NeoMutt->sub, he, err);
845  if (CSR_RESULT(rc) != CSR_SUCCESS)
846  return MUTT_CMD_ERROR;
847  }
848  else
849  {
850  myvar_del(buf->data);
851  }
852  continue;
853  }
854 
855  if ((data == MUTT_SET_SET) && !inv && !unset)
856  {
857  if (query)
858  {
859  // mutt_buffer_printf(err, "ACT08 query variable %s", buf->data);
860  if (he)
861  {
862  mutt_buffer_addstr(err, buf->data);
863  mutt_buffer_addch(err, '=');
864  mutt_buffer_reset(buf);
865  rc = cs_subset_he_string_get(NeoMutt->sub, he, buf);
866  if (CSR_RESULT(rc) != CSR_SUCCESS)
867  {
868  mutt_buffer_addstr(err, buf->data);
869  return MUTT_CMD_ERROR;
870  }
871  if (DTYPE(he->type) == DT_PATH)
872  mutt_pretty_mailbox(buf->data, buf->dsize);
873  pretty_var(buf->data, err);
874  }
875  else
876  {
877  const char *val = myvar_get(buf->data);
878  if (val)
879  {
880  mutt_buffer_addstr(err, buf->data);
881  mutt_buffer_addch(err, '=');
882  pretty_var(val, err);
883  }
884  else
885  {
886  mutt_buffer_printf(err, _("%s: unknown variable"), buf->data);
887  return MUTT_CMD_ERROR;
888  }
889  }
890  break;
891  }
892  else if (equals)
893  {
894  // mutt_buffer_printf(err, "ACT11 set variable %s to ", buf->data);
895  const char *name = NULL;
896  if (my)
897  {
898  name = mutt_str_dup(buf->data);
899  }
901  if (my)
902  {
903  assert(!decrement);
904  if (increment)
905  {
906  myvar_append(name, buf->data);
907  }
908  else
909  {
910  myvar_set(name, buf->data);
911  }
912  FREE(&name);
913  }
914  else
915  {
916  if (DTYPE(he->type) == DT_PATH)
917  {
918  if (he->type & (DT_PATH_DIR | DT_PATH_FILE))
920  else
921  mutt_path_tilde(buf->data, buf->dsize, HomeDir);
922  }
923  else if (IS_MAILBOX(he))
924  {
926  }
927  else if (IS_COMMAND(he))
928  {
929  struct Buffer scratch = mutt_buffer_make(1024);
930  mutt_buffer_copy(&scratch, buf);
931 
932  if (!mutt_str_equal(buf->data, "builtin"))
933  {
934  mutt_buffer_expand_path(&scratch);
935  }
936  mutt_buffer_reset(buf);
937  mutt_buffer_addstr(buf, mutt_buffer_string(&scratch));
938  mutt_buffer_dealloc(&scratch);
939  }
940  if (increment)
941  {
942  rc = cs_subset_he_string_plus_equals(NeoMutt->sub, he, buf->data, err);
943  }
944  else if (decrement)
945  {
946  rc = cs_subset_he_string_minus_equals(NeoMutt->sub, he, buf->data, err);
947  }
948  else
949  {
950  rc = cs_subset_he_string_set(NeoMutt->sub, he, buf->data, err);
951  }
952  if (CSR_RESULT(rc) != CSR_SUCCESS)
953  return MUTT_CMD_ERROR;
954  }
955  continue;
956  }
957  else
958  {
959  if (bq)
960  {
961  // mutt_buffer_printf(err, "ACT23 set variable %s to 'yes'", buf->data);
962  rc = cs_subset_he_native_set(NeoMutt->sub, he, true, err);
963  if (CSR_RESULT(rc) != CSR_SUCCESS)
964  return MUTT_CMD_ERROR;
965  continue;
966  }
967  else
968  {
969  // mutt_buffer_printf(err, "ACT10 query variable %s", buf->data);
970  if (he)
971  {
972  mutt_buffer_addstr(err, buf->data);
973  mutt_buffer_addch(err, '=');
974  mutt_buffer_reset(buf);
975  rc = cs_subset_he_string_get(NeoMutt->sub, he, buf);
976  if (CSR_RESULT(rc) != CSR_SUCCESS)
977  {
978  mutt_buffer_addstr(err, buf->data);
979  return MUTT_CMD_ERROR;
980  }
981  if (DTYPE(he->type) == DT_PATH)
982  mutt_pretty_mailbox(buf->data, buf->dsize);
983  pretty_var(buf->data, err);
984  }
985  else
986  {
987  const char *val = myvar_get(buf->data);
988  if (val)
989  {
990  mutt_buffer_addstr(err, buf->data);
991  mutt_buffer_addch(err, '=');
992  pretty_var(val, err);
993  }
994  else
995  {
996  mutt_buffer_printf(err, _("%s: unknown variable"), buf->data);
997  return MUTT_CMD_ERROR;
998  }
999  }
1000  break;
1001  }
1002  }
1003  }
1004 
1005  if (my)
1006  {
1007  myvar_del(buf->data);
1008  }
1009  else if (bq)
1010  {
1011  if (inv)
1012  {
1013  // mutt_buffer_printf(err, "ACT25 TOGGLE bool/quad variable %s", buf->data);
1014  if (DTYPE(he->type) == DT_BOOL)
1015  bool_he_toggle(NeoMutt->sub, he, err);
1016  else
1017  quad_he_toggle(NeoMutt->sub, he, err);
1018  }
1019  else
1020  {
1021  // mutt_buffer_printf(err, "ACT26 UNSET bool/quad variable %s", buf->data);
1022  rc = cs_subset_he_native_set(NeoMutt->sub, he, false, err);
1023  if (CSR_RESULT(rc) != CSR_SUCCESS)
1024  return MUTT_CMD_ERROR;
1025  }
1026  continue;
1027  }
1028  else
1029  {
1030  rc = cs_subset_he_string_set(NeoMutt->sub, he, NULL, err);
1031  if (CSR_RESULT(rc) != CSR_SUCCESS)
1032  return MUTT_CMD_ERROR;
1033  }
1034  }
1035 
1036  return MUTT_CMD_SUCCESS;
1037 }
1038 
1042 enum CommandResult parse_setenv(struct Buffer *buf, struct Buffer *s,
1043  intptr_t data, struct Buffer *err)
1044 {
1045  char **envp = mutt_envlist_getlist();
1046 
1047  bool query = false;
1048  bool prefix = false;
1049  bool unset = (data == MUTT_SET_UNSET);
1050 
1051  if (!MoreArgs(s))
1052  {
1053  mutt_buffer_printf(err, _("%s: too few arguments"), "setenv");
1054  return MUTT_CMD_WARNING;
1055  }
1056 
1057  if (*s->dptr == '?')
1058  {
1059  query = true;
1060  prefix = true;
1061 
1062  if (unset)
1063  {
1064  mutt_buffer_printf(err, _("Can't query a variable with the '%s' command"), "unsetenv");
1065  return MUTT_CMD_WARNING;
1066  }
1067 
1068  s->dptr++;
1069  }
1070 
1071  /* get variable name */
1073 
1074  if (*s->dptr == '?')
1075  {
1076  if (unset)
1077  {
1078  mutt_buffer_printf(err, _("Can't query a variable with the '%s' command"), "unsetenv");
1079  return MUTT_CMD_WARNING;
1080  }
1081 
1082  if (prefix)
1083  {
1084  mutt_buffer_printf(err, _("Can't use a prefix when querying a variable"));
1085  return MUTT_CMD_WARNING;
1086  }
1087 
1088  query = true;
1089  s->dptr++;
1090  }
1091 
1092  if (query)
1093  {
1094  bool found = false;
1095  while (envp && *envp)
1096  {
1097  /* This will display all matches for "^QUERY" */
1098  if (mutt_str_startswith(*envp, buf->data))
1099  {
1100  if (!found)
1101  {
1102  mutt_endwin();
1103  found = true;
1104  }
1105  puts(*envp);
1106  }
1107  envp++;
1108  }
1109 
1110  if (found)
1111  {
1113  return MUTT_CMD_SUCCESS;
1114  }
1115 
1116  mutt_buffer_printf(err, _("%s is unset"), buf->data);
1117  return MUTT_CMD_WARNING;
1118  }
1119 
1120  if (unset)
1121  {
1122  if (mutt_envlist_unset(buf->data))
1123  return MUTT_CMD_SUCCESS;
1124  return MUTT_CMD_ERROR;
1125  }
1126 
1127  /* set variable */
1128 
1129  if (*s->dptr == '=')
1130  {
1131  s->dptr++;
1132  SKIPWS(s->dptr);
1133  }
1134 
1135  if (!MoreArgs(s))
1136  {
1137  mutt_buffer_printf(err, _("%s: too few arguments"), "setenv");
1138  return MUTT_CMD_WARNING;
1139  }
1140 
1141  char *name = mutt_str_dup(buf->data);
1143  mutt_envlist_set(name, buf->data, true);
1144  FREE(&name);
1145 
1146  return MUTT_CMD_SUCCESS;
1147 }
1148 
1152 enum CommandResult parse_source(struct Buffer *buf, struct Buffer *s,
1153  intptr_t data, struct Buffer *err)
1154 {
1155  char path[PATH_MAX];
1156 
1157  do
1158  {
1159  if (mutt_extract_token(buf, s, MUTT_TOKEN_NO_FLAGS) != 0)
1160  {
1161  mutt_buffer_printf(err, _("source: error at %s"), s->dptr);
1162  return MUTT_CMD_ERROR;
1163  }
1164  mutt_str_copy(path, buf->data, sizeof(path));
1165  mutt_expand_path(path, sizeof(path));
1166 
1167  if (source_rc(path, err) < 0)
1168  {
1169  mutt_buffer_printf(err, _("source: file %s could not be sourced"), path);
1170  return MUTT_CMD_ERROR;
1171  }
1172 
1173  } while (MoreArgs(s));
1174 
1175  return MUTT_CMD_SUCCESS;
1176 }
1177 
1181 enum CommandResult parse_spam_list(struct Buffer *buf, struct Buffer *s,
1182  intptr_t data, struct Buffer *err)
1183 {
1184  struct Buffer templ;
1185 
1186  mutt_buffer_init(&templ);
1187 
1188  /* Insist on at least one parameter */
1189  if (!MoreArgs(s))
1190  {
1191  if (data == MUTT_SPAM)
1192  mutt_buffer_strcpy(err, _("spam: no matching pattern"));
1193  else
1194  mutt_buffer_strcpy(err, _("nospam: no matching pattern"));
1195  return MUTT_CMD_ERROR;
1196  }
1197 
1198  /* Extract the first token, a regex */
1200 
1201  /* data should be either MUTT_SPAM or MUTT_NOSPAM. MUTT_SPAM is for spam commands. */
1202  if (data == MUTT_SPAM)
1203  {
1204  /* If there's a second parameter, it's a template for the spam tag. */
1205  if (MoreArgs(s))
1206  {
1208 
1209  /* Add to the spam list. */
1210  if (mutt_replacelist_add(&SpamList, buf->data, templ.data, err) != 0)
1211  {
1212  FREE(&templ.data);
1213  return MUTT_CMD_ERROR;
1214  }
1215  FREE(&templ.data);
1216  }
1217  /* If not, try to remove from the nospam list. */
1218  else
1219  {
1221  }
1222 
1223  return MUTT_CMD_SUCCESS;
1224  }
1225  /* MUTT_NOSPAM is for nospam commands. */
1226  else if (data == MUTT_NOSPAM)
1227  {
1228  /* nospam only ever has one parameter. */
1229 
1230  /* "*" is a special case. */
1231  if (mutt_str_equal(buf->data, "*"))
1232  {
1235  return MUTT_CMD_SUCCESS;
1236  }
1237 
1238  /* If it's on the spam list, just remove it. */
1239  if (mutt_replacelist_remove(&SpamList, buf->data) != 0)
1240  return MUTT_CMD_SUCCESS;
1241 
1242  /* Otherwise, add it to the nospam list. */
1243  if (mutt_regexlist_add(&NoSpamList, buf->data, REG_ICASE, err) != 0)
1244  return MUTT_CMD_ERROR;
1245 
1246  return MUTT_CMD_SUCCESS;
1247  }
1248 
1249  /* This should not happen. */
1250  mutt_buffer_strcpy(err, "This is no good at all.");
1251  return MUTT_CMD_ERROR;
1252 }
1253 
1259 enum CommandResult parse_stailq(struct Buffer *buf, struct Buffer *s,
1260  intptr_t data, struct Buffer *err)
1261 {
1262  do
1263  {
1265  add_to_stailq((struct ListHead *) data, buf->data);
1266  } while (MoreArgs(s));
1267 
1268  return MUTT_CMD_SUCCESS;
1269 }
1270 
1274 enum CommandResult parse_subscribe(struct Buffer *buf, struct Buffer *s,
1275  intptr_t data, struct Buffer *err)
1276 {
1277  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
1278 
1279  do
1280  {
1282 
1283  if (parse_grouplist(&gl, buf, s, err) == -1)
1284  goto bail;
1285 
1288 
1289  if (mutt_regexlist_add(&MailLists, buf->data, REG_ICASE, err) != 0)
1290  goto bail;
1291  if (mutt_regexlist_add(&SubscribedLists, buf->data, REG_ICASE, err) != 0)
1292  goto bail;
1293  if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
1294  goto bail;
1295  } while (MoreArgs(s));
1296 
1298  return MUTT_CMD_SUCCESS;
1299 
1300 bail:
1302  return MUTT_CMD_ERROR;
1303 }
1304 
1305 #ifdef USE_IMAP
1306 
1313 enum CommandResult parse_subscribe_to(struct Buffer *buf, struct Buffer *s,
1314  intptr_t data, struct Buffer *err)
1315 {
1316  if (!buf || !s || !err)
1317  return MUTT_CMD_ERROR;
1318 
1319  mutt_buffer_reset(err);
1320 
1321  if (MoreArgs(s))
1322  {
1324 
1325  if (MoreArgs(s))
1326  {
1327  mutt_buffer_printf(err, _("%s: too many arguments"), "subscribe-to");
1328  return MUTT_CMD_WARNING;
1329  }
1330 
1331  if (buf->data && (*buf->data != '\0'))
1332  {
1333  /* Expand and subscribe */
1334  if (imap_subscribe(mutt_expand_path(buf->data, buf->dsize), true) == 0)
1335  {
1336  mutt_message(_("Subscribed to %s"), buf->data);
1337  return MUTT_CMD_SUCCESS;
1338  }
1339 
1340  mutt_buffer_printf(err, _("Could not subscribe to %s"), buf->data);
1341  return MUTT_CMD_ERROR;
1342  }
1343 
1344  mutt_debug(LL_DEBUG1, "Corrupted buffer");
1345  return MUTT_CMD_ERROR;
1346  }
1347 
1348  mutt_buffer_addstr(err, _("No folder specified"));
1349  return MUTT_CMD_WARNING;
1350 }
1351 #endif
1352 
1356 enum CommandResult parse_tag_formats(struct Buffer *buf, struct Buffer *s,
1357  intptr_t data, struct Buffer *err)
1358 {
1359  if (!buf || !s)
1360  return MUTT_CMD_ERROR;
1361 
1362  char *tmp = NULL;
1363 
1364  while (MoreArgs(s))
1365  {
1366  char *tag = NULL, *format = NULL;
1367 
1369  if (buf->data && (*buf->data != '\0'))
1370  tag = mutt_str_dup(buf->data);
1371  else
1372  continue;
1373 
1375  format = mutt_str_dup(buf->data);
1376 
1377  /* avoid duplicates */
1378  tmp = mutt_hash_find(TagFormats, format);
1379  if (tmp)
1380  {
1381  mutt_debug(LL_DEBUG3, "tag format '%s' already registered as '%s'\n", format, tmp);
1382  FREE(&tag);
1383  FREE(&format);
1384  continue;
1385  }
1386 
1387  mutt_hash_insert(TagFormats, format, tag);
1388  }
1389  return MUTT_CMD_SUCCESS;
1390 }
1391 
1395 enum CommandResult parse_tag_transforms(struct Buffer *buf, struct Buffer *s,
1396  intptr_t data, struct Buffer *err)
1397 {
1398  if (!buf || !s)
1399  return MUTT_CMD_ERROR;
1400 
1401  char *tmp = NULL;
1402 
1403  while (MoreArgs(s))
1404  {
1405  char *tag = NULL, *transform = NULL;
1406 
1408  if (buf->data && (*buf->data != '\0'))
1409  tag = mutt_str_dup(buf->data);
1410  else
1411  continue;
1412 
1414  transform = mutt_str_dup(buf->data);
1415 
1416  /* avoid duplicates */
1417  tmp = mutt_hash_find(TagTransforms, tag);
1418  if (tmp)
1419  {
1420  mutt_debug(LL_DEBUG3, "tag transform '%s' already registered as '%s'\n", tag, tmp);
1421  FREE(&tag);
1422  FREE(&transform);
1423  continue;
1424  }
1425 
1426  mutt_hash_insert(TagTransforms, tag, transform);
1427  }
1428  return MUTT_CMD_SUCCESS;
1429 }
1430 
1434 enum CommandResult parse_unignore(struct Buffer *buf, struct Buffer *s,
1435  intptr_t data, struct Buffer *err)
1436 {
1437  do
1438  {
1440 
1441  /* don't add "*" to the unignore list */
1442  if (strcmp(buf->data, "*") != 0)
1443  add_to_stailq(&UnIgnore, buf->data);
1444 
1445  remove_from_stailq(&Ignore, buf->data);
1446  } while (MoreArgs(s));
1447 
1448  return MUTT_CMD_SUCCESS;
1449 }
1450 
1454 enum CommandResult parse_unlists(struct Buffer *buf, struct Buffer *s,
1455  intptr_t data, struct Buffer *err)
1456 {
1458  do
1459  {
1463 
1464  if (!mutt_str_equal(buf->data, "*") &&
1465  (mutt_regexlist_add(&UnMailLists, buf->data, REG_ICASE, err) != 0))
1466  {
1467  return MUTT_CMD_ERROR;
1468  }
1469  } while (MoreArgs(s));
1470 
1471  return MUTT_CMD_SUCCESS;
1472 }
1473 
1478 static void do_unmailboxes(struct Mailbox *m)
1479 {
1480 #ifdef USE_INOTIFY
1482 #endif
1483  m->flags = MB_HIDDEN;
1484  m->gen = -1;
1485  if (m->opened)
1486  {
1487  struct EventMailbox ev_m = { NULL };
1488  mutt_debug(LL_NOTIFY, "NT_MAILBOX_SWITCH: NULL\n");
1490  }
1491  else
1492  {
1494  mailbox_free(&m);
1495  }
1496 }
1497 
1501 static void do_unmailboxes_star(void)
1502 {
1503  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
1505  struct MailboxNode *np = NULL;
1506  struct MailboxNode *nptmp = NULL;
1507  STAILQ_FOREACH_SAFE(np, &ml, entries, nptmp)
1508  {
1509  do_unmailboxes(np->mailbox);
1510  }
1512 }
1513 
1519 enum CommandResult parse_unmailboxes(struct Buffer *buf, struct Buffer *s,
1520  intptr_t data, struct Buffer *err)
1521 {
1522  while (MoreArgs(s))
1523  {
1525 
1526  if (mutt_str_equal(buf->data, "*"))
1527  {
1529  return MUTT_CMD_SUCCESS;
1530  }
1531 
1533 
1534  struct Account *a = NULL;
1535  TAILQ_FOREACH(a, &NeoMutt->accounts, entries)
1536  {
1537  struct Mailbox *m = mx_mbox_find(a, mutt_buffer_string(buf));
1538  if (m)
1539  {
1540  do_unmailboxes(m);
1541  break;
1542  }
1543  }
1544  }
1545  return MUTT_CMD_SUCCESS;
1546 }
1547 
1551 enum CommandResult parse_unmy_hdr(struct Buffer *buf, struct Buffer *s,
1552  intptr_t data, struct Buffer *err)
1553 {
1554  struct ListNode *np = NULL, *tmp = NULL;
1555  size_t l;
1556 
1557  do
1558  {
1560  if (mutt_str_equal("*", buf->data))
1561  {
1562  /* Clear all headers, send a notification for each header */
1563  STAILQ_FOREACH(np, &UserHeader, entries)
1564  {
1565  mutt_debug(LL_NOTIFY, "NT_HEADER_DELETE: %s\n", np->data);
1566  struct EventHeader ev_h = { np->data };
1568  }
1569  mutt_list_free(&UserHeader);
1570  continue;
1571  }
1572 
1573  l = mutt_str_len(buf->data);
1574  if (buf->data[l - 1] == ':')
1575  l--;
1576 
1577  STAILQ_FOREACH_SAFE(np, &UserHeader, entries, tmp)
1578  {
1579  if (mutt_istrn_equal(buf->data, np->data, l) && (np->data[l] == ':'))
1580  {
1581  mutt_debug(LL_NOTIFY, "NT_HEADER_DELETE: %s\n", np->data);
1582  struct EventHeader ev_h = { np->data };
1584 
1585  header_free(&UserHeader, np);
1586  }
1587  }
1588  } while (MoreArgs(s));
1589  return MUTT_CMD_SUCCESS;
1590 }
1591 
1597 enum CommandResult parse_unstailq(struct Buffer *buf, struct Buffer *s,
1598  intptr_t data, struct Buffer *err)
1599 {
1600  do
1601  {
1603  /* Check for deletion of entire list */
1604  if (mutt_str_equal(buf->data, "*"))
1605  {
1606  mutt_list_free((struct ListHead *) data);
1607  break;
1608  }
1609  remove_from_stailq((struct ListHead *) data, buf->data);
1610  } while (MoreArgs(s));
1611 
1612  return MUTT_CMD_SUCCESS;
1613 }
1614 
1618 enum CommandResult parse_unsubscribe(struct Buffer *buf, struct Buffer *s,
1619  intptr_t data, struct Buffer *err)
1620 {
1622  do
1623  {
1626 
1627  if (!mutt_str_equal(buf->data, "*") &&
1628  (mutt_regexlist_add(&UnSubscribedLists, buf->data, REG_ICASE, err) != 0))
1629  {
1630  return MUTT_CMD_ERROR;
1631  }
1632  } while (MoreArgs(s));
1633 
1634  return MUTT_CMD_SUCCESS;
1635 }
1636 
1637 #ifdef USE_IMAP
1638 
1646  intptr_t data, struct Buffer *err)
1647 {
1648  if (!buf || !s || !err)
1649  return MUTT_CMD_ERROR;
1650 
1651  if (MoreArgs(s))
1652  {
1654 
1655  if (MoreArgs(s))
1656  {
1657  mutt_buffer_printf(err, _("%s: too many arguments"), "unsubscribe-from");
1658  return MUTT_CMD_WARNING;
1659  }
1660 
1661  if (buf->data && (*buf->data != '\0'))
1662  {
1663  /* Expand and subscribe */
1664  if (imap_subscribe(mutt_expand_path(buf->data, buf->dsize), false) == 0)
1665  {
1666  mutt_message(_("Unsubscribed from %s"), buf->data);
1667  return MUTT_CMD_SUCCESS;
1668  }
1669 
1670  mutt_buffer_printf(err, _("Could not unsubscribe from %s"), buf->data);
1671  return MUTT_CMD_ERROR;
1672  }
1673 
1674  mutt_debug(LL_DEBUG1, "Corrupted buffer");
1675  return MUTT_CMD_ERROR;
1676  }
1677 
1678  mutt_buffer_addstr(err, _("No folder specified"));
1679  return MUTT_CMD_WARNING;
1680 }
1681 #endif
1682 
1687 {
1689 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
int parse_grouplist(struct GroupList *gl, struct Buffer *buf, struct Buffer *s, struct Buffer *err)
Parse a group context.
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:43
union HashKey key
Key representing the data.
Definition: hash.h:46
enum CommandResult parse_setenv(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;setenv&#39; and &#39;unsetenv&#39; commands - Implements Command::parse() -.
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:327
struct ListNode * header_find(const struct ListHead *hdrlist, const char *header)
Find a header, matching on its field, in a list of headers.
Definition: email.c:180
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:526
Manage keymappings.
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define NONULL(x)
Definition: string2.h:37
An existing header has been changed.
Definition: email.h:170
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
int mutt_replacelist_add(struct ReplaceList *rl, const char *pat, const char *templ, struct Buffer *err)
Add a pattern and a template to a list.
Definition: regex.c:263
char * name
Name of Account.
Definition: account.h:39
#define MUTT_UNGROUP
&#39;ungroup&#39; config command
Definition: group.h:34
IMAP network mailbox.
enum CommandResult parse_finish(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;finish&#39; command - Implements Command::parse() -.
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition: regex.c:227
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
bool feature_enabled(const char *name)
Test if a compile-time feature is enabled.
Definition: version.c:565
Config/command parsing.
#define MUTT_RL_CONT
-continuation
Definition: file.h:39
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
Log of notifications.
Definition: logging.h:45
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition: mx.c:1468
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
#define mutt_error(...)
Definition: logging.h:88
int bool_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:186
enum CommandResult parse_unmy_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unmy_hdr&#39; command - Implements Command::parse() -.
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
#define MUTT_NOSPAM
Definition: mutt.h:111
enum CommandResult parse_unignore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unignore&#39; command - Implements Command::parse() -.
void mutt_grouplist_clear(struct GroupList *gl)
Clear a GroupList.
Definition: group.c:103
An event that happened to a header.
Definition: email.h:176
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() -.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:449
Header has been removed.
Definition: email.h:169
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:526
struct Notify * notify
Notifications: NotifyAccount, EventAccount.
Definition: account.h:42
int mutt_regexlist_add(struct RegexList *rl, const char *str, uint16_t flags, struct Buffer *err)
Compile a regex string and add it to a list.
Definition: regex.c:132
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Match any Mailbox type.
Definition: mailbox.h:45
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
int quad_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Toggle the value of a quad.
Definition: quad.c:203
void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
Add a Group to a GroupList.
Definition: group.c:137
enum CommandResult parse_unlists(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unlists&#39; command - Implements Command::parse() -.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
A group of associated Mailboxes.
Definition: account.h:36
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:40
struct ListNode * header_add(struct ListHead *hdrlist, const char *header)
Add a header to a list.
Definition: email.c:203
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult parse_group(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;group&#39; and &#39;ungroup&#39; commands - Implements Command::parse() -.
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1039
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:41
enum CommandResult parse_stailq(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse a list command - Implements Command::parse() -This is used by &#39;alternative_order&#39;, &#39;auto_view&#39; and several others.
#define MUTT_NAMED
Definition: mutt_commands.h:79
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1578
static bool is_function(const char *name)
Is the argument a neomutt function?
Definition: command_parse.c:85
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:667
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition: subset.c:104
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:226
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:179
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:616
An Event that happened to a Mailbox.
Definition: mailbox.h:190
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:481
enum CommandResult parse_cd(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;cd&#39; command - Implements Command::parse() -.
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1554
int cs_subset_he_string_minus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: subset.c:462
#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:448
int mailbox_gen(void)
Get the next generation number.
Definition: mailbox.c:58
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
enum CommandResult parse_source(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;source&#39; command - Implements Command::parse() -.
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:75
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
Convenience wrapper for the config headers.
#define DT_PATH_DIR
Path is a directory.
Definition: types.h:53
struct HashTable * AutoSubscribeCache
Hash Table of auto-subscribed mailing lists.
Definition: globals.c:38
#define CSR_RESULT(x)
Definition: set.h:52
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
Email Address Handling.
int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:386
default is to reset all vars to default
Definition: mutt_commands.h:75
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Some miscellaneous functions.
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:122
#define MoreArgs(buf)
Definition: buffer.h:40
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: subset.c:320
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1461
enum CommandResult parse_set(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;set&#39; family of commands - Implements Command::parse() -This is used by &#39;reset&#39;...
Many unsorted constants and some structs.
Log at debug level 2.
Definition: logging.h:41
API for mailboxes.
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
void clear_source_stack(void)
Free memory from the stack used for the souce command.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define MUTT_SPAM
Definition: mutt.h:110
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:354
Convenience wrapper for the core headers.
const char * name
name of the function
Definition: keymap.h:93
int mutt_grouplist_add_regex(struct GroupList *gl, const char *s, uint16_t flags, struct Buffer *err)
Add matching Addresses to a GroupList.
Definition: group.c:276
#define SKIPWS(ch)
Definition: string2.h:46
int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
Remove matching addresses from a GroupList.
Definition: group.c:301
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
enum CommandResult parse_unsubscribe(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unsubscribe&#39; command - Implements Command::parse() -.
GroupState
Type of email address group.
Definition: command_parse.c:72
bool mutt_path_tilde(char *buf, size_t buflen, const char *homedir)
Expand &#39;~&#39; in a path.
Definition: path.c:223
Header has been added.
Definition: email.h:168
int opened
Number of times mailbox is opened.
Definition: mailbox.h:132
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:35
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
void myvar_del(const char *var)
Unset the value of a "my_" variable.
Definition: myvar.c:146
int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition: group.c:245
#define mutt_warning(...)
Definition: logging.h:86
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define DT_PATH_FILE
Path is a file.
Definition: types.h:54
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
#define MUTT_TOKEN_QUOTE
Don&#39;t interpret quotes.
Definition: mutt.h:70
WHERE bool OptForceRefresh
(pseudo) refresh even during macros
Definition: options.h:36
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1728
#define MB_HIDDEN
Definition: mailbox.h:38
enum CommandResult parse_spam_list(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;spam&#39; and &#39;nospam&#39; commands - Implements Command::parse() -.
Entry is an address.
Definition: command_parse.c:76
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
#define DT_PATH
a path to a file/directory
Definition: types.h:36
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:40
Functions to parse commands in a config file.
bool mutt_envlist_unset(const char *name)
Unset an environment variable.
Definition: envlist.c:132
#define IS_MAILBOX(x)
Definition: types.h:57
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
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:69
struct ListNode * header_update(struct ListNode *hdr, const char *header)
Update an existing header.
Definition: email.c:217
char * data
Pointer to data.
Definition: buffer.h:35
enum CommandResult parse_subscribe_to(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;subscribe-to&#39; command - Implements Command::parse() -The &#39;subscribe-to&#39; command allows to ...
enum CommandResult parse_unstailq(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse an unlist command - Implements Command::parse() -This is used by &#39;unalternative_order&#39;, &#39;unauto_view&#39; and several others.
Definitions of NeoMutt commands.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
static void do_unmailboxes_star(void)
Remove all Mailboxes from the Sidebar/notifications.
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:37
void myvar_set(const char *var, const char *val)
Set the value of a "my_" variable.
Definition: myvar.c:109
Group is missing an argument.
Definition: command_parse.c:74
bool mutt_path_to_absolute(char *path, const char *reference)
Convert relative filepath to an absolute path.
Definition: path.c:397
struct Command * mutt_command_get(const char *s)
Get a Command by its name.
#define MUTT_TOKEN_PLUS
Treat &#39;+&#39; as a special.
Definition: mutt.h:77
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
enum CommandResult parse_subscribe(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;subscribe&#39; command - Implements Command::parse() -.
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:980
default is to unset all vars
Definition: mutt_commands.h:74
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition: account.c:42
static void do_unmailboxes(struct Mailbox *m)
Remove a Mailbox from the Sidebar/notifications.
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
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
A header has changed, NotifyHeader EventHeader.
Definition: notify_type.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
const struct Binding * km_get_table(enum MenuType mtype)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1313
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:92
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1756
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
Definition: muttlib.c:1753
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:68
void header_free(struct ListHead *hdrlist, struct ListNode *target)
Free and remove a header from a header list.
Definition: email.c:245
Success: Command worked.
Definition: mutt_commands.h:38
char * data
String.
Definition: list.h:36
enum CommandResult parse_mailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;mailboxes&#39; command - Implements Command::parse() -This is also used by &#39;virtual-mailboxes&#39;...
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:36
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
Log at debug level 1.
Definition: logging.h:40
Warning: Help given to the user.
Definition: mutt_commands.h:37
int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: subset.c:424
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:749
enum CommandResult parse_echo(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;echo&#39; command - Implements Command::parse() -.
int mutt_replacelist_remove(struct ReplaceList *rl, const char *pat)
Remove a pattern from a list.
Definition: regex.c:565
Finish: Stop processing this file.
Definition: mutt_commands.h:39
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define MAX_ERRS
Definition: command_parse.c:67
Current Mailbox has changed.
Definition: mailbox.h:182
enum CommandResult parse_ifdef(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;ifdef&#39; and &#39;ifndef&#39; commands - Implements Command::parse() -The &#39;ifdef&#39; command allows con...
const char * strkey
String key.
Definition: hash.h:36
#define MUTT_TOKEN_MINUS
Treat &#39;-&#39; as a special.
Definition: mutt.h:78
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:42
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:74
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:31
void mutt_grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition: group.c:157
enum CommandResult parse_tag_transforms(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;tag-transforms&#39; command - Implements Command::parse() -.
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:95
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:48
struct ConfigSubset * sub
Inherited config items.
Definition: account.h:40
enum CommandResult parse_tag_formats(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;tag-formats&#39; command - Implements Command::parse() -.
enum CommandResult parse_unmailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unmailboxes&#39; command - Implements Command::parse() -This is also used by &#39;unvirtual-mailbo...
enum CommandResult parse_ignore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;ignore&#39; command - Implements Command::parse() -.
Monitor files for changes.
void myvar_append(const char *var, const char *val)
Append to the value of a "my_" variable.
Definition: myvar.c:128
static struct ListHead MuttrcStack
Definition: command_parse.c:65
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
The item stored in a Hash Table.
Definition: hash.h:43
#define MUTT_TOKEN_EQUAL
Treat &#39;=&#39; as a special.
Definition: mutt.h:67
List of Mailboxes.
Definition: mailbox.h:156
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define IS_COMMAND(x)
Definition: types.h:58
const char * name
Definition: mapping.h:33
default is to set all vars
Definition: mutt_commands.h:72
#define TAILQ_EMPTY(head)
Definition: queue.h:721
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
Entry is a regular expression.
Definition: command_parse.c:75
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:84
enum CommandResult parse_lists(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;lists&#39; command - Implements Command::parse() -.
struct Buffer pathbuf
Definition: mailbox.h:83
Convenience wrapper for the library headers.
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:55
A List node for strings.
Definition: list.h:34
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition: muttlib.c:1315
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define MB_NORMAL
Definition: mailbox.h:37
Handling of personal config (&#39;my&#39; variables)
#define STAILQ_FIRST(head)
Definition: queue.h:350
Mapping between a user key and a function.
Definition: keymap.h:91
int gen
Generation number, for sorting.
Definition: mailbox.h:150
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:65
#define DT_BOOL
boolean option
Definition: types.h:30
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
enum CommandResult parse_unsubscribe_from(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unsubscribe-from&#39; command - Implements Command::parse() -The &#39;unsubscribe-from&#39; command al...
Log at debug level 3.
Definition: logging.h:42
default is to invert all vars
Definition: mutt_commands.h:73
int cs_subset_he_native_set(const struct ConfigSubset *sub, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition: subset.c:283
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
#define MUTT_TOKEN_QUESTION
Treat &#39;?&#39; as a special.
Definition: mutt.h:76
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1286
char ** mutt_envlist_getlist(void)
Get the private environment.
Definition: envlist.c:169
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
#define MUTT_GROUP
&#39;group&#39; config command
Definition: group.h:33
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171