NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
29
81
87
88#define GNULIB_defined_setlocale
89
90#include "config.h"
91#include <errno.h>
92#include <limits.h>
93#include <pwd.h>
94#include <stdbool.h>
95#include <stdio.h>
96#include <string.h>
97#include <sys/stat.h>
98#include <sys/utsname.h>
99#include <time.h>
100#include <unistd.h>
101#include "mutt/lib.h"
102#include "address/lib.h"
103#include "config/lib.h"
104#include "email/lib.h"
105#include "core/lib.h"
106#include "alias/lib.h"
107#include "conn/lib.h"
108#include "gui/lib.h"
109#include "mutt.h"
110#include "attach/lib.h"
111#include "browser/lib.h"
112#include "cli/lib.h"
113#include "color/lib.h"
114#include "commands/lib.h"
115#include "compose/lib.h"
116#include "editor/lib.h"
117#include "fuzzy/lib.h"
118#include "history/lib.h"
119#include "hooks/lib.h"
120#include "imap/lib.h"
121#include "index/lib.h"
122#include "key/lib.h"
123#include "mlist/lib.h"
124#include "ncrypt/lib.h"
125#include "nntp/lib.h"
126#include "pager/lib.h"
127#include "parse/lib.h"
128#include "pop/lib.h"
129#include "postpone/lib.h"
130#include "question/lib.h"
131#include "send/lib.h"
132#include "sidebar/lib.h"
133#include "external.h"
134#include "globals.h"
135#include "mutt_logging.h"
136#include "mutt_mailbox.h"
137#include "muttlib.h"
138#include "mx.h"
139#include "nntp/adata.h" // IWYU pragma: keep
140#include "version.h"
141#ifdef USE_AUTOCRYPT
142#include "autocrypt/lib.h"
143#endif
144#if defined(USE_DEBUG_NOTIFY) || defined(USE_DEBUG_BACKTRACE)
145#include "debug/lib.h"
146#endif
147#ifndef DOMAIN
148#include "conn/lib.h"
149#endif
150
151bool StartupComplete = false;
152
153void show_cli(enum HelpMode mode, bool use_color);
154
155// clang-format off
156extern const struct Module ModuleMain;
157extern const struct Module ModuleAddress; extern const struct Module ModuleAlias; extern const struct Module ModuleAttach; extern const struct Module ModuleAutocrypt;
158extern const struct Module ModuleBcache; extern const struct Module ModuleBrowser; extern const struct Module ModuleColor; extern const struct Module ModuleCommands;
159extern const struct Module ModuleComplete; extern const struct Module ModuleCompmbox; extern const struct Module ModuleCompose; extern const struct Module ModuleCompress;
160extern const struct Module ModuleConfig; extern const struct Module ModuleConn; extern const struct Module ModuleConvert; extern const struct Module ModuleCore;
161extern const struct Module ModuleEditor; extern const struct Module ModuleEmail; extern const struct Module ModuleEnvelope; extern const struct Module ModuleExpando;
162extern const struct Module ModuleFuzzy; extern const struct Module ModuleGui; extern const struct Module ModuleHcache; extern const struct Module ModuleHelpbar;
163extern const struct Module ModuleHistory; extern const struct Module ModuleHooks; extern const struct Module ModuleImap; extern const struct Module ModuleIndex;
164extern const struct Module ModuleKey; extern const struct Module ModuleLua; extern const struct Module ModuleMaildir; extern const struct Module ModuleMbox;
165extern const struct Module ModuleMenu; extern const struct Module ModuleMh; extern const struct Module ModuleMlist; extern const struct Module ModuleMutt;
166extern const struct Module ModuleNcrypt; extern const struct Module ModuleNntp; extern const struct Module ModuleNotmuch; extern const struct Module ModulePager;
167extern const struct Module ModuleParse; extern const struct Module ModulePattern; extern const struct Module ModulePop; extern const struct Module ModulePostpone;
168extern const struct Module ModuleProgress; extern const struct Module ModuleQuestion; extern const struct Module ModuleSend; extern const struct Module ModuleSidebar;
169extern const struct Module ModuleStore;
170// clang-format on
171
175static const struct Module *Modules[] = {
176 // clang-format off
177 &ModuleMain, &ModuleGui, // These two have priority
187// clang-format on
188#ifdef USE_AUTOCRYPT
190#endif
191#ifdef USE_HCACHE_COMPRESSION
193#endif
194#ifdef USE_HCACHE
196#endif
197#ifdef USE_LUA
198 &ModuleLua,
199#endif
200#ifdef USE_NOTMUCH
202#endif
203#ifdef USE_HCACHE
205#endif
206 NULL,
207};
208
215static int execute_commands(struct StringArray *sa)
216{
217 int rc = 0;
218 struct Buffer *line = buf_pool_get();
219 struct ParseContext *pc = parse_context_new();
220 struct ParseError *pe = parse_error_new();
221
222 const char **cp = NULL;
223 ARRAY_FOREACH(cp, sa)
224 {
225 buf_strcpy(line, *cp);
226 enum CommandResult rc2 = parse_rc_line(line, pc, pe);
227 if (rc2 == MUTT_CMD_ERROR)
228 mutt_error(_("Error in command line: %s"), buf_string(pe->message));
229 else if (rc2 == MUTT_CMD_WARNING)
230 mutt_warning(_("Warning in command line: %s"), buf_string(pe->message));
231
232 if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
233 {
234 rc = -1;
235 goto done;
236 }
237 }
238
239done:
240 buf_pool_release(&line);
242 parse_error_free(&pe);
243
244 return rc;
245}
246
254static char *find_cfg(const char *home, const char *xdg_cfg_home)
255{
256 const char *names[] = {
257 "neomuttrc",
258 "muttrc",
259 NULL,
260 };
261
262 const char *locations[][2] = {
263 { xdg_cfg_home, "neomutt/" },
264 { xdg_cfg_home, "mutt/" },
265 { home, ".neomutt/" },
266 { home, ".mutt/" },
267 { home, "." },
268 { NULL, NULL },
269 };
270
271 struct Buffer *buf = buf_pool_get();
272 char *cfg = NULL;
273
274 for (int i = 0; locations[i][0] || locations[i][1]; i++)
275 {
276 if (!locations[i][0])
277 continue;
278
279 for (int j = 0; names[j]; j++)
280 {
281 buf_printf(buf, "%s/%s%s", locations[i][0], locations[i][1], names[j]);
282 if (access(buf_string(buf), F_OK) == 0)
283 {
284 cfg = buf_strdup(buf);
285 goto done;
286 }
287 }
288 }
289
290done:
291 buf_pool_release(&buf);
292 return cfg;
293}
294
295#ifndef DOMAIN
301static char *getmailname(void)
302{
303 char *mailname = NULL;
304 static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
305
306 for (size_t i = 0; i < countof(mn_files); i++)
307 {
308 FILE *fp = mutt_file_fopen(mn_files[i], "r");
309 if (!fp)
310 continue;
311
312 size_t len = 0;
313 mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NONE);
314 mutt_file_fclose(&fp);
315 if (mailname && *mailname)
316 break;
317
318 FREE(&mailname);
319 }
320
321 return mailname;
322}
323#endif
324
334static bool get_hostname(struct ConfigSet *cs)
335{
336 const char *short_host = NULL;
337 struct utsname utsname = { 0 };
338
339 const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
340 if (c_hostname)
341 {
342 short_host = c_hostname;
343 }
344 else
345 {
346 /* The call to uname() shouldn't fail, but if it does, the system is horribly
347 * broken, and the system's networking configuration is in an unreliable
348 * state. We should bail. */
349 if ((uname(&utsname)) == -1)
350 {
351 mutt_perror(_("unable to determine nodename via uname()"));
352 return false; // TEST09: can't test
353 }
354
355 short_host = utsname.nodename;
356 }
357
358 /* some systems report the FQDN instead of just the hostname */
359 const char *dot = strchr(short_host, '.');
360 if (dot)
361 ShortHostname = mutt_strn_dup(short_host, dot - short_host);
362 else
363 ShortHostname = mutt_str_dup(short_host);
364
365 // All the code paths from here alloc memory for the fqdn
366 char *fqdn = mutt_str_dup(c_hostname);
367 if (!fqdn)
368 {
369 mutt_debug(LL_DEBUG1, "Setting $hostname\n");
370 /* now get FQDN. Use configured domain first, DNS next, then uname */
371#ifdef DOMAIN
372 /* we have a compile-time domain name, use that for `$hostname` */
373 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
374#else
375 fqdn = getmailname();
376 if (!fqdn)
377 {
378 struct Buffer *domain = buf_pool_get();
379 if (getdnsdomainname(domain) == 0)
380 {
381 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), buf_string(domain));
382 }
383 else
384 {
385 /* DNS failed, use the nodename. Whether or not the nodename had a '.'
386 * in it, we can use the nodename as the FQDN. On hosts where DNS is
387 * not being used, e.g. small network that relies on hosts files, a
388 * short host name is all that is required for SMTP to work correctly.
389 * It could be wrong, but we've done the best we can, at this point the
390 * onus is on the user to provide the correct hostname if the nodename
391 * won't work in their network. */
392 fqdn = mutt_str_dup(utsname.nodename);
393 }
394 buf_pool_release(&domain);
395 mutt_debug(LL_DEBUG1, "Hostname: %s\n", NONULL(fqdn));
396 }
397#endif
398 }
399
400 if (fqdn)
401 {
402 config_str_set_initial(cs, "hostname", fqdn);
403 FREE(&fqdn);
404 }
405
406 return true;
407}
408
420static int mutt_init(struct ConfigSet *cs, struct Buffer *dlevel,
421 struct Buffer *dfile, bool skip_sys_rc,
422 struct StringArray *user_files, struct StringArray *commands)
423{
424 bool need_pause = false;
425 int rc = 1;
426 struct Buffer *buf = buf_pool_get();
427 struct ParseContext *pc = parse_context_new();
428 struct ParseError *pe = parse_error_new();
429 const char **cp = NULL;
430
431#ifdef NEOMUTT_DIRECT_COLORS
432 /* Test if we run in a terminal which supports direct colours.
433 *
434 * The user/terminal can indicate their capability independent of the
435 * terminfo file by setting the COLORTERM environment variable to "truecolor"
436 * or "24bit" (case sensitive).
437 *
438 * Note: This is to test is less about whether the terminal understands
439 * direct color commands but more about whether ncurses believes it can send
440 * them to the terminal, e.g. ncurses ignores COLORTERM.
441 */
442 if (COLORS == 16777216) // 2^24
443 {
444 /* Ncurses believes the Terminal supports it check the environment variable
445 * to respect the user's choice */
446 const char *env_colorterm = mutt_str_getenv("COLORTERM");
447 if (env_colorterm && (mutt_str_equal(env_colorterm, "truecolor") ||
448 mutt_str_equal(env_colorterm, "24bit")))
449 {
450 config_str_set_initial(cs, "color_directcolor", "yes");
451 }
452 }
453#endif
454
455 /* "$spool_file" precedence: config file, environment */
456 const char *p = mutt_str_getenv("MAIL");
457 if (!p)
458 p = mutt_str_getenv("MAILDIR");
459 if (!p)
460 {
461#ifdef HOMESPOOL
462 buf_concat_path(buf, NONULL(NeoMutt->home_dir), MAILPATH);
463#else
464 buf_concat_path(buf, MAILPATH, NONULL(NeoMutt->username));
465#endif
466 p = buf_string(buf);
467 }
468 config_str_set_initial(cs, "spool_file", p);
469
470 p = mutt_str_getenv("REPLYTO");
471 if (p)
472 {
473 buf_printf(buf, "Reply-To: %s", p);
474 buf_seek(buf, 0);
475
477 ASSERT(cmd);
478 parse_my_header(cmd, buf, pc, pe);
479 }
480
481 p = mutt_str_getenv("EMAIL");
482 if (p)
483 config_str_set_initial(cs, "from", p);
484
485 /* "$mailcap_path" precedence: config file, environment, code */
486 struct Buffer *mc = buf_pool_get();
487 struct Slist *sl_mc = NULL;
488 const char *env_mc = mutt_str_getenv("MAILCAPS");
489 if (env_mc)
490 {
491 sl_mc = slist_parse(env_mc, D_SLIST_SEP_COLON);
492 }
493 else
494 {
495 cs_str_initial_get(cs, "mailcap_path", mc);
497 buf_reset(mc);
498 }
499 slist_to_buffer(sl_mc, mc);
500 config_str_set_initial(cs, "mailcap_path", buf_string(mc));
501 slist_free(&sl_mc);
502 buf_pool_release(&mc);
503
504 /* "$tmp_dir" precedence: config file, environment, code */
505 const char *env_tmp = mutt_str_getenv("TMPDIR");
506 if (env_tmp)
507 {
508 config_str_set_initial(cs, "tmp_dir", env_tmp);
509 config_str_set_initial(cs, "tmp_draft_dir", env_tmp);
510 }
511
512 /* "$visual", "$editor" precedence: config file, environment, code */
513 const char *env_ed = mutt_str_getenv("VISUAL");
514 if (!env_ed)
515 env_ed = mutt_str_getenv("EDITOR");
516 if (!env_ed)
517 env_ed = "vi";
518 config_str_set_initial(cs, "editor", env_ed);
519
520 const char *charset = mutt_ch_get_langinfo_charset();
521 config_str_set_initial(cs, "charset", charset);
522 mutt_ch_set_charset(charset);
523 FREE(&charset);
524
525 char name[256] = { 0 };
526 const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
527 if (!c_real_name)
528 {
529 struct passwd *pw = getpwuid(getuid());
530 if (pw)
531 {
532 c_real_name = mutt_gecos_name(name, sizeof(name), pw);
533 }
534 }
535 config_str_set_initial(cs, "real_name", c_real_name);
536
537 if (ARRAY_EMPTY(user_files))
538 {
539 const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
540
541 if (!xdg_cfg_home && NeoMutt->home_dir)
542 {
543 buf_printf(buf, "%s/.config", NeoMutt->home_dir);
544 xdg_cfg_home = buf_string(buf);
545 }
546
547 char *config = find_cfg(NeoMutt->home_dir, xdg_cfg_home);
548 if (config)
549 {
550 ARRAY_ADD(user_files, config);
551 }
552 }
553 else
554 {
555 ARRAY_FOREACH(cp, user_files)
556 {
557 buf_strcpy(buf, *cp);
558 FREE(cp);
559 expand_path(buf, false);
560 ARRAY_SET(user_files, ARRAY_FOREACH_IDX_cp, buf_strdup(buf));
561 if (access(buf_string(buf), F_OK))
562 {
563 mutt_perror("%s", buf_string(buf));
564 goto done; // TEST10: neomutt -F missing
565 }
566 }
567 }
568
569 ARRAY_FOREACH(cp, user_files)
570 {
571 if (*cp && !mutt_str_equal(*cp, "/dev/null"))
572 {
573 cs_str_string_set(cs, "alias_file", *cp, NULL);
574 break;
575 }
576 }
577
578 /* Process the global rc file if it exists and the user hasn't explicitly
579 * requested not to via "-n". */
580 if (!skip_sys_rc)
581 {
582 do
583 {
585 break;
586
587 buf_printf(buf, "%s/neomuttrc", SYSCONFDIR);
588 if (access(buf_string(buf), F_OK) == 0)
589 break;
590
591 buf_printf(buf, "%s/Muttrc", SYSCONFDIR);
592 if (access(buf_string(buf), F_OK) == 0)
593 break;
594
595 buf_printf(buf, "%s/neomuttrc", PKGDATADIR);
596 if (access(buf_string(buf), F_OK) == 0)
597 break;
598
599 buf_printf(buf, "%s/Muttrc", PKGDATADIR);
600 } while (false);
601
602 if (access(buf_string(buf), F_OK) == 0)
603 {
604 if (source_rc(buf_string(buf), pc, pe) != 0)
605 {
606 mutt_error("%s", buf_string(pe->message));
607 need_pause = true; // TEST11: neomutt (error in /etc/neomuttrc)
608 }
609 }
610 }
611
612 /* Read the user's initialization file. */
613 ARRAY_FOREACH(cp, user_files)
614 {
615 if (*cp)
616 {
617 if (source_rc(*cp, pc, pe) != 0)
618 {
619 mutt_error("%s", buf_string(pe->message));
620 need_pause = true; // TEST12: neomutt (error in ~/.neomuttrc)
621 }
622 }
623 }
624
625 if (execute_commands(commands) != 0)
626 need_pause = true; // TEST13: neomutt -e broken
627
628 if (!get_hostname(cs))
629 goto done;
630
631 /* The command line overrides the config */
632 if (!buf_is_empty(dlevel))
633 cs_str_reset(cs, "debug_level", NULL);
634 if (!buf_is_empty(dfile))
635 cs_str_reset(cs, "debug_file", NULL);
636
637 if (mutt_log_start() < 0)
638 {
639 mutt_perror("log file");
640 goto done;
641 }
642
643 if (need_pause && OptGui)
644 {
646 if (mutt_any_key_to_continue(NULL) == 'q')
647 goto done; // TEST14: neomutt -e broken (press 'q')
648 }
649
650 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
651 if (mutt_file_mkdir(c_tmp_dir, S_IRWXU) < 0)
652 {
653 mutt_error(_("Can't create %s: %s"), c_tmp_dir, strerror(errno));
654 goto done;
655 }
656
657 rc = 0;
658
659done:
661 parse_error_free(&pe);
662 buf_pool_release(&buf);
663 return rc;
664}
665
673static int get_elem_queries(struct StringArray *queries, struct HashElemArray *hea)
674{
675 int rc = 0;
676 const char **cp = NULL;
677 ARRAY_FOREACH(cp, queries)
678 {
679 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, *cp);
680 if (!he)
681 {
682 mutt_warning(_("Unknown option %s"), *cp);
683 rc = 1;
684 continue;
685 }
686
687 if (he->type & D_INTERNAL_DEPRECATED)
688 {
689 mutt_warning(_("Option %s is deprecated"), *cp);
690 rc = 1;
691 continue;
692 }
693
694 ARRAY_ADD(hea, he);
695 }
696
697 return rc; // TEST16: neomutt -Q charset
698}
699
703static void init_keys(struct NeoMutt *n)
704{
705 struct SubMenu *sm_generic = generic_init_keys(n);
706
707 alias_init_keys(n, sm_generic);
708 attach_init_keys(n, sm_generic);
709#ifdef USE_AUTOCRYPT
710 autocrypt_init_keys(n, sm_generic);
711#endif
712 browser_init_keys(n, sm_generic);
713 compose_init_keys(n, sm_generic);
714 editor_init_keys(n, sm_generic);
715 fuzzy_init_keys(n, sm_generic);
716 sidebar_init_keys(n, sm_generic);
717 index_init_keys(n, sm_generic);
718 mlist_init_keys(n, sm_generic);
719 pager_init_keys(n, sm_generic);
720 pgp_init_keys(n, sm_generic);
721 postpone_init_keys(n, sm_generic);
722
723 km_sort();
724}
725
731static int start_curses(void)
732{
733 /* should come before initscr() so that ncurses 4.2 doesn't try to install
734 * its own SIGWINCH handler */
736
737 if (!initscr())
738 {
739 mutt_error(_("Error initializing terminal"));
740 return 1;
741 }
742
744 colors_init(color_mod_data);
745 keypad(stdscr, true);
746 cbreak();
747 noecho();
748 nonl();
749 typeahead(-1); /* simulate smooth scrolling */
750 meta(stdscr, true);
752 ext_keys_init(mod_data->key_names);
753
754 /* Now that curses is set up, we drop back to normal screen mode.
755 * This simplifies displaying error messages to the user.
756 * The first call to refresh() will swap us back to curses screen mode. */
757 endwin();
758 return 0;
759}
760
768static bool get_user_info(struct ConfigSet *cs)
769{
770 const char *shell = mutt_str_getenv("SHELL");
771
772 /* Get some information about the user */
773 struct passwd *pw = getpwuid(getuid());
774 if (pw)
775 {
776 if (!NeoMutt->username)
777 NeoMutt->username = mutt_str_dup(pw->pw_name);
778 if (!NeoMutt->home_dir)
779 NeoMutt->home_dir = mutt_str_dup(pw->pw_dir);
780 if (!shell)
781 shell = pw->pw_shell;
782 }
783
784 if (!NeoMutt->username)
785 {
786 mutt_error(_("unable to determine username"));
787 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
788 }
789
790 if (!NeoMutt->home_dir)
791 {
792 mutt_error(_("unable to determine home directory"));
793 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
794 }
795
796 if (shell)
797 config_str_set_initial(cs, "shell", shell);
798
799 return true;
800}
801
809static void log_translation(void)
810{
811 const char *header = ""; // Do not merge these two lines
812 header = _(header); // otherwise the .po files will end up badly ordered
813 const char *label = "Language:"; // the start of the lookup/needle
814 const char *lang = mutt_istr_find(header, label);
815 int len = 64;
816 if (lang)
817 {
818 lang += strlen(label); // skip label
819 SKIPWS(lang);
820 const char *nl = strchr(lang, '\n');
821 if (nl)
822 len = (nl - lang);
823 }
824 else
825 {
826 lang = "NONE";
827 }
828
829 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
830}
831
836{
837 static time_t last_run = 0;
838
839 if (nc->event_type != NT_TIMEOUT)
840 return 0;
841
842 const short c_timeout = cs_subset_number(NeoMutt->sub, "timeout");
843 if (c_timeout <= 0)
844 goto done;
845
846 time_t now = mutt_date_now();
847 if (now < (last_run + c_timeout))
848 goto done;
849
850 // Limit hook to running under the Index or Pager
852 struct MuttWindow *dlg = dialog_find(focus);
853 if (!dlg || (dlg->type != WT_DLG_INDEX))
854 goto done;
855
856 last_run = now;
858
859done:
860 mutt_debug(LL_DEBUG5, "timeout done\n");
861 return 0;
862}
863
869static bool show_help(struct CliHelp *help)
870{
871 if (!help->is_set)
872 return true;
873
875
876 const bool tty = isatty(STDOUT_FILENO);
877
878 if (help->help)
879 {
880 show_cli(help->mode, tty);
881 }
882 else if (help->license)
883 {
885 }
886 else
887 {
888 print_version(stdout, tty);
889 }
890
891 return false; // Stop
892}
893
900static bool init_logging(struct CliShared *shared, struct ConfigSet *cs)
901{
902 if (!shared->is_set)
903 return true;
904
905 if (!buf_is_empty(&shared->log_file))
906 config_str_set_initial(cs, "debug_file", buf_string(&shared->log_file));
907
908 if (!buf_is_empty(&shared->log_level))
909 {
910 const char *dlevel = buf_string(&shared->log_level);
911 short num = 0;
912 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
913 {
914 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
915 return false;
916 }
917
918 config_str_set_initial(cs, "debug_level", dlevel);
919 }
920
921 return true;
922}
923
929static void init_nntp(struct Buffer *server, struct ConfigSet *cs)
930{
931 const char *cli_nntp = NULL;
932 if (!buf_is_empty(server))
933 cli_nntp = buf_string(server);
934
935 /* "$news_server" precedence: command line, config file, environment, system file */
936 if (!cli_nntp)
937 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
938
939 if (!cli_nntp)
940 cli_nntp = mutt_str_getenv("NNTPSERVER");
941
942 if (!cli_nntp)
943 {
944 char buf[1024] = { 0 };
945 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
946 }
947
948 if (cli_nntp)
949 config_str_set_initial(cs, "news_server", cli_nntp);
950}
951
958static bool dump_info(struct CliInfo *ci, struct ConfigSet *cs)
959{
960 if (!ci->is_set)
961 return true;
962
963 if (ci->dump_config || !ARRAY_EMPTY(&ci->queries))
964 {
965 const bool tty = isatty(STDOUT_FILENO);
966
968 if (tty)
969 cdflags |= CS_DUMP_LINK_DOCS;
970 if (ci->hide_sensitive)
971 cdflags |= CS_DUMP_HIDE_SENSITIVE;
972 if (ci->show_help)
973 cdflags |= CS_DUMP_SHOW_DOCS;
974
975 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
976 if (ci->dump_config)
977 {
979 hea = get_elem_list(cs, gel_flags);
980 }
981 else
982 {
983 get_elem_queries(&ci->queries, &hea);
984 }
985
986 dump_config(cs, &hea, cdflags, stdout);
987 ARRAY_FREE(&hea);
988 }
989 else if (!ARRAY_EMPTY(&ci->alias_queries))
990 {
991 const char **cp = NULL;
993 {
994 struct AddressList *al = alias_lookup(*cp);
995 if (al)
996 {
997 /* output in machine-readable form */
998 mutt_addrlist_to_intl(al, NULL);
999 struct Buffer *buf = buf_pool_get();
1000 mutt_addrlist_write(al, buf, false);
1001 printf("%s\n", buf_string(buf));
1002 buf_pool_release(&buf);
1003 }
1004 else
1005 {
1006 printf("%s\n", NONULL(*cp)); // TEST19: neomutt -A unknown
1007 }
1008 }
1009 }
1010
1011 return false; // Stop
1012}
1013
1022int main(int argc, char *argv[], char *envp[])
1023{
1025
1026 struct Email *e = NULL;
1027 SendFlags sendflags = SEND_NONE;
1028 int rc = 1;
1029 bool repeat_error = false;
1030 struct Buffer *expanded_infile = buf_pool_get();
1031 struct Buffer *tempfile = buf_pool_get();
1032 struct ConfigSet *cs = NULL;
1033 struct CommandLine *cli = command_line_new();
1034
1035 /* sanity check against stupid administrators */
1036 if (getegid() != getgid())
1037 {
1038 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
1039 goto done; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
1040 }
1041
1042 OptGui = true;
1043
1044 NeoMutt = neomutt_new();
1045 if (!neomutt_init(NeoMutt, envp, Modules))
1046 goto done;
1047
1048 cli_parse(argc, argv, cli);
1049
1050 if (!show_help(&cli->help))
1051 {
1052 rc = 0;
1053 goto done;
1054 }
1055
1057
1058#ifdef USE_DEBUG_NOTIFY
1060#endif
1061
1062 cs = NeoMutt->sub->cs;
1063 if (!get_user_info(cs))
1064 goto done;
1065
1066 if (!init_logging(&cli->shared, cs))
1067 goto done;
1068
1069 mutt_log_prep();
1071
1072 /* Check for a batch send. */
1073 if (!isatty(STDIN_FILENO) || !ARRAY_EMPTY(&cli->info.queries) ||
1075 {
1076 OptGui = false;
1077 sendflags |= SEND_BATCH;
1080 }
1081
1082 /* Check to make sure stdout is available in curses mode. */
1083 if (OptGui && !isatty(STDOUT_FILENO))
1084 goto done;
1085
1086 /* This must come before mutt_init() because curses needs to be started
1087 * before calling the init_pair() function to set the color scheme. */
1088 if (OptGui)
1089 {
1090 int crc = start_curses();
1091 if (crc != 0)
1092 goto done; // TEST08: can't test -- fake term?
1093 }
1094
1095 /* Always create the mutt_windows because batch mode has some shared code
1096 * paths that end up referencing them. */
1098 rootwin_new(gui_mod_data);
1099
1100 /* set defaults and read init files */
1101 int rc2 = mutt_init(cs, &cli->shared.log_level, &cli->shared.log_file,
1103 &cli->shared.commands);
1104 if (rc2 != 0)
1105 goto done;
1106
1107 if (OptGui)
1109
1110 init_nntp(&cli->tui.nntp_server, cs);
1111
1112 /* Initialize crypto backends. */
1113 crypt_init();
1114
1115 if (!buf_is_empty(&cli->shared.mbox_type) &&
1116 !config_str_set_initial(cs, "mbox_type", buf_string(&cli->shared.mbox_type)))
1117 {
1118 goto done;
1119 }
1120
1121 if (!dump_info(&cli->info, cs))
1122 {
1123 rc = 0;
1124 goto done;
1125 }
1126
1127#ifdef USE_AUTOCRYPT
1128 /* Initialize autocrypt after curses messages are working,
1129 * because of the initial account setup screens. */
1130 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
1131 if (c_autocrypt)
1132 (void) mutt_autocrypt_init(!(sendflags & SEND_BATCH));
1133#endif
1134
1135 /* Create the `$folder` directory if it doesn't exist. */
1136 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1137 if (OptGui && c_folder)
1138 {
1139 struct stat st = { 0 };
1140 struct Buffer *fpath = buf_pool_get();
1141
1142 buf_strcpy(fpath, c_folder);
1143 expand_path(fpath, false);
1144 bool skip = false;
1145 /* we're not connected yet - skip mail folder creation */
1146 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
1147 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
1148 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
1149 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
1150 {
1151 char msg2[256] = { 0 };
1152 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
1153 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
1154 {
1155 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
1156 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
1157 }
1158 }
1159 buf_pool_release(&fpath);
1160 }
1161
1162 StartupComplete = true;
1163
1167
1168 if (cli->tui.start_postponed)
1169 {
1170 if (OptGui)
1171 mutt_flushinp();
1172 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1173 rc = 0;
1174 // TEST23: neomutt -p (postponed message, cancel)
1175 // TEST24: neomutt -p (no postponed message)
1177 repeat_error = true;
1178 goto done;
1179 }
1180 else if (cli->send.is_set)
1181 {
1182 FILE *fp_in = NULL;
1183 FILE *fp_out = NULL;
1184 const char *infile = NULL;
1185 char *bodytext = NULL;
1186 const char *bodyfile = NULL;
1187 int rv = 0;
1188
1189 if (OptGui)
1190 mutt_flushinp();
1191
1192 if (cli->send.use_crypto)
1193 sendflags |= SEND_CLI_CRYPTO;
1194
1195 e = email_new();
1196 e->env = mutt_env_new();
1197
1198 const char **cp = NULL;
1199 ARRAY_FOREACH(cp, &cli->send.bcc_list)
1200 {
1201 mutt_addrlist_parse(&e->env->bcc, *cp);
1202 }
1203
1204 ARRAY_FOREACH(cp, &cli->send.cc_list)
1205 {
1206 mutt_addrlist_parse(&e->env->cc, *cp);
1207 }
1208
1209 ARRAY_FOREACH(cp, &cli->send.addresses)
1210 {
1211 if (url_check_scheme(*cp) == U_MAILTO)
1212 {
1213 if (!mutt_parse_mailto(e->env, &bodytext, *cp))
1214 {
1215 mutt_error(_("Failed to parse mailto: link"));
1216 email_free(&e);
1217 goto done; // TEST25: neomutt mailto:?
1218 }
1219 }
1220 else
1221 {
1222 mutt_addrlist_parse(&e->env->to, *cp);
1223 }
1224 }
1225
1226 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1227 if (buf_is_empty(&cli->send.draft_file) && c_auto_edit &&
1228 TAILQ_EMPTY(&e->env->to) && TAILQ_EMPTY(&e->env->cc))
1229 {
1230 mutt_error(_("No recipients specified"));
1231 email_free(&e);
1232 goto done; // TEST26: neomutt -s test (with auto_edit=yes)
1233 }
1234
1235 if (!buf_is_empty(&cli->send.subject))
1236 {
1237 /* prevent header injection */
1240 }
1241
1242 if (!buf_is_empty(&cli->send.draft_file))
1243 {
1244 infile = buf_string(&cli->send.draft_file);
1245 }
1246 else if (!buf_is_empty(&cli->send.include_file))
1247 {
1248 infile = buf_string(&cli->send.include_file);
1249 }
1250 else
1251 {
1252 cli->send.edit_infile = false;
1253 }
1254
1255 if (infile || bodytext)
1256 {
1257 /* Prepare fp_in and expanded_infile. */
1258 if (infile)
1259 {
1260 if (mutt_str_equal("-", infile))
1261 {
1262 if (cli->send.edit_infile)
1263 {
1264 mutt_error(_("Can't use -E flag with stdin"));
1265 email_free(&e);
1266 goto done; // TEST27: neomutt -E -H -
1267 }
1268 fp_in = stdin;
1269 }
1270 else
1271 {
1272 buf_strcpy(expanded_infile, infile);
1273 expand_path(expanded_infile, false);
1274 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1275 if (!fp_in)
1276 {
1277 mutt_perror("%s", buf_string(expanded_infile));
1278 email_free(&e);
1279 goto done; // TEST28: neomutt -E -H missing
1280 }
1281 }
1282 }
1283
1284 if (cli->send.edit_infile)
1285 {
1286 /* If editing the infile, keep it around afterwards so
1287 * it doesn't get unlinked, and we can rebuild the draft_file */
1288 sendflags |= SEND_NO_FREE_HEADER;
1289 }
1290 else
1291 {
1292 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1293 * Note: stdin is always copied to a tempfile, ensuring draft_file
1294 * can stat and get the correct st_size below. */
1295 buf_mktemp_draft(tempfile);
1296
1297 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1298 if (!fp_out)
1299 {
1300 mutt_file_fclose(&fp_in);
1301 mutt_perror("%s", buf_string(tempfile));
1302 email_free(&e);
1303 goto done; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1304 }
1305 if (fp_in)
1306 {
1307 mutt_file_copy_stream(fp_in, fp_out);
1308 if (fp_in == stdin)
1309 sendflags |= SEND_CONSUMED_STDIN;
1310 else
1311 mutt_file_fclose(&fp_in);
1312 }
1313 else if (bodytext)
1314 {
1315 fputs(bodytext, fp_out);
1316 }
1317 mutt_file_fclose(&fp_out);
1318
1319 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1320 if (!fp_in)
1321 {
1322 mutt_perror("%s", buf_string(tempfile));
1323 email_free(&e);
1324 goto done; // TEST30: can't test
1325 }
1326 }
1327
1328 /* Parse the draft_file into the full Email/Body structure.
1329 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1330 * our e->body. */
1331 if (!buf_is_empty(&cli->send.draft_file))
1332 {
1333 struct Envelope *opts_env = e->env;
1334 struct stat st = { 0 };
1335
1336 sendflags |= SEND_DRAFT_FILE;
1337
1338 /* Set up a tmp Email with just enough information so that
1339 * mutt_prepare_template() can parse the message in fp_in. */
1340 struct Email *e_tmp = email_new();
1341 e_tmp->offset = 0;
1342 e_tmp->body = mutt_body_new();
1343 if (fstat(fileno(fp_in), &st) != 0)
1344 {
1345 mutt_perror("%s", buf_string(&cli->send.draft_file));
1346 email_free(&e);
1347 email_free(&e_tmp);
1348 goto done; // TEST31: can't test
1349 }
1350 e_tmp->body->length = st.st_size;
1351
1352 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1353 {
1354 mutt_error(_("Can't parse message template: %s"),
1355 buf_string(&cli->send.draft_file));
1356 email_free(&e);
1357 email_free(&e_tmp);
1358 goto done;
1359 }
1360
1361 /* Scan for neomutt header to set `$resume_draft_files` */
1362 struct ListNode *tmp = NULL;
1363 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1364 struct ListNode *np = NULL;
1365 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1366 {
1367 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1368 {
1369 if (c_resume_edited_draft_files)
1370 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1371
1372 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1373 FREE(&np->data);
1374 FREE(&np);
1375 }
1376 }
1377
1378 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1379 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1380 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1381 if (opts_env->subject)
1382 mutt_env_set_subject(e->env, opts_env->subject);
1383
1384 mutt_env_free(&opts_env);
1385 email_free(&e_tmp);
1386 }
1387 else if (cli->send.edit_infile)
1388 {
1389 /* Editing the include_file: pass it directly in.
1390 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1391 bodyfile = buf_string(expanded_infile);
1392 }
1393 else
1394 {
1395 // For bodytext and unedited include_file: use the tempfile.
1396 bodyfile = buf_string(tempfile);
1397 }
1398
1399 mutt_file_fclose(&fp_in);
1400 }
1401
1402 FREE(&bodytext);
1403
1404 if (!ARRAY_EMPTY(&cli->send.attach))
1405 {
1406 struct Body *b = e->body;
1407
1408 while (b && b->next)
1409 b = b->next;
1410
1411 ARRAY_FOREACH(cp, &cli->send.attach)
1412 {
1413 if (b)
1414 {
1416 b = b->next;
1417 }
1418 else
1419 {
1421 e->body = b;
1422 }
1423 if (!b)
1424 {
1425 mutt_error(_("%s: unable to attach file"), *cp);
1426 email_free(&e);
1427 goto done; // TEST32: neomutt john@example.com -a missing
1428 }
1429 }
1430 }
1431
1432 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1433 /* We WANT the "Mail sent." and any possible, later error */
1435 if (ErrorBufMessage)
1436 mutt_message("%s", ErrorBuf);
1437
1438 if (cli->send.edit_infile)
1439 {
1440 if (!buf_is_empty(&cli->send.draft_file))
1441 {
1442 if (truncate(buf_string(expanded_infile), 0) == -1)
1443 {
1444 mutt_perror("%s", buf_string(expanded_infile));
1445 email_free(&e);
1446 goto done; // TEST33: neomutt -H read-only -s test john@example.com -E
1447 }
1448 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1449 if (!fp_out)
1450 {
1451 mutt_perror("%s", buf_string(expanded_infile));
1452 email_free(&e);
1453 goto done; // TEST34: can't test
1454 }
1455
1456 /* If the message was sent or postponed, these will already
1457 * have been done. */
1458 if (rv < 0)
1459 {
1460 if (e->body->next)
1461 e->body = mutt_make_multipart(e->body);
1463 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1464 mutt_env_to_intl(e->env, NULL, NULL);
1465 }
1466
1467 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1469 c_crypt_protected_headers_read &&
1471 NeoMutt->sub);
1472 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1473 if (c_resume_edited_draft_files)
1474 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1475 fputc('\n', fp_out);
1476 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1477 {
1478 mutt_file_fclose(&fp_out);
1479 email_free(&e);
1480 goto done; // TEST35: can't test
1481 }
1482 mutt_file_fclose(&fp_out);
1483 }
1484
1485 email_free(&e);
1486 }
1487
1488 /* !edit_infile && draft_file will leave the tempfile around */
1489 if (!buf_is_empty(tempfile))
1490 unlink(buf_string(tempfile));
1491
1492 rootwin_cleanup(gui_mod_data);
1493
1494 if (rv != 0)
1495 goto done; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1496 }
1497 else if (sendflags & SEND_BATCH)
1498 {
1499 /* This guards against invoking `neomutt < /dev/null` and accidentally
1500 * sending an email due to a my-header or other setting. */
1501 mutt_error(_("No recipients specified"));
1502 goto done;
1503 }
1504 else
1505 {
1506 struct Buffer *folder = &cli->tui.folder;
1507 bool explicit_folder = !buf_is_empty(folder);
1508
1509 if (cli->tui.start_new_mail)
1510 {
1511 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1512 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1514 if (mutt_mailbox_check(NULL, csflags) == 0)
1515 {
1516 mutt_message(_("No mailbox with new mail"));
1517 goto done; // TEST37: neomutt -Z (no new mail)
1518 }
1519 buf_reset(folder);
1520 mutt_mailbox_next(NULL, folder);
1521 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1522 }
1523 else if (cli->tui.start_nntp || cli->tui.start_browser)
1524 {
1525 if (cli->tui.start_nntp)
1526 {
1528 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1529 OptNews = true;
1530 mod_data->current_news_srv = nntp_select_server(NULL, c_news_server, false);
1531 if (!mod_data->current_news_srv)
1532 goto done; // TEST38: neomutt -G (unset news_server)
1533 }
1534 else if (ARRAY_EMPTY(&NeoMutt->accounts))
1535 {
1536 mutt_error(_("No incoming mailboxes defined"));
1537 goto done; // TEST39: neomutt -n -F /dev/null -y
1538 }
1539 buf_reset(folder);
1540 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1541 if (buf_is_empty(folder))
1542 {
1543 rc = 0;
1544 goto done; // TEST40: neomutt -y (quit selection)
1545 }
1546 }
1547
1548 if (buf_is_empty(folder))
1549 {
1550 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1551 if (c_spool_file)
1552 {
1553 // Check if `$spool_file` corresponds a mailboxes' description.
1554 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1555 if (m_desc)
1556 buf_strcpy(folder, m_desc->realpath);
1557 else
1558 buf_strcpy(folder, c_spool_file);
1559 }
1560 else if (c_folder)
1561 {
1562 buf_strcpy(folder, c_folder);
1563 }
1564 /* else no folder */
1565 }
1566
1567 if (OptNews)
1568 {
1570 OptNews = false;
1571 buf_alloc(folder, PATH_MAX);
1572 nntp_expand_path(folder->data, folder->dsize,
1573 &mod_data->current_news_srv->conn->account);
1574 }
1575 else
1576 {
1577 expand_path(folder, false);
1578 }
1579
1582
1583 if (cli->tui.start_any_mail || cli->tui.start_new_mail)
1584 {
1585 /* check to see if there are any messages in the folder */
1586 switch (mx_path_is_empty(folder))
1587 {
1588 case -1:
1589 mutt_perror("%s", buf_string(folder));
1590 goto done; // TEST41: neomutt -z -f missing
1591 case 1:
1592 mutt_error(_("Mailbox is empty"));
1593 goto done; // TEST42: neomutt -z -f /dev/null
1594 }
1595 }
1596
1597 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1598 // Take a copy of the name just in case the hook alters m_cur
1599 const char *name = m_cur ? mutt_str_dup(m_cur->name) : NULL;
1601 FREE(&name);
1603 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1605
1607 window_redraw(NULL);
1608
1609 repeat_error = true;
1610 struct Mailbox *m = mx_resolve(buf_string(folder));
1611 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1612 if (!mx_mbox_open(m, (cli->tui.read_only || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NONE))
1613 {
1614 if (m->account)
1616
1617 mailbox_free(&m);
1618 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1619 repeat_error = false;
1620 }
1621 if (m || !explicit_folder)
1622 {
1623 struct MuttWindow *dlg = index_pager_init();
1624 dialog_push(dlg);
1625
1627 m = dlg_index(dlg, m);
1629 mailbox_free(&m);
1630
1631 dialog_pop();
1632 mutt_window_free(&dlg);
1634 repeat_error = false;
1635 }
1637 // TEST43: neomutt (no change to mailbox)
1638 // TEST44: neomutt (change mailbox)
1639 }
1640 rc = 0;
1641
1642done:
1644 /* Repeat the last message to the user */
1645 if (repeat_error && ErrorBufMessage)
1646 puts(ErrorBuf);
1647
1648 if (NeoMutt && NeoMutt->sub)
1649 {
1653 }
1654
1655 buf_pool_release(&expanded_infile);
1656 buf_pool_release(&tempfile);
1657 if (NeoMutt)
1661 command_line_free(&cli);
1662
1664
1666 FREE(&LastFolder);
1668
1676 mutt_log_stop();
1677 return rc;
1678}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:776
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1219
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:481
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1306
Email Address Handling.
const struct Module ModuleAddress
Module for the Address library.
Definition module.c:94
void alias_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Alias Keybindings - Implements ::init_keys_api.
Definition functions.c:120
Email Aliases.
const struct Module ModuleAlias
Module for the Alias library.
Definition module.c:128
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:274
#define ARRAY_SET(head, idx, elem)
Set an element in the array.
Definition array.h:123
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
void attach_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Attach Keybindings - Implements ::init_keys_api.
Definition functions.c:123
GUI display the mailboxes in a side panel.
const struct Module ModuleAttach
Module for the Attach library.
Definition module.c:111
void autocrypt_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Autocrypt Keybindings - Implements ::init_keys_api.
Definition functions.c:73
Autocrypt end-to-end encryption.
const struct Module ModuleAutocrypt
Module for the Autocrypt library.
Definition module.c:91
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition autocrypt.c:104
const struct Module ModuleBcache
Module for the Bcache library.
Definition module.c:66
void browser_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Browser Keybindings - Implements ::init_keys_api.
Definition functions.c:127
Select a Mailbox from a list.
@ MUTT_SEL_MAILBOX
Select a mailbox.
Definition lib.h:60
@ MUTT_SEL_FOLDER
Select a local directory.
Definition lib.h:62
const struct Module ModuleBrowser
Module for the Browser library.
Definition module.c:91
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition buffer.c:628
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:515
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:342
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
Parse the Command Line.
bool cli_parse(int argc, char *const *argv, struct CommandLine *cli)
Parse the Command Line.
Definition parse.c:148
Color and attribute parsing.
const struct Module ModuleColor
Module for the Color library.
Definition module.c:104
void colors_init(struct ColorModuleData *mod_data)
Initialize colours.
Definition color.c:51
@ CMD_MY_HEADER
:my-header
Definition command.h:100
@ CMD_STARTUP_HOOK
:startup-hook
Definition command.h:118
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
const struct Command * command_find_by_id(const struct CommandArray *ca, enum CommandId id)
Find a NeoMutt Command by its CommandId.
Definition commands.c:120
NeoMutt Commands.
const struct Module ModuleCommands
Module for the Commands library.
Definition module.c:78
const struct Module ModuleComplete
Module for the Complete library.
Definition module.c:66
const struct Module ModuleCompmbox
Module for the Compmbox library.
Definition module.c:76
void compose_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Compose Keybindings - Implements ::init_keys_api.
Definition functions.c:212
GUI editor for an email's headers.
const struct Module ModuleCompose
Module for the Compose library.
Definition module.c:77
const struct Module ModuleCompress
Module for the Compress library.
Definition module.c:66
bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition dump.c:198
@ CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition dump.h:50
@ CS_DUMP_NONE
No flags are set.
Definition dump.h:40
@ CS_DUMP_LINK_DOCS
Link to the online docs.
Definition dump.h:51
@ CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition dump.h:42
uint16_t ConfigDumpFlags
Definition dump.h:53
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
bool config_str_set_initial(struct ConfigSet *cs, const char *name, const char *value)
Set the initial value of a Config Option.
Definition helpers.c:332
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
const struct Module ModuleConfig
Module for the Config library.
Definition module.c:103
int cs_str_initial_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition set.c:618
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition set.c:447
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition set.c:693
int cs_str_native_set(const struct ConfigSet *cs, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition set.c:813
bool StartupComplete
When the config has been read.
Definition address.c:11
void config_cache_cleanup(void)
Cleanup the cache of charset config variables.
Connection Library.
const struct Module ModuleConn
Module for the Conn library.
Definition module.c:128
const struct Module ModuleConvert
Module for the Convert library.
Definition module.c:66
void account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition account.c:94
Convenience wrapper for the core headers.
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition mailbox.c:187
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:151
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:51
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:48
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
const struct Module ModuleCore
Module for the Core library.
Definition module.c:67
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition crypt.c:1106
void crypt_init(void)
Initialise the crypto backends.
Definition cryptglue.c:99
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
Convenience wrapper for the debug headers.
int debug_all_observer(struct NotifyCallback *nc)
Debug observer for all notifications.
Definition notify.c:237
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition dialog.c:109
void dialog_pop(void)
Hide a Window from the user.
Definition dialog.c:148
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition dialog.c:89
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition dlg_index.c:1462
void editor_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Editor Keybindings - Implements ::init_keys_api.
Definition functions.c:127
Edit a string.
const struct Module ModuleEditor
Module for the Editor library.
Definition module.c:66
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
Structs that make up an email.
const struct Module ModuleEmail
Module for the Email library.
Definition module.c:127
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
Definition parse.c:1878
void mutt_filter_commandline_header_value(char *header)
Sanitise characters in a header value.
Definition parse.c:93
const struct Module ModuleEnvelope
Module for the Envelope library.
Definition module.c:66
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope's Address fields to Punycode format.
Definition envelope.c:350
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition envelope.c:68
void envlist_free(char ***envp)
Free the private copy of the environment.
Definition envlist.c:42
const struct Module ModuleExpando
Module for the Expando library.
Definition module.c:77
void ext_keys_init(struct Mapping *key_names)
Initialise map of ncurses extended keys.
Definition extended.c:114
void external_cleanup(void)
Clean up commands globals.
Definition external.c:77
Manage where the email is piped to external commands.
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
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:678
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition file.c:1299
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition file.c:844
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
@ MUTT_RL_NONE
No flags are set.
Definition file.h:43
void sidebar_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Sidebar Keybindings - Implements ::init_keys_api.
const struct Module ModulePop
Module for the Pop library.
Definition module.c:77
const struct Module ModuleParse
Module for the Parse library.
Definition module.c:66
const struct Module ModuleMaildir
Module for the Maildir library.
Definition module.c:84
const struct Module ModulePostpone
Module for the Postpone library.
Definition module.c:66
const struct Module ModuleSidebar
Module for the Sidebar library.
Definition module.c:111
const struct Module ModuleMh
Module for the Mh library.
Definition module.c:77
const struct Module ModuleLua
Module for the Lua library.
Definition module.c:84
const struct Module ModulePager
Module for the Pager library.
Definition module.c:80
const struct Module ModuleGui
Module for the Gui library.
Definition module.c:145
const struct Module ModuleProgress
Module for the Progress library.
Definition module.c:77
const struct Module ModuleMenu
Module for the Menu library.
Definition module.c:101
static const struct Module * Modules[]
All the library Modules.
Definition address.c:32
const struct Module ModuleNcrypt
Module for the Ncrypt library.
Definition module.c:105
const struct Module ModuleMutt
Module for the Mutt library.
Definition module.c:67
const struct Module ModuleHcache
Module for the Hcache library.
Definition module.c:86
const struct Module ModuleSend
Module for the Send library.
Definition module.c:91
const struct Module ModuleQuestion
Module for the Question library.
Definition module.c:66
const struct Module ModuleImap
Module for the Imap library.
Definition module.c:96
const struct Module ModuleMain
Module for the Main library.
Definition module.c:63
const struct Module ModuleStore
Module for the Store library.
Definition module.c:66
const struct Module ModuleMbox
Module for the Mbox library.
Definition module.c:77
const struct Module ModulePattern
Module for the Pattern library.
Definition module.c:93
const struct Module ModuleNntp
Module for the Nntp library.
Definition module.c:77
const struct Module ModuleHelpbar
Module for the Helpbar library.
Definition module.c:77
const struct Module ModuleHistory
Module for the History library.
Definition module.c:98
const struct Module ModuleNotmuch
Module for the Notmuch library.
Definition module.c:118
const struct Module ModuleKey
Module for the Key library.
Definition module.c:98
const struct Module ModuleIndex
Module for the Index library.
Definition module.c:91
const struct Module ModuleHooks
Module for the Hooks library.
Definition module.c:92
void fuzzy_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Fuzzy Keybindings - Implements ::init_keys_api.
Definition functions.c:70
Fuzzy matching library.
const struct Module ModuleFuzzy
Module for the Fuzzy library.
Definition module.c:61
void mutt_flushinp(void)
MacroEvents moved to KeyModuleData UngetKeyEvents moved to KeyModuleData.
Definition get.c:81
int getdnsdomainname(struct Buffer *result)
Lookup the host's name using DNS.
Definition getdomain.c:124
bool OptNews
(pseudo) used to change reader mode
Definition globals.c:53
char * LastFolder
Previously selected mailbox.
Definition globals.c:39
char * ShortHostname
Short version of the hostname.
Definition globals.c:36
char ErrorBuf[1024]
Copy of the last error message.
Definition globals.c:34
bool ErrorBufMessage
true if the last message was an error
Definition globals.c:33
char * CurrentFolder
Currently selected mailbox.
Definition globals.c:38
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:48
Global variables.
enum CommandResult parse_my_header(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'my-header' command - Implements Command::parse() -.
Definition my_header.c:52
void dlg_browser(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file -.
struct Mailbox * dlg_index(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails -.
Definition dlg_index.c:1121
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Save a log line to an internal queue - Implements log_dispatcher_t -.
Definition logging.c:384
#define mutt_warning(...)
Definition logging2.h:92
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition logging.c:427
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox?
Definition nntp.c:2797
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox?
Definition pop.c:1177
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2683
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has change - Implements observer_t -.
Definition history.c:693
static int main_timeout_observer(struct NotifyCallback *nc)
Notification that a timeout has occurred - Implements observer_t -.
Definition main.c:835
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
struct SubMenu * generic_init_keys(struct NeoMutt *n)
Initialise the Generic Keybindings.
Definition functions.c:154
Convenience wrapper for the gui headers.
Read/write command history from/to a file.
void exec_startup_shutdown_hook(enum CommandId id)
Execute any startup/shutdown hooks.
Definition exec.c:418
void exec_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition exec.c:64
void exec_timeout_hook(void)
Execute any timeout hooks.
Definition exec.c:378
Hook Commands.
IMAP network mailbox.
void imap_logout_all(void)
Close all open connections.
Definition imap.c:667
void index_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Index Keybindings - Implements ::init_keys_api.
Definition functions.c:327
GUI manage the main index (list of emails)
void km_sort(void)
Sort all the menu keybindings.
Definition init.c:195
Manage keymappings.
int log_dispatcher_t MuttLogger
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
@ LL_MESSAGE
Log informational message.
Definition logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:50
@ LL_MAX
Definition logging2.h:52
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition main.c:254
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition main.c:301
static bool init_logging(struct CliShared *shared, struct ConfigSet *cs)
Initialise the Logging.
Definition main.c:900
static void log_translation(void)
Log the translation being used.
Definition main.c:809
static void init_nntp(struct Buffer *server, struct ConfigSet *cs)
Initialise the NNTP config.
Definition main.c:929
static bool show_help(struct CliHelp *help)
Show the Help.
Definition main.c:869
static int start_curses(void)
Start the Curses UI.
Definition main.c:731
static bool dump_info(struct CliInfo *ci, struct ConfigSet *cs)
Show config info.
Definition main.c:958
static void init_keys(struct NeoMutt *n)
Initialise the Keybindings.
Definition main.c:703
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition main.c:768
const struct Module ModuleMlist
Module for the Mlist library.
Definition module.c:64
void show_cli(enum HelpMode mode, bool use_color)
Show Instructions on how to run NeoMutt.
Definition usage.c:336
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition main.c:334
static int get_elem_queries(struct StringArray *queries, struct HashElemArray *hea)
Lookup the HashElems for a set of queries.
Definition main.c:673
static int execute_commands(struct StringArray *sa)
Execute a set of NeoMutt commands.
Definition main.c:215
int main(int argc, char *argv[], char *envp[])
Start NeoMutt.
Definition main.c:1022
static int mutt_init(struct ConfigSet *cs, struct Buffer *dlevel, struct Buffer *dfile, bool skip_sys_rc, struct StringArray *user_files, struct StringArray *commands)
Initialise NeoMutt.
Definition main.c:420
#define countof(x)
Definition memory.h:49
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
void mlist_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Mlist Keybindings - Implements ::init_keys_api.
Definition functions.c:90
Mailing-list action dialog.
@ MODULE_ID_COLOR
ModuleColor, Color
Definition module_api.h:53
@ MODULE_ID_GUI
ModuleGui, Graphical code
Definition module_api.h:45
@ MODULE_ID_KEY
ModuleKey, Key mappings
Definition module_api.h:74
@ MODULE_ID_NNTP
ModuleNntp, Nntp
Definition module_api.h:83
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition multipart.c:107
char * mutt_ch_get_langinfo_charset(void)
Get the user's choice of character set.
Definition charset.c:473
void mutt_ch_cache_cleanup(void)
Clean up the cached iconv handles and charset strings.
Definition charset.c:1165
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition charset.c:1063
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:459
Convenience wrapper for the library headers.
void log_queue_empty(void)
Free the contents of the queue.
Definition logging.c:331
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition logging.c:353
#define _(a)
Definition message.h:28
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition notify.c:230
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition notify.c:191
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition slist.c:177
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition slist.c:124
int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
Export an Slist to a Buffer.
Definition slist.c:269
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:384
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:809
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition string.c:732
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:528
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
Many unsorted constants and some structs.
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition mutt.h:68
void mutt_signal_init(void)
Initialise the signal handling.
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition muttlib.c:828
#define PATH_MAX
Definition mutt.h:49
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition mutt_curses.c:94
@ MUTT_CURSOR_INVISIBLE
Hide the cursor.
Definition mutt_curses.h:65
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition mutt_curses.h:66
void mutt_log_stop(void)
Close the log file.
int mutt_log_start(void)
Enable file logging.
void mutt_log_prep(void)
Prepare to log.
NeoMutt Logging.
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Mailbox helper functions.
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
struct MuttWindow * window_get_focus(void)
Get the currently focused Window.
@ WT_DLG_INDEX
Index Dialog, dlg_index()
Definition mutt_window.h:86
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition muttlib.c:321
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
Some miscellaneous functions.
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition mx.c:1722
int mx_path_is_empty(struct Buffer *path)
Is the mailbox empty.
Definition mx.c:1257
API for mailboxes.
@ MUTT_READONLY
Open in read-only mode.
Definition mxapi.h:45
@ MUTT_OPEN_NONE
No flags are set.
Definition mxapi.h:42
@ MUTT_MAILBOX_CHECK_IMMEDIATE
Don't postpone the actual checking.
Definition mxapi.h:61
uint8_t CheckStatsFlags
Definition mxapi.h:63
void pgp_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the PGP Keybindings - Implements ::init_keys_api.
Definition functions.c:84
API for encryption/signing of emails.
void neomutt_cleanup(struct NeoMutt *n)
Clean up NeoMutt and Modules.
Definition neomutt.c:474
bool neomutt_init(struct NeoMutt *n, char **envp, const struct Module **modules)
Initialise NeoMutt.
Definition neomutt.c:350
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
void neomutt_gui_cleanup(struct NeoMutt *n)
Clean up the GUI Modules.
Definition neomutt.c:489
struct NeoMutt * neomutt_new(void)
Create the main NeoMutt object.
Definition neomutt.c:338
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition neomutt.c:501
bool neomutt_gui_init(struct NeoMutt *n)
Initialise the GUI Modules.
Definition neomutt.c:400
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition neomutt.h:69
Nntp-specific Account data.
Usenet network mailbox type; talk to an NNTP server.
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition newsrc.c:559
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition newsrc.c:957
@ NT_TIMEOUT
Timeout has occurred.
Definition notify_type.h:57
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition notify_type.h:43
@ NT_ALL
Register for all notifications.
Definition notify_type.h:35
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition notify_type.h:46
@ NT_RESIZE
Window has been resized.
Definition notify_type.h:53
struct CommandLine * command_line_new(void)
Create a new CommandLine.
Definition objects.c:105
void command_line_free(struct CommandLine **ptr)
Free a CommandLine.
Definition objects.c:114
HelpMode
Show detailed help.
Definition objects.h:33
void pager_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Pager Keybindings - Implements ::init_keys_api.
Definition functions.c:108
GUI display a file/email/help in a viewport with paging.
Text parsing functions.
void parse_context_free(struct ParseContext **pptr)
Free a ParseContext.
Definition pcontext.c:48
struct ParseContext * parse_context_new(void)
Create a new ParseContext.
Definition pcontext.c:37
void parse_error_free(struct ParseError **pptr)
Free a ParseError.
Definition perror.c:50
struct ParseError * parse_error_new(void)
Create a new ParseError.
Definition perror.c:37
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
void buf_pool_cleanup(void)
Release the Buffer pool.
Definition pool.c:75
POP network mailbox.
void postpone_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Postponed Keybindings - Implements ::init_keys_api.
Definition functions.c:69
Postponed Emails.
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition postpone.c:490
void mutt_prex_cleanup(void)
Cleanup heap memory allocated by compiled regexes.
Definition prex.c:342
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
Ask the user a question.
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
#define STAILQ_REMOVE(head, elm, type, field)
Definition queue.h:441
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:400
#define TAILQ_EMPTY(head)
Definition queue.h:778
enum CommandResult parse_rc_line(struct Buffer *line, struct ParseContext *pc, struct ParseError *pe)
Parse a line of user config.
Definition rc.c:45
void rootwin_new(struct GuiModuleData *mod_data)
Create the default Windows.
Definition rootwin.c:229
void rootwin_cleanup(struct GuiModuleData *mod_data)
Free all the default Windows.
Definition rootwin.c:211
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition body.c:304
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *b, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition header.c:584
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition header.h:40
Convenience wrapper for the send headers.
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
RFC2047 encode the content-descriptions.
Definition send.c:1501
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition send.c:2031
uint32_t SendFlags
Definition send.h:64
@ SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
Definition send.h:61
@ SEND_NO_FREE_HEADER
Used by the -E flag.
Definition send.h:55
@ SEND_NONE
No flags are set.
Definition send.h:45
@ SEND_BATCH
Send email in batch mode (without user interaction)
Definition send.h:51
@ SEND_CLI_CRYPTO
Enable message security in modes that by default don't enable it.
Definition send.h:62
@ SEND_DRAFT_FILE
Used by the -H flag.
Definition send.h:56
@ SEND_POSTPONED
Recall a postponed email.
Definition send.h:50
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition sendlib.c:617
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition sendlib.c:750
GUI display the mailboxes in a side panel.
#define ASSERT(COND)
Definition signal2.h:59
int endwin(void)
void source_stack_cleanup(void)
Free memory from the stack used for the source command.
Definition source.c:274
int source_rc(const char *rcfile_path, struct ParseContext *pc, struct ParseError *pe)
Read an initialization file.
Definition source.c:64
#define NONULL(x)
Definition string2.h:44
#define SKIPWS(ch)
Definition string2.h:52
The body of an email.
Definition body.h:36
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition body.h:68
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
struct Body * next
next attachment in the list
Definition body.h:72
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
Help Mode Command Line options.
Definition objects.h:64
bool license
-vv Print license
Definition objects.h:68
enum HelpMode mode
Display detailed help.
Definition objects.h:70
bool help
-h Print help
Definition objects.h:66
bool is_set
This struct has been used.
Definition objects.h:65
Info Mode Command Line options.
Definition objects.h:77
bool show_help
-O Show one-liner help
Definition objects.h:81
bool is_set
This struct has been used.
Definition objects.h:78
struct StringArray queries
-Q Query a config option
Definition objects.h:85
struct StringArray alias_queries
-A Lookup an alias
Definition objects.h:84
bool dump_config
-D Dump the config options
Definition objects.h:79
bool dump_changed
-DD Dump the changed config options
Definition objects.h:80
bool hide_sensitive
-S Hide sensitive config
Definition objects.h:82
struct Buffer draft_file
-H Use this draft file
Definition objects.h:102
bool is_set
This struct has been used.
Definition objects.h:93
struct Buffer include_file
-i Use this include file
Definition objects.h:103
struct StringArray cc_list
-c Add a Cc:
Definition objects.h:99
struct StringArray attach
-a Attach a file
Definition objects.h:97
bool use_crypto
-C Use CLI crypto
Definition objects.h:94
bool edit_infile
-E Edit the draft/include
Definition objects.h:95
struct StringArray bcc_list
-b Add a Bcc:
Definition objects.h:98
struct StringArray addresses
Send to these addresses.
Definition objects.h:100
struct Buffer subject
-s Use this Subject:
Definition objects.h:104
Shared Command Line options.
Definition objects.h:47
struct Buffer log_level
-d Debug log level
Definition objects.h:56
struct Buffer log_file
-l Debug log file
Definition objects.h:57
struct StringArray commands
-e Run these commands
Definition objects.h:53
bool is_set
This struct has been used.
Definition objects.h:48
bool disable_system
-n Don't read the system config file
Definition objects.h:51
struct StringArray user_files
-F Use these user config files
Definition objects.h:50
struct Buffer mbox_type
-m Set the default Mailbox type
Definition objects.h:54
bool read_only
-R Open Mailbox read-only
Definition objects.h:113
bool start_any_mail
-z Check for Any Mail
Definition objects.h:118
bool start_nntp
-G Open an NNTP Mailbox
Definition objects.h:116
struct Buffer nntp_server
-g Open this NNTP Mailbox
Definition objects.h:121
struct Buffer folder
-f Open this Mailbox
Definition objects.h:120
bool start_postponed
-p Open Postponed emails
Definition objects.h:114
bool start_new_mail
-Z Check for New Mail
Definition objects.h:117
bool start_browser
-y Open the Mailbox Browser
Definition objects.h:115
Color private Module data.
Definition module_data.h:35
Command Line options.
Definition objects.h:128
struct CliSend send
Send Mode command line options.
Definition objects.h:132
struct CliShared shared
Shared command line options.
Definition objects.h:129
struct CliHelp help
Help Mode command line options.
Definition objects.h:130
struct CliInfo info
Info Mode command line options.
Definition objects.h:131
struct CliTui tui
Tui Mode command line options.
Definition objects.h:133
Container for lots of config items.
Definition set.h:251
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition subset.h:51
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
struct Body * body
List of MIME parts.
Definition email.h:69
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
The header of an Email.
Definition envelope.h:57
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
char *const subject
Email's subject.
Definition envelope.h:70
struct AddressList to
Email's 'To' list.
Definition envelope.h:60
struct AddressList cc
Email's 'Cc' list.
Definition envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition envelope.h:62
Gui private Module data.
Definition module_data.h:32
The item stored in a Hash Table.
Definition hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
Key private Module data.
Definition module_data.h:34
struct Mapping * key_names
Key name lookup table.
Definition module_data.h:41
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
A mailbox.
Definition mailbox.h:81
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:83
char * name
A short name for the Mailbox.
Definition mailbox.h:84
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:129
struct MuttWindow * focus
Focused Window.
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct AccountArray accounts
All Accounts.
Definition neomutt.h:50
struct CommandArray commands
NeoMutt commands.
Definition neomutt.h:53
struct Notify * notify_resize
Window resize notifications handler.
Definition neomutt.h:46
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
char * username
User's login name.
Definition neomutt.h:56
char * home_dir
User's home directory.
Definition neomutt.h:55
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
struct Connection * conn
Connection to NNTP Server.
Definition adata.h:63
Nntp private Module data.
Definition module_data.h:30
struct NntpAccountData * current_news_srv
Current NNTP news server.
Definition module_data.h:32
Data passed to a notification function.
Definition observer.h:34
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition observer.h:36
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
String list.
Definition slist.h:37
Collection of related functions.
Definition menudef.h:33
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition subset.c:193
GetElemListFlags
Filtering modes for get_elem_list()
Definition subset.h:80
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition subset.h:82
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
#define buf_mktemp_draft(buf)
Definition tmp.h:34
#define D_SLIST_SEP_COLON
Slist items are colon-separated.
Definition types.h:112
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition types.h:88
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition url.c:229
@ U_MAILTO
Url is mailto://.
Definition url.h:45
bool print_copyright(void)
Print copyright message.
Definition version.c:701
bool print_version(FILE *fp, bool use_ansi)
Print system and compile info to a file.
Definition version.c:589
Display version and copyright about NeoMutt.