NeoMutt  2023-05-17-33-gce4425
Teaching an old dog new tricks
DOXYGEN
commands.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <errno.h>
33#include <inttypes.h> // IWYU pragma: keep
34#include <limits.h>
35#include <stdbool.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include "mutt/lib.h"
41#include "address/lib.h"
42#include "config/lib.h"
43#include "email/lib.h"
44#include "core/lib.h"
45#include "alias/lib.h"
46#include "gui/lib.h"
47#include "mutt.h"
48#include "commands.h"
49#include "attach/lib.h"
50#include "color/lib.h"
51#include "imap/lib.h"
52#include "menu/lib.h"
53#include "pager/lib.h"
54#include "parse/lib.h"
55#include "store/lib.h"
56#include "alternates.h"
57#include "globals.h" // IWYU pragma: keep
58#include "keymap.h"
59#include "muttlib.h"
60#include "mx.h"
61#include "score.h"
62#include "version.h"
63#ifdef USE_INOTIFY
64#include "monitor.h"
65#endif
66#ifdef ENABLE_NLS
67#include <libintl.h>
68#endif
69
73
74#define MAX_ERRS 128
75
80{
84};
85
92static bool is_function(const char *name)
93{
94 for (size_t i = 0; MenuNames[i].name; i++)
95 {
96 const struct MenuFuncOp *fns = km_get_table(MenuNames[i].value);
97 if (!fns)
98 continue;
99
100 for (int j = 0; fns[j].name; j++)
101 if (mutt_str_equal(name, fns[j].name))
102 return true;
103 }
104 return false;
105}
106
116int parse_grouplist(struct GroupList *gl, struct Buffer *buf, struct Buffer *s,
117 struct Buffer *err)
118{
119 while (mutt_istr_equal(buf->data, "-group"))
120 {
121 if (!MoreArgs(s))
122 {
123 buf_strcpy(err, _("-group: no group name"));
124 return -1;
125 }
126
128
130
131 if (!MoreArgs(s))
132 {
133 buf_strcpy(err, _("out of arguments"));
134 return -1;
135 }
136
138 }
139
140 return 0;
141}
142
150enum CommandResult parse_rc_line_cwd(const char *line, char *cwd, struct Buffer *err)
151{
153
154 enum CommandResult ret = parse_rc_line(line, err);
155
156 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
158 FREE(&np->data);
159 FREE(&np);
160
161 return ret;
162}
163
171{
172 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
173 if (np && np->data)
174 return mutt_str_dup(np->data);
175
176 // stack is empty, return our own dummy file relative to cwd
177 struct Buffer *cwd = buf_pool_get();
178 mutt_path_getcwd(cwd);
179 buf_addstr(cwd, "/dummy.rc");
180 char *ret = buf_strdup(cwd);
181 buf_pool_release(&cwd);
182 return ret;
183}
184
191int source_rc(const char *rcfile_path, struct Buffer *err)
192{
193 int lineno = 0, rc = 0, warnings = 0;
194 enum CommandResult line_rc;
195 struct Buffer *token = NULL, *linebuf = NULL;
196 char *line = NULL;
197 char *currentline = NULL;
198 char rcfile[PATH_MAX] = { 0 };
199 size_t linelen = 0;
200 pid_t pid;
201
202 mutt_str_copy(rcfile, rcfile_path, sizeof(rcfile));
203
204 size_t rcfilelen = mutt_str_len(rcfile);
205 if (rcfilelen == 0)
206 return -1;
207
208 bool ispipe = rcfile[rcfilelen - 1] == '|';
209
210 if (!ispipe)
211 {
212 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
213 if (!mutt_path_to_absolute(rcfile, np ? NONULL(np->data) : ""))
214 {
215 mutt_error(_("Error: Can't build path of '%s'"), rcfile_path);
216 return -1;
217 }
218
219 STAILQ_FOREACH(np, &MuttrcStack, entries)
220 {
221 if (mutt_str_equal(np->data, rcfile))
222 {
223 break;
224 }
225 }
226 if (np)
227 {
228 mutt_error(_("Error: Cyclic sourcing of configuration file '%s'"), rcfile);
229 return -1;
230 }
231
233 }
234
235 mutt_debug(LL_DEBUG2, "Reading configuration file '%s'\n", rcfile);
236
237 FILE *fp = mutt_open_read(rcfile, &pid);
238 if (!fp)
239 {
240 buf_printf(err, "%s: %s", rcfile, strerror(errno));
241 return -1;
242 }
243
244 token = buf_pool_get();
245 linebuf = buf_pool_get();
246
247 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
248 const char *const c_charset = cc_charset();
249 while ((line = mutt_file_read_line(line, &linelen, fp, &lineno, MUTT_RL_CONT)) != NULL)
250 {
251 const bool conv = c_config_charset && c_charset;
252 if (conv)
253 {
254 currentline = mutt_str_dup(line);
255 if (!currentline)
256 continue;
257 mutt_ch_convert_string(&currentline, c_config_charset, c_charset, MUTT_ICONV_NO_FLAGS);
258 }
259 else
260 {
261 currentline = line;
262 }
263
264 buf_strcpy(linebuf, currentline);
265
266 buf_reset(err);
267 line_rc = parse_rc_buffer(linebuf, token, err);
268 if (line_rc == MUTT_CMD_ERROR)
269 {
270 mutt_error(_("Error in %s, line %d: %s"), rcfile, lineno, err->data);
271 if (--rc < -MAX_ERRS)
272 {
273 if (conv)
274 FREE(&currentline);
275 break;
276 }
277 }
278 else if (line_rc == MUTT_CMD_WARNING)
279 {
280 /* Warning */
281 mutt_warning(_("Warning in %s, line %d: %s"), rcfile, lineno, err->data);
282 warnings++;
283 }
284 else if (line_rc == MUTT_CMD_FINISH)
285 {
286 if (conv)
287 FREE(&currentline);
288 break; /* Found "finish" command */
289 }
290 else
291 {
292 if (rc < 0)
293 rc = -1;
294 }
295 if (conv)
296 FREE(&currentline);
297 }
298
299 FREE(&line);
300 mutt_file_fclose(&fp);
301 if (pid != -1)
302 filter_wait(pid);
303
304 if (rc)
305 {
306 /* the neomuttrc source keyword */
307 buf_reset(err);
308 buf_printf(err, (rc >= -MAX_ERRS) ? _("source: errors in %s") : _("source: reading aborted due to too many errors in %s"),
309 rcfile);
310 rc = -1;
311 }
312 else
313 {
314 /* Don't alias errors with warnings */
315 if (warnings > 0)
316 {
317 buf_printf(err, ngettext("source: %d warning in %s", "source: %d warnings in %s", warnings),
318 warnings, rcfile);
319 rc = -2;
320 }
321 }
322
323 if (!ispipe && !STAILQ_EMPTY(&MuttrcStack))
324 {
325 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
327 FREE(&np->data);
328 FREE(&np);
329 }
330
331 buf_pool_release(&token);
332 buf_pool_release(&linebuf);
333 return rc;
334}
335
339static enum CommandResult parse_cd(struct Buffer *buf, struct Buffer *s,
340 intptr_t data, struct Buffer *err)
341{
343 buf_expand_path(buf);
344 if (buf_len(buf) == 0)
345 {
346 if (HomeDir)
347 {
348 buf_strcpy(buf, HomeDir);
349 }
350 else
351 {
352 buf_printf(err, _("%s: too few arguments"), "cd");
353 return MUTT_CMD_ERROR;
354 }
355 }
356
357 if (chdir(buf_string(buf)) != 0)
358 {
359 buf_printf(err, "cd: %s", strerror(errno));
360 return MUTT_CMD_ERROR;
361 }
362
363 return MUTT_CMD_SUCCESS;
364}
365
369static enum CommandResult parse_echo(struct Buffer *buf, struct Buffer *s,
370 intptr_t data, struct Buffer *err)
371{
372 if (!MoreArgs(s))
373 {
374 buf_printf(err, _("%s: too few arguments"), "echo");
375 return MUTT_CMD_WARNING;
376 }
378 OptForceRefresh = true;
379 mutt_message("%s", buf->data);
380 OptForceRefresh = false;
381 mutt_sleep(0);
382
383 return MUTT_CMD_SUCCESS;
384}
385
393static enum CommandResult parse_finish(struct Buffer *buf, struct Buffer *s,
394 intptr_t data, struct Buffer *err)
395{
396 if (MoreArgs(s))
397 {
398 buf_printf(err, _("%s: too many arguments"), "finish");
399 return MUTT_CMD_WARNING;
400 }
401
402 return MUTT_CMD_FINISH;
403}
404
408static enum CommandResult parse_group(struct Buffer *buf, struct Buffer *s,
409 intptr_t data, struct Buffer *err)
410{
411 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
412 enum GroupState gstate = GS_NONE;
413
414 do
415 {
417 if (parse_grouplist(&gl, buf, s, err) == -1)
418 goto bail;
419
420 if ((data == MUTT_UNGROUP) && mutt_istr_equal(buf->data, "*"))
421 {
423 goto out;
424 }
425
426 if (mutt_istr_equal(buf->data, "-rx"))
427 {
428 gstate = GS_RX;
429 }
430 else if (mutt_istr_equal(buf->data, "-addr"))
431 {
432 gstate = GS_ADDR;
433 }
434 else
435 {
436 switch (gstate)
437 {
438 case GS_NONE:
439 buf_printf(err, _("%sgroup: missing -rx or -addr"),
440 (data == MUTT_UNGROUP) ? "un" : "");
441 goto warn;
442
443 case GS_RX:
444 if ((data == MUTT_GROUP) &&
445 (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0))
446 {
447 goto bail;
448 }
449 else if ((data == MUTT_UNGROUP) &&
450 (mutt_grouplist_remove_regex(&gl, buf->data) < 0))
451 {
452 goto bail;
453 }
454 break;
455
456 case GS_ADDR:
457 {
458 char *estr = NULL;
459 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
460 mutt_addrlist_parse2(&al, buf->data);
461 if (TAILQ_EMPTY(&al))
462 goto bail;
463 if (mutt_addrlist_to_intl(&al, &estr))
464 {
465 buf_printf(err, _("%sgroup: warning: bad IDN '%s'"),
466 (data == 1) ? "un" : "", estr);
468 FREE(&estr);
469 goto bail;
470 }
471 if (data == MUTT_GROUP)
473 else if (data == MUTT_UNGROUP)
476 break;
477 }
478 }
479 }
480 } while (MoreArgs(s));
481
482out:
484 return MUTT_CMD_SUCCESS;
485
486bail:
488 return MUTT_CMD_ERROR;
489
490warn:
492 return MUTT_CMD_WARNING;
493}
494
508static enum CommandResult parse_ifdef(struct Buffer *buf, struct Buffer *s,
509 intptr_t data, struct Buffer *err)
510{
512
513 if (buf_is_empty(buf))
514 {
515 buf_printf(err, _("%s: too few arguments"), (data ? "ifndef" : "ifdef"));
516 return MUTT_CMD_WARNING;
517 }
518
519 // is the item defined as:
520 bool res = cs_subset_lookup(NeoMutt->sub, buf->data) // a variable?
521 || feature_enabled(buf->data) // a compiled-in feature?
522 || is_function(buf->data) // a function?
523 || command_get(buf->data) // a command?
524#ifdef USE_HCACHE
525 || store_is_valid_backend(buf->data) // a store? (database)
526#endif
527 || mutt_str_getenv(buf->data); // an environment variable?
528
529 if (!MoreArgs(s))
530 {
531 buf_printf(err, _("%s: too few arguments"), (data ? "ifndef" : "ifdef"));
532 return MUTT_CMD_WARNING;
533 }
535
536 /* ifdef KNOWN_SYMBOL or ifndef UNKNOWN_SYMBOL */
537 if ((res && (data == 0)) || (!res && (data == 1)))
538 {
539 enum CommandResult rc = parse_rc_line(buf->data, err);
540 if (rc == MUTT_CMD_ERROR)
541 {
542 mutt_error(_("Error: %s"), err->data);
543 return MUTT_CMD_ERROR;
544 }
545 return rc;
546 }
547 return MUTT_CMD_SUCCESS;
548}
549
553static enum CommandResult parse_ignore(struct Buffer *buf, struct Buffer *s,
554 intptr_t data, struct Buffer *err)
555{
556 do
557 {
560 add_to_stailq(&Ignore, buf->data);
561 } while (MoreArgs(s));
562
563 return MUTT_CMD_SUCCESS;
564}
565
569static enum CommandResult parse_lists(struct Buffer *buf, struct Buffer *s,
570 intptr_t data, struct Buffer *err)
571{
572 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
573
574 do
575 {
577
578 if (parse_grouplist(&gl, buf, s, err) == -1)
579 goto bail;
580
582
583 if (mutt_regexlist_add(&MailLists, buf->data, REG_ICASE, err) != 0)
584 goto bail;
585
586 if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
587 goto bail;
588 } while (MoreArgs(s));
589
591 return MUTT_CMD_SUCCESS;
592
593bail:
595 return MUTT_CMD_ERROR;
596}
597
603enum CommandResult parse_mailboxes(struct Buffer *buf, struct Buffer *s,
604 intptr_t data, struct Buffer *err)
605{
606 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
607 while (MoreArgs(s))
608 {
609 struct Mailbox *m = mailbox_new();
610
611 if (data & MUTT_NAMED)
612 {
613 // This may be empty, e.g. `named-mailboxes "" +inbox`
615 m->name = buf_strdup(buf);
616 }
617
619 if (buf_is_empty(buf))
620 {
621 /* Skip empty tokens. */
622 mailbox_free(&m);
623 continue;
624 }
625
626 buf_strcpy(&m->pathbuf, buf->data);
627 /* int rc = */ mx_path_canon2(m, c_folder);
628
629 if (m->type <= MUTT_UNKNOWN)
630 {
631 mutt_error("Unknown Mailbox: %s", m->realpath);
632 mailbox_free(&m);
633 return MUTT_CMD_ERROR;
634 }
635
636 bool new_account = false;
637 struct Account *a = mx_ac_find(m);
638 if (!a)
639 {
640 a = account_new(NULL, NeoMutt->sub);
641 a->type = m->type;
642 new_account = true;
643 }
644
645 if (!new_account)
646 {
647 struct Mailbox *m_old = mx_mbox_find(a, m->realpath);
648 if (m_old)
649 {
650 if (!m_old->visible)
651 {
652 m_old->visible = true;
653 m_old->gen = mailbox_gen();
654 }
655
656 const bool rename = (data & MUTT_NAMED) && !mutt_str_equal(m_old->name, m->name);
657 if (rename)
658 {
659 mutt_str_replace(&m_old->name, m->name);
660 }
661
662 mailbox_free(&m);
663 continue;
664 }
665 }
666
667 if (!mx_ac_add(a, m))
668 {
669 mailbox_free(&m);
670 if (new_account)
671 {
672 cs_subset_free(&a->sub);
673 FREE(&a->name);
674 notify_free(&a->notify);
675 FREE(&a);
676 }
677 continue;
678 }
679 if (new_account)
680 {
682 }
683
684 // this is finally a visible mailbox in the sidebar and mailboxes list
685 m->visible = true;
686
687#ifdef USE_INOTIFY
689#endif
690 }
691 return MUTT_CMD_SUCCESS;
692}
693
697enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s,
698 intptr_t data, struct Buffer *err)
699{
701 char *p = strpbrk(buf->data, ": \t");
702 if (!p || (*p != ':'))
703 {
704 buf_strcpy(err, _("invalid header field"));
705 return MUTT_CMD_WARNING;
706 }
707
708 struct EventHeader ev_h = { buf->data };
709 struct ListNode *n = header_find(&UserHeader, buf->data);
710
711 if (n)
712 {
713 header_update(n, buf->data);
714 mutt_debug(LL_NOTIFY, "NT_HEADER_CHANGE: %s\n", buf->data);
716 }
717 else
718 {
719 header_add(&UserHeader, buf->data);
720 mutt_debug(LL_NOTIFY, "NT_HEADER_ADD: %s\n", buf->data);
722 }
723
724 return MUTT_CMD_SUCCESS;
725}
726
737{
738 char tempfile[PATH_MAX] = { 0 };
739 mutt_mktemp(tempfile, sizeof(tempfile));
740
741 FILE *fp_out = mutt_file_fopen(tempfile, "w");
742 if (!fp_out)
743 {
744 // L10N: '%s' is the file name of the temporary file
745 buf_printf(err, _("Could not create temporary file %s"), tempfile);
746 return MUTT_CMD_ERROR;
747 }
748
749 dump_config(NeoMutt->sub->cs, flags, fp_out);
750
751 mutt_file_fclose(&fp_out);
752
753 struct PagerData pdata = { 0 };
754 struct PagerView pview = { &pdata };
755
756 pdata.fname = tempfile;
757
758 pview.banner = "set";
760 pview.mode = PAGER_MODE_OTHER;
761
762 mutt_do_pager(&pview, NULL);
763
764 return MUTT_CMD_SUCCESS;
765}
766
775static int envlist_sort(const void *a, const void *b)
776{
777 return strcmp(*(const char **) a, *(const char **) b);
778}
779
783static enum CommandResult parse_setenv(struct Buffer *buf, struct Buffer *s,
784 intptr_t data, struct Buffer *err)
785{
786 char **envp = EnvList;
787
788 bool query = false;
789 bool prefix = false;
790 bool unset = (data == MUTT_SET_UNSET);
791
792 if (!MoreArgs(s))
793 {
794 if (!StartupComplete)
795 {
796 buf_printf(err, _("%s: too few arguments"), "setenv");
797 return MUTT_CMD_WARNING;
798 }
799
800 char tempfile[PATH_MAX] = { 0 };
801 mutt_mktemp(tempfile, sizeof(tempfile));
802
803 FILE *fp_out = mutt_file_fopen(tempfile, "w");
804 if (!fp_out)
805 {
806 // L10N: '%s' is the file name of the temporary file
807 buf_printf(err, _("Could not create temporary file %s"), tempfile);
808 return MUTT_CMD_ERROR;
809 }
810
811 int count = 0;
812 for (char **env = EnvList; *env; env++)
813 count++;
814
815 qsort(EnvList, count, sizeof(char *), envlist_sort);
816
817 for (char **env = EnvList; *env; env++)
818 fprintf(fp_out, "%s\n", *env);
819
820 mutt_file_fclose(&fp_out);
821
822 struct PagerData pdata = { 0 };
823 struct PagerView pview = { &pdata };
824
825 pdata.fname = tempfile;
826
827 pview.banner = "setenv";
829 pview.mode = PAGER_MODE_OTHER;
830
831 mutt_do_pager(&pview, NULL);
832 return MUTT_CMD_SUCCESS;
833 }
834
835 if (*s->dptr == '?')
836 {
837 query = true;
838 prefix = true;
839
840 if (unset)
841 {
842 buf_printf(err, _("Can't query a variable with the '%s' command"), "unsetenv");
843 return MUTT_CMD_WARNING;
844 }
845
846 s->dptr++;
847 }
848
849 /* get variable name */
851
852 if (*s->dptr == '?')
853 {
854 if (unset)
855 {
856 buf_printf(err, _("Can't query a variable with the '%s' command"), "unsetenv");
857 return MUTT_CMD_WARNING;
858 }
859
860 if (prefix)
861 {
862 buf_printf(err, _("Can't use a prefix when querying a variable"));
863 return MUTT_CMD_WARNING;
864 }
865
866 query = true;
867 s->dptr++;
868 }
869
870 if (query)
871 {
872 bool found = false;
873 while (envp && *envp)
874 {
875 /* This will display all matches for "^QUERY" */
876 if (mutt_str_startswith(*envp, buf->data))
877 {
878 if (!found)
879 {
880 mutt_endwin();
881 found = true;
882 }
883 puts(*envp);
884 }
885 envp++;
886 }
887
888 if (found)
889 {
891 return MUTT_CMD_SUCCESS;
892 }
893
894 buf_printf(err, _("%s is unset"), buf->data);
895 return MUTT_CMD_WARNING;
896 }
897
898 if (unset)
899 {
900 if (!envlist_unset(&EnvList, buf->data))
901 {
902 buf_printf(err, _("%s is unset"), buf->data);
903 return MUTT_CMD_WARNING;
904 }
905 return MUTT_CMD_SUCCESS;
906 }
907
908 /* set variable */
909
910 if (*s->dptr == '=')
911 {
912 s->dptr++;
913 SKIPWS(s->dptr);
914 }
915
916 if (!MoreArgs(s))
917 {
918 buf_printf(err, _("%s: too few arguments"), "setenv");
919 return MUTT_CMD_WARNING;
920 }
921
922 char *name = mutt_str_dup(buf->data);
924 envlist_set(&EnvList, name, buf->data, true);
925 FREE(&name);
926
927 return MUTT_CMD_SUCCESS;
928}
929
933static enum CommandResult parse_source(struct Buffer *buf, struct Buffer *s,
934 intptr_t data, struct Buffer *err)
935{
936 char path[PATH_MAX] = { 0 };
937
938 do
939 {
940 if (parse_extract_token(buf, s, TOKEN_NO_FLAGS) != 0)
941 {
942 buf_printf(err, _("source: error at %s"), s->dptr);
943 return MUTT_CMD_ERROR;
944 }
945 mutt_str_copy(path, buf->data, sizeof(path));
946 mutt_expand_path(path, sizeof(path));
947
948 if (source_rc(path, err) < 0)
949 {
950 buf_printf(err, _("source: file %s could not be sourced"), path);
951 return MUTT_CMD_ERROR;
952 }
953
954 } while (MoreArgs(s));
955
956 return MUTT_CMD_SUCCESS;
957}
958
962static enum CommandResult parse_spam_list(struct Buffer *buf, struct Buffer *s,
963 intptr_t data, struct Buffer *err)
964{
965 struct Buffer templ;
966
967 buf_init(&templ);
968
969 /* Insist on at least one parameter */
970 if (!MoreArgs(s))
971 {
972 if (data == MUTT_SPAM)
973 buf_strcpy(err, _("spam: no matching pattern"));
974 else
975 buf_strcpy(err, _("nospam: no matching pattern"));
976 return MUTT_CMD_ERROR;
977 }
978
979 /* Extract the first token, a regex */
981
982 /* data should be either MUTT_SPAM or MUTT_NOSPAM. MUTT_SPAM is for spam commands. */
983 if (data == MUTT_SPAM)
984 {
985 /* If there's a second parameter, it's a template for the spam tag. */
986 if (MoreArgs(s))
987 {
989
990 /* Add to the spam list. */
991 if (mutt_replacelist_add(&SpamList, buf->data, templ.data, err) != 0)
992 {
993 FREE(&templ.data);
994 return MUTT_CMD_ERROR;
995 }
996 FREE(&templ.data);
997 }
998 else
999 {
1000 /* If not, try to remove from the nospam list. */
1002 }
1003
1004 return MUTT_CMD_SUCCESS;
1005 }
1006 else if (data == MUTT_NOSPAM)
1007 {
1008 /* MUTT_NOSPAM is for nospam commands. */
1009 /* nospam only ever has one parameter. */
1010
1011 /* "*" is a special case. */
1012 if (mutt_str_equal(buf->data, "*"))
1013 {
1016 return MUTT_CMD_SUCCESS;
1017 }
1018
1019 /* If it's on the spam list, just remove it. */
1020 if (mutt_replacelist_remove(&SpamList, buf->data) != 0)
1021 return MUTT_CMD_SUCCESS;
1022
1023 /* Otherwise, add it to the nospam list. */
1024 if (mutt_regexlist_add(&NoSpamList, buf->data, REG_ICASE, err) != 0)
1025 return MUTT_CMD_ERROR;
1026
1027 return MUTT_CMD_SUCCESS;
1028 }
1029
1030 /* This should not happen. */
1031 buf_strcpy(err, "This is no good at all.");
1032 return MUTT_CMD_ERROR;
1033}
1034
1040static enum CommandResult parse_stailq(struct Buffer *buf, struct Buffer *s,
1041 intptr_t data, struct Buffer *err)
1042{
1043 do
1044 {
1046 add_to_stailq((struct ListHead *) data, buf->data);
1047 } while (MoreArgs(s));
1048
1049 return MUTT_CMD_SUCCESS;
1050}
1051
1055static enum CommandResult parse_subscribe(struct Buffer *buf, struct Buffer *s,
1056 intptr_t data, struct Buffer *err)
1057{
1058 struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
1059
1060 do
1061 {
1063
1064 if (parse_grouplist(&gl, buf, s, err) == -1)
1065 goto bail;
1066
1069
1070 if (mutt_regexlist_add(&MailLists, buf->data, REG_ICASE, err) != 0)
1071 goto bail;
1072 if (mutt_regexlist_add(&SubscribedLists, buf->data, REG_ICASE, err) != 0)
1073 goto bail;
1074 if (mutt_grouplist_add_regex(&gl, buf->data, REG_ICASE, err) != 0)
1075 goto bail;
1076 } while (MoreArgs(s));
1077
1079 return MUTT_CMD_SUCCESS;
1080
1081bail:
1083 return MUTT_CMD_ERROR;
1084}
1085
1086#ifdef USE_IMAP
1094enum CommandResult parse_subscribe_to(struct Buffer *buf, struct Buffer *s,
1095 intptr_t data, struct Buffer *err)
1096{
1097 if (!buf || !s || !err)
1098 return MUTT_CMD_ERROR;
1099
1100 buf_reset(err);
1101
1102 if (MoreArgs(s))
1103 {
1105
1106 if (MoreArgs(s))
1107 {
1108 buf_printf(err, _("%s: too many arguments"), "subscribe-to");
1109 return MUTT_CMD_WARNING;
1110 }
1111
1112 if (buf->data && (*buf->data != '\0'))
1113 {
1114 /* Expand and subscribe */
1115 if (imap_subscribe(mutt_expand_path(buf->data, buf->dsize), true) == 0)
1116 {
1117 mutt_message(_("Subscribed to %s"), buf->data);
1118 return MUTT_CMD_SUCCESS;
1119 }
1120
1121 buf_printf(err, _("Could not subscribe to %s"), buf->data);
1122 return MUTT_CMD_ERROR;
1123 }
1124
1125 mutt_debug(LL_DEBUG1, "Corrupted buffer");
1126 return MUTT_CMD_ERROR;
1127 }
1128
1129 buf_addstr(err, _("No folder specified"));
1130 return MUTT_CMD_WARNING;
1131}
1132#endif
1133
1141static enum CommandResult parse_tag_formats(struct Buffer *buf, struct Buffer *s,
1142 intptr_t data, struct Buffer *err)
1143{
1144 if (!s)
1145 return MUTT_CMD_ERROR;
1146
1147 struct Buffer *tagbuf = buf_pool_get();
1148 struct Buffer *fmtbuf = buf_pool_get();
1149
1150 while (MoreArgs(s))
1151 {
1153 const char *tag = buf_string(tagbuf);
1154 if (*tag == '\0')
1155 continue;
1156
1158 const char *fmt = buf_string(fmtbuf);
1159
1160 /* avoid duplicates */
1161 const char *tmp = mutt_hash_find(TagFormats, fmt);
1162 if (tmp)
1163 {
1164 mutt_warning(_("tag format '%s' already registered as '%s'"), fmt, tmp);
1165 continue;
1166 }
1167
1169 }
1170
1171 buf_pool_release(&tagbuf);
1172 buf_pool_release(&fmtbuf);
1173 return MUTT_CMD_SUCCESS;
1174}
1175
1183static enum CommandResult parse_tag_transforms(struct Buffer *buf, struct Buffer *s,
1184 intptr_t data, struct Buffer *err)
1185{
1186 if (!s)
1187 return MUTT_CMD_ERROR;
1188
1189 struct Buffer *tagbuf = buf_pool_get();
1190 struct Buffer *trnbuf = buf_pool_get();
1191
1192 while (MoreArgs(s))
1193 {
1195 const char *tag = buf_string(tagbuf);
1196 if (*tag == '\0')
1197 continue;
1198
1200 const char *trn = buf_string(trnbuf);
1201
1202 /* avoid duplicates */
1203 const char *tmp = mutt_hash_find(TagTransforms, tag);
1204 if (tmp)
1205 {
1206 mutt_warning(_("tag transform '%s' already registered as '%s'"), tag, tmp);
1207 continue;
1208 }
1209
1211 }
1212
1213 buf_pool_release(&tagbuf);
1214 buf_pool_release(&trnbuf);
1215 return MUTT_CMD_SUCCESS;
1216}
1217
1221static enum CommandResult parse_unignore(struct Buffer *buf, struct Buffer *s,
1222 intptr_t data, struct Buffer *err)
1223{
1224 do
1225 {
1227
1228 /* don't add "*" to the unignore list */
1229 if (!mutt_str_equal(buf->data, "*"))
1230 add_to_stailq(&UnIgnore, buf->data);
1231
1233 } while (MoreArgs(s));
1234
1235 return MUTT_CMD_SUCCESS;
1236}
1237
1241static enum CommandResult parse_unlists(struct Buffer *buf, struct Buffer *s,
1242 intptr_t data, struct Buffer *err)
1243{
1245 do
1246 {
1250
1251 if (!mutt_str_equal(buf->data, "*") &&
1252 (mutt_regexlist_add(&UnMailLists, buf->data, REG_ICASE, err) != 0))
1253 {
1254 return MUTT_CMD_ERROR;
1255 }
1256 } while (MoreArgs(s));
1257
1258 return MUTT_CMD_SUCCESS;
1259}
1260
1265static void do_unmailboxes(struct Mailbox *m)
1266{
1267#ifdef USE_INOTIFY
1269#endif
1270 m->visible = false;
1271 m->gen = -1;
1272 if (m->opened)
1273 {
1274 struct EventMailbox ev_m = { NULL };
1275 mutt_debug(LL_NOTIFY, "NT_MAILBOX_CHANGE: NULL\n");
1277 }
1278 else
1279 {
1281 mailbox_free(&m);
1282 }
1283}
1284
1288static void do_unmailboxes_star(void)
1289{
1290 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
1292 struct MailboxNode *np = NULL;
1293 struct MailboxNode *nptmp = NULL;
1294 STAILQ_FOREACH_SAFE(np, &ml, entries, nptmp)
1295 {
1297 }
1299}
1300
1306enum CommandResult parse_unmailboxes(struct Buffer *buf, struct Buffer *s,
1307 intptr_t data, struct Buffer *err)
1308{
1309 while (MoreArgs(s))
1310 {
1312
1313 if (mutt_str_equal(buf->data, "*"))
1314 {
1316 return MUTT_CMD_SUCCESS;
1317 }
1318
1319 buf_expand_path(buf);
1320
1321 struct Account *a = NULL;
1322 TAILQ_FOREACH(a, &NeoMutt->accounts, entries)
1323 {
1324 struct Mailbox *m = mx_mbox_find(a, buf_string(buf));
1325 if (m)
1326 {
1327 do_unmailboxes(m);
1328 break;
1329 }
1330 }
1331 }
1332 return MUTT_CMD_SUCCESS;
1333}
1334
1338static enum CommandResult parse_unmy_hdr(struct Buffer *buf, struct Buffer *s,
1339 intptr_t data, struct Buffer *err)
1340{
1341 struct ListNode *np = NULL, *tmp = NULL;
1342 size_t l;
1343
1344 do
1345 {
1347 if (mutt_str_equal("*", buf->data))
1348 {
1349 /* Clear all headers, send a notification for each header */
1350 STAILQ_FOREACH(np, &UserHeader, entries)
1351 {
1352 mutt_debug(LL_NOTIFY, "NT_HEADER_DELETE: %s\n", np->data);
1353 struct EventHeader ev_h = { np->data };
1355 }
1357 continue;
1358 }
1359
1360 l = mutt_str_len(buf->data);
1361 if (buf->data[l - 1] == ':')
1362 l--;
1363
1364 STAILQ_FOREACH_SAFE(np, &UserHeader, entries, tmp)
1365 {
1366 if (mutt_istrn_equal(buf->data, np->data, l) && (np->data[l] == ':'))
1367 {
1368 mutt_debug(LL_NOTIFY, "NT_HEADER_DELETE: %s\n", np->data);
1369 struct EventHeader ev_h = { np->data };
1371
1372 header_free(&UserHeader, np);
1373 }
1374 }
1375 } while (MoreArgs(s));
1376 return MUTT_CMD_SUCCESS;
1377}
1378
1384static enum CommandResult parse_unstailq(struct Buffer *buf, struct Buffer *s,
1385 intptr_t data, struct Buffer *err)
1386{
1387 do
1388 {
1390 /* Check for deletion of entire list */
1391 if (mutt_str_equal(buf->data, "*"))
1392 {
1393 mutt_list_free((struct ListHead *) data);
1394 break;
1395 }
1396 remove_from_stailq((struct ListHead *) data, buf->data);
1397 } while (MoreArgs(s));
1398
1399 return MUTT_CMD_SUCCESS;
1400}
1401
1405static enum CommandResult parse_unsubscribe(struct Buffer *buf, struct Buffer *s,
1406 intptr_t data, struct Buffer *err)
1407{
1409 do
1410 {
1413
1414 if (!mutt_str_equal(buf->data, "*") &&
1415 (mutt_regexlist_add(&UnSubscribedLists, buf->data, REG_ICASE, err) != 0))
1416 {
1417 return MUTT_CMD_ERROR;
1418 }
1419 } while (MoreArgs(s));
1420
1421 return MUTT_CMD_SUCCESS;
1422}
1423
1424#ifdef USE_IMAP
1433 intptr_t data, struct Buffer *err)
1434{
1435 if (!buf || !s || !err)
1436 return MUTT_CMD_ERROR;
1437
1438 if (MoreArgs(s))
1439 {
1441
1442 if (MoreArgs(s))
1443 {
1444 buf_printf(err, _("%s: too many arguments"), "unsubscribe-from");
1445 return MUTT_CMD_WARNING;
1446 }
1447
1448 if (buf->data && (*buf->data != '\0'))
1449 {
1450 /* Expand and subscribe */
1451 if (imap_subscribe(mutt_expand_path(buf->data, buf->dsize), false) == 0)
1452 {
1453 mutt_message(_("Unsubscribed from %s"), buf->data);
1454 return MUTT_CMD_SUCCESS;
1455 }
1456
1457 buf_printf(err, _("Could not unsubscribe from %s"), buf->data);
1458 return MUTT_CMD_ERROR;
1459 }
1460
1461 mutt_debug(LL_DEBUG1, "Corrupted buffer");
1462 return MUTT_CMD_ERROR;
1463 }
1464
1465 buf_addstr(err, _("No folder specified"));
1466 return MUTT_CMD_WARNING;
1467}
1468#endif
1469
1473static enum CommandResult parse_version(struct Buffer *buf, struct Buffer *s,
1474 intptr_t data, struct Buffer *err)
1475{
1476 // silently ignore 'version' if it's in a config file
1477 if (!StartupComplete)
1478 return MUTT_CMD_SUCCESS;
1479
1480 char tempfile[PATH_MAX] = { 0 };
1481 mutt_mktemp(tempfile, sizeof(tempfile));
1482
1483 FILE *fp_out = mutt_file_fopen(tempfile, "w");
1484 if (!fp_out)
1485 {
1486 // L10N: '%s' is the file name of the temporary file
1487 buf_printf(err, _("Could not create temporary file %s"), tempfile);
1488 return MUTT_CMD_ERROR;
1489 }
1490
1491 print_version(fp_out);
1492 mutt_file_fclose(&fp_out);
1493
1494 struct PagerData pdata = { 0 };
1495 struct PagerView pview = { &pdata };
1496
1497 pdata.fname = tempfile;
1498
1499 pview.banner = "version";
1500 pview.flags = MUTT_PAGER_NO_FLAGS;
1501 pview.mode = PAGER_MODE_OTHER;
1502
1503 mutt_do_pager(&pview, NULL);
1504 return MUTT_CMD_SUCCESS;
1505}
1506
1511{
1513}
1514
1518static const struct Command MuttCommands[] = {
1519 // clang-format off
1520 { "alias", parse_alias, 0 },
1521 { "alternates", parse_alternates, 0 },
1522 { "alternative_order", parse_stailq, IP &AlternativeOrderList },
1523 { "attachments", parse_attachments, 0 },
1524 { "auto_view", parse_stailq, IP &AutoViewList },
1525 { "bind", mutt_parse_bind, 0 },
1526 { "cd", parse_cd, 0 },
1527 { "color", mutt_parse_color, 0 },
1528 { "echo", parse_echo, 0 },
1529 { "exec", mutt_parse_exec, 0 },
1530 { "finish", parse_finish, 0 },
1531 { "group", parse_group, MUTT_GROUP },
1532 { "hdr_order", parse_stailq, IP &HeaderOrderList },
1533 { "ifdef", parse_ifdef, 0 },
1534 { "ifndef", parse_ifdef, 1 },
1535 { "ignore", parse_ignore, 0 },
1536 { "lists", parse_lists, 0 },
1537 { "macro", mutt_parse_macro, 1 },
1538 { "mailboxes", parse_mailboxes, 0 },
1539 { "mailto_allow", parse_stailq, IP &MailToAllow },
1540 { "mime_lookup", parse_stailq, IP &MimeLookupList },
1541 { "mono", mutt_parse_mono, 0 },
1542 { "my_hdr", parse_my_hdr, 0 },
1543 { "named-mailboxes", parse_mailboxes, MUTT_NAMED },
1544 { "nospam", parse_spam_list, MUTT_NOSPAM },
1545 { "push", mutt_parse_push, 0 },
1546 { "reset", parse_set, MUTT_SET_RESET },
1547 { "score", mutt_parse_score, 0 },
1548 { "set", parse_set, MUTT_SET_SET },
1549 { "setenv", parse_setenv, MUTT_SET_SET },
1550 { "source", parse_source, 0 },
1551 { "spam", parse_spam_list, MUTT_SPAM },
1552 { "subjectrx", parse_subjectrx_list, 0 },
1553 { "subscribe", parse_subscribe, 0 },
1554 { "tag-formats", parse_tag_formats, 0 },
1555 { "tag-transforms", parse_tag_transforms, 0 },
1556 { "toggle", parse_set, MUTT_SET_INV },
1557 { "unalias", parse_unalias, 0 },
1558 { "unalternates", parse_unalternates, 0 },
1559 { "unalternative_order", parse_unstailq, IP &AlternativeOrderList },
1560 { "unattachments", parse_unattachments, 0 },
1561 { "unauto_view", parse_unstailq, IP &AutoViewList },
1562 { "unbind", mutt_parse_unbind, MUTT_UNBIND },
1563 { "uncolor", mutt_parse_uncolor, 0 },
1564 { "ungroup", parse_group, MUTT_UNGROUP },
1565 { "unhdr_order", parse_unstailq, IP &HeaderOrderList },
1566 { "unignore", parse_unignore, 0 },
1567 { "unlists", parse_unlists, 0 },
1568 { "unmacro", mutt_parse_unbind, MUTT_UNMACRO },
1569 { "unmailboxes", parse_unmailboxes, 0 },
1570 { "unmailto_allow", parse_unstailq, IP &MailToAllow },
1571 { "unmime_lookup", parse_unstailq, IP &MimeLookupList },
1572 { "unmono", mutt_parse_unmono, 0 },
1573 { "unmy_hdr", parse_unmy_hdr, 0 },
1574 { "unscore", mutt_parse_unscore, 0 },
1575 { "unset", parse_set, MUTT_SET_UNSET },
1576 { "unsetenv", parse_setenv, MUTT_SET_UNSET },
1577 { "unsubjectrx", parse_unsubjectrx_list, 0 },
1578 { "unsubscribe", parse_unsubscribe, 0 },
1579 { "version", parse_version, 0 },
1580 // clang-format on
1581};
1582
1587{
1589}
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:96
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition: account.c:43
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1450
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:627
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1285
Email Address Handling.
Email Aliases.
Alternate address handling.
GUI display the mailboxes in a side panel.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:171
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:414
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:86
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:301
struct Buffer * buf_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:53
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:236
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:370
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:490
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
const char * cc_charset(void)
Get the cached value of $charset.
Definition: cache.c:106
Color and attribute parsing.
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
@ MUTT_CMD_FINISH
Finish: Stop processing this file.
Definition: command.h:40
static const struct Command MuttCommands[]
General NeoMutt Commands.
Definition: commands.c:1518
enum CommandResult set_dump(ConfigDumpFlags flags, struct Buffer *err)
Dump list of config variables into a file/pager.
Definition: commands.c:736
GroupState
Type of email address group.
Definition: commands.c:80
@ GS_RX
Entry is a regular expression.
Definition: commands.c:82
@ GS_NONE
Group is missing an argument.
Definition: commands.c:81
@ GS_ADDR
Entry is an address.
Definition: commands.c:83
#define MAX_ERRS
Definition: commands.c:74
enum CommandResult parse_rc_line_cwd(const char *line, char *cwd, struct Buffer *err)
Parse and run a muttrc line in a relative directory.
Definition: commands.c:150
void commands_init(void)
Initialize commands array and register default commands.
Definition: commands.c:1586
int parse_grouplist(struct GroupList *gl, struct Buffer *buf, struct Buffer *s, struct Buffer *err)
Parse a group context.
Definition: commands.c:116
static void do_unmailboxes_star(void)
Remove all Mailboxes from the Sidebar/notifications.
Definition: commands.c:1288
void clear_source_stack(void)
Free memory from the stack used for the source command.
Definition: commands.c:1510
static int envlist_sort(const void *a, const void *b)
Sort two environment strings.
Definition: commands.c:775
static struct ListHead MuttrcStack
LIFO designed to contain the list of config files that have been sourced and avoid cyclic sourcing.
Definition: commands.c:72
static void do_unmailboxes(struct Mailbox *m)
Remove a Mailbox from the Sidebar/notifications.
Definition: commands.c:1265
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
Definition: commands.c:191
char * mutt_get_sourced_cwd(void)
Get the current file path that is being parsed.
Definition: commands.c:170
static bool is_function(const char *name)
Is the argument a neomutt function?
Definition: commands.c:92
Functions to parse commands in a config file.
#define MUTT_NAMED
Definition: commands.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: globals.c:39
#define IP
Definition: set.h:54
void commands_register(const struct Command *cmds, const size_t num_cmds)
Add commands to Commands array.
Definition: command.c:53
struct Command * command_get(const char *s)
Get a Command by its name.
Definition: command.c:87
Convenience wrapper for the core headers.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:355
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:123
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:34
void header_free(struct ListHead *hdrlist, struct ListNode *target)
Free and remove a header from a header list.
Definition: email.c:206
struct ListNode * header_add(struct ListHead *hdrlist, const char *header)
Add a header to a list.
Definition: email.c:164
struct ListNode * header_update(struct ListNode *hdr, const char *header)
Update an existing header.
Definition: email.c:178
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:141
struct ReplaceList SpamList
List of regexes to match subscribed mailing lists.
Definition: globals.c:45
struct RegexList SubscribedLists
List of header patterns to unignore (see)
Definition: globals.c:47
struct HashTable * AutoSubscribeCache
< Hash Table: "mailto:" -> AutoSubscribeCache
Definition: globals.c:35
struct RegexList UnSubscribedLists
Definition: globals.c:53
struct RegexList UnMailLists
List of regexes to exclude false matches in SubscribedLists.
Definition: globals.c:51
struct RegexList MailLists
List of permitted fields in a mailto: url.
Definition: globals.c:39
struct ListHead MailToAllow
List of regexes to identify non-spam emails.
Definition: globals.c:41
struct ListHead Ignore
List of regexes to match mailing lists.
Definition: globals.c:37
struct RegexList NoSpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:43
struct ListHead UnIgnore
List of regexes to exclude false matches in MailLists.
Definition: globals.c:49
Structs that make up an email.
@ NT_HEADER_CHANGE
An existing header has been changed.
Definition: email.h:174
@ NT_HEADER_ADD
Header has been added.
Definition: email.h:172
@ NT_HEADER_DELETE
Header has been removed.
Definition: email.h:173
bool envlist_set(char ***envp, const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:87
bool envlist_unset(char ***envp, const char *name)
Unset an environment variable.
Definition: envlist.c:135
int parse_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: extract.c:47
#define TOKEN_SPACE
Don't treat whitespace as a term.
Definition: extract.h:47
#define TOKEN_QUOTE
Don't interpret quotes.
Definition: extract.h:48
#define TOKEN_EQUAL
Treat '=' as a special.
Definition: extract.h:45
#define MoreArgs(buf)
Definition: extract.h:30
#define TOKEN_QUESTION
Treat '?' as a special.
Definition: extract.h:54
#define TOKEN_NO_FLAGS
No flags are set.
Definition: extract.h:44
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:738
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
#define MUTT_RL_CONT
-continuation
Definition: file.h:40
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
struct ListHead MimeLookupList
List of mime types that that shouldn't use the mailcap entry.
Definition: globals.c:52
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition: globals.c:49
struct ListHead AutoViewList
List of mime types to auto view.
Definition: globals.c:50
bool OptForceRefresh
(pseudo) refresh even during macros
Definition: globals.c:71
struct ListHead UserHeader
List of custom headers to add to outgoing emails.
Definition: globals.c:55
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: globals.c:51
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:91
Global variables.
int mutt_grouplist_remove_addrlist(struct GroupList *gl, struct AddressList *al)
Remove an AddressList from a GroupList.
Definition: group.c:290
void mutt_grouplist_add(struct GroupList *gl, struct Group *group)
Add a Group to a GroupList.
Definition: group.c:182
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:321
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:117
int mutt_grouplist_remove_regex(struct GroupList *gl, const char *s)
Remove matching addresses from a GroupList.
Definition: group.c:346
void mutt_grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition: group.c:202
void mutt_grouplist_clear(struct GroupList *gl)
Clear a GroupList.
Definition: group.c:148
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:271
#define MUTT_GROUP
'group' config command
Definition: group.h:33
#define MUTT_UNGROUP
'ungroup' config command
Definition: group.h:34
static enum CommandResult parse_finish(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'finish' command - Implements Command::parse() -.
Definition: commands.c:393
static enum CommandResult parse_stailq(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse a list command - Implements Command::parse() -.
Definition: commands.c:1040
static enum CommandResult parse_version(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'version' command - Implements Command::parse() -.
Definition: commands.c:1473
static enum CommandResult parse_unlists(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unlists' command - Implements Command::parse() -.
Definition: commands.c:1241
static enum CommandResult parse_group(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'group' and 'ungroup' commands - Implements Command::parse() -.
Definition: commands.c:408
enum CommandResult parse_unsubjectrx_list(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unsubjectrx' command - Implements Command::parse() -.
Definition: subjectrx.c:184
enum CommandResult parse_set(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'set' family of commands - Implements Command::parse() -.
Definition: set.c:425
enum CommandResult parse_alternates(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'alternates' command - Implements Command::parse() -.
Definition: alternates.c:92
enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unscore' command - Implements Command::parse() -.
Definition: score.c:197
enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unmono' command - Implements Command::parse() -.
Definition: command.c:1204
static enum CommandResult parse_unstailq(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse an unlist command - Implements Command::parse() -.
Definition: commands.c:1384
enum CommandResult mutt_parse_bind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'bind' command - Implements Command::parse() -.
Definition: keymap.c:1514
enum CommandResult parse_subjectrx_list(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'subjectrx' command - Implements Command::parse() -.
Definition: subjectrx.c:167
enum CommandResult parse_unsubscribe_from(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unsubscribe-from' command - Implements Command::parse() -.
Definition: commands.c:1432
static enum CommandResult parse_unignore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unignore' command - Implements Command::parse() -.
Definition: commands.c:1221
static enum CommandResult parse_ifdef(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'ifdef' and 'ifndef' commands - Implements Command::parse() -.
Definition: commands.c:508
static enum CommandResult parse_source(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'source' command - Implements Command::parse() -.
Definition: commands.c:933
enum CommandResult parse_unalternates(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unalternates' command - Implements Command::parse() -.
Definition: alternates.c:128
enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'score' command - Implements Command::parse() -.
Definition: score.c:87
enum CommandResult parse_unmailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unmailboxes' command - Implements Command::parse() -.
Definition: commands.c:1306
static enum CommandResult parse_unmy_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unmy_hdr' command - Implements Command::parse() -.
Definition: commands.c:1338
enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'mono' command - Implements Command::parse() -.
Definition: command.c:1228
enum CommandResult mutt_parse_color(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'color' command - Implements Command::parse() -.
Definition: command.c:1214
static enum CommandResult parse_subscribe(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'subscribe' command - Implements Command::parse() -.
Definition: commands.c:1055
static enum CommandResult parse_tag_transforms(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'tag-transforms' command - Implements Command::parse() -.
Definition: commands.c:1183
enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'uncolor' command - Implements Command::parse() -.
Definition: command.c:1187
static enum CommandResult parse_cd(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'cd' command - Implements Command::parse() -.
Definition: commands.c:339
static enum CommandResult parse_ignore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'ignore' command - Implements Command::parse() -.
Definition: commands.c:553
enum CommandResult parse_subscribe_to(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'subscribe-to' command - Implements Command::parse() -.
Definition: commands.c:1094
enum CommandResult mutt_parse_unbind(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unbind' command - Implements Command::parse() -.
Definition: keymap.c:1677
enum CommandResult parse_alias(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'alias' command - Implements Command::parse() -.
Definition: commands.c:47
enum CommandResult parse_unalias(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unalias' command - Implements Command::parse() -.
Definition: commands.c:160
enum CommandResult parse_mailboxes(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'mailboxes' command - Implements Command::parse() -.
Definition: commands.c:603
static enum CommandResult parse_tag_formats(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'tag-formats' command - Implements Command::parse() -.
Definition: commands.c:1141
enum CommandResult mutt_parse_macro(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'macro' command - Implements Command::parse() -.
Definition: keymap.c:1764
static enum CommandResult parse_spam_list(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'spam' and 'nospam' commands - Implements Command::parse() -.
Definition: commands.c:962
enum CommandResult parse_unattachments(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unattachments' command - Implements Command::parse() -.
Definition: attachments.c:534
static enum CommandResult parse_lists(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'lists' command - Implements Command::parse() -.
Definition: commands.c:569
static enum CommandResult parse_echo(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'echo' command - Implements Command::parse() -.
Definition: commands.c:369
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
Definition: commands.c:697
static enum CommandResult parse_unsubscribe(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'unsubscribe' command - Implements Command::parse() -.
Definition: commands.c:1405
static enum CommandResult parse_setenv(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'setenv' and 'unsetenv' commands - Implements Command::parse() -.
Definition: commands.c:783
enum CommandResult mutt_parse_push(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'push' command - Implements Command::parse() -.
Definition: keymap.c:1133
enum CommandResult parse_attachments(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'attachments' command - Implements Command::parse() -.
Definition: attachments.c:475
enum CommandResult mutt_parse_exec(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'exec' command - Implements Command::parse() -.
Definition: keymap.c:1850
#define mutt_warning(...)
Definition: logging2.h:85
#define mutt_error(...)
Definition: logging2.h:87
#define mutt_message(...)
Definition: logging2.h:86
#define mutt_debug(LEVEL,...)
Definition: logging2.h:84
Convenience wrapper for the gui headers.
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:335
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:362
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
IMAP network mailbox.
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1124
const struct MenuFuncOp * km_get_table(enum MenuType mtype)
Lookup a Menu's functions.
Definition: keymap.c:1248
Manage keymappings.
#define MUTT_UNBIND
Definition: keymap.h:33
#define MUTT_UNMACRO
Definition: keymap.h:34
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:41
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:40
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:45
int mailbox_gen(void)
Get the next generation number.
Definition: mailbox.c:59
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:69
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:88
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition: mailbox.h:171
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition: mailbox.h:42
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
bool StartupComplete
When the config has been read.
Definition: main.c:199
#define FREE(x)
Definition: memory.h:43
#define mutt_array_size(x)
Definition: memory.h:36
GUI present the user with a selectable list.
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition: monitor.c:489
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition: monitor.c:534
Monitor files for changes.
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:822
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
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
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
bool mutt_path_to_absolute(char *path, const char *reference)
Convert relative filepath to an absolute path.
Definition: path.c:397
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition: path.c:563
int mutt_replacelist_remove(struct ReplaceList *rl, const char *pat)
Remove a pattern from a list.
Definition: regex.c:587
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:174
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:135
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:471
int mutt_regexlist_remove(struct RegexList *rl, const char *str)
Remove a Regex from a list.
Definition: regex.c:230
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:266
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:918
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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:653
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:525
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
Many unsorted constants and some structs.
#define MUTT_NOSPAM
Definition: mutt.h:100
#define MUTT_SPAM
Definition: mutt.h:99
#define PATH_MAX
Definition: mutt.h:41
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
Definition: muttlib.c:1718
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1693
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:124
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1424
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:333
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition: muttlib.c:1280
Some miscellaneous functions.
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition: mx.c:1604
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition: mx.c:1781
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition: mx.c:1580
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition: mx.c:1494
API for mailboxes.
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition: neomutt.c:84
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
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
@ NT_HEADER
A header has changed, NotifyHeader EventHeader.
Definition: notify_type.h:47
GUI display a file/email/help in a viewport with paging.
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:59
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition: lib.h:140
Text parsing functions.
@ MUTT_SET_INV
default is to invert all vars
Definition: set.h:37
@ MUTT_SET_SET
default is to set all vars
Definition: set.h:36
@ MUTT_SET_RESET
default is to reset all vars to default
Definition: set.h:39
@ MUTT_SET_UNSET
default is to unset all vars
Definition: set.h:38
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:106
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:119
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
#define TAILQ_EMPTY(head)
Definition: queue.h:721
enum CommandResult parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: rc.c:108
enum CommandResult parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: rc.c:50
Routines for adding user scores to emails.
Key value store.
bool store_is_valid_backend(const char *str)
Is the string a valid Store backend.
Definition: store.c:128
#define NONULL(x)
Definition: string2.h:37
#define SKIPWS(ch)
Definition: string2.h:45
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
char * name
Name of Account.
Definition: account.h:39
struct Notify * notify
Notifications: NotifyAccount, EventAccount.
Definition: account.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: account.h:40
String manipulation buffer.
Definition: buffer.h:34
char * dptr
Current read/write position.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
An event that happened to a header.
Definition: email.h:181
An Event that happened to a Mailbox.
Definition: mailbox.h:185
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
List of Mailboxes.
Definition: mailbox.h:152
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:153
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:127
bool visible
True if a result of "mailboxes".
Definition: mailbox.h:130
int opened
Number of times mailbox is opened.
Definition: mailbox.h:128
int gen
Generation number, for sorting.
Definition: mailbox.h:145
const char * name
String value.
Definition: mapping.h:33
Mapping between a function and an operation.
Definition: keymap.h:92
const char * name
Name of the function.
Definition: keymap.h:93
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Data to be displayed by PagerView.
Definition: lib.h:159
const char * fname
Name of the file to read.
Definition: lib.h:163
Paged view into some data.
Definition: lib.h:170
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:171
enum PagerMode mode
Pager mode.
Definition: lib.h:172
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:173
const char * banner
Title to display in status bar.
Definition: lib.h:174
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition: subset.c:105
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:184
struct HashTable * TagFormats
Hash Table: "inbox" -> "GI" - Tag format strings.
Definition: tags.c:39
struct HashTable * TagTransforms
Hash Table: "inbox" -> "i" - Alternative tag names.
Definition: tags.c:38
#define mutt_mktemp(buf, buflen)
Definition: tmp.h:34
const struct Mapping MenuNames[]
Menu name lookup table.
Definition: type.c:37
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:420
bool feature_enabled(const char *name)
Test if a compile-time feature is enabled.
Definition: version.c:575
Display version and copyright about NeoMutt.