NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
main.c File Reference

Command line processing. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "attach/lib.h"
#include "browser/lib.h"
#include "color/lib.h"
#include "index/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "postpone/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "alternates.h"
#include "external.h"
#include "globals.h"
#include "hook.h"
#include "init.h"
#include "keymap.h"
#include "mutt_history.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "protos.h"
#include "subjectrx.h"
#include "version.h"
#include <libintl.h>
#include "imap/lib.h"
#include "pop/lib.h"
#include "nntp/lib.h"
#include "nntp/adata.h"
#include "autocrypt/lib.h"
+ Include dependency graph for main.c:

Go to the source code of this file.

Macros

#define GNULIB_defined_setlocale
 
#define MUTT_CLI_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_CLI_IGNORE   (1 << 0)
 -z Open first mailbox if it has mail More...
 
#define MUTT_CLI_MAILBOX   (1 << 1)
 -Z Open first mailbox if is has new mail More...
 
#define MUTT_CLI_NOSYSRC   (1 << 2)
 -n Do not read the system-wide config file More...
 
#define MUTT_CLI_RO   (1 << 3)
 -R Open mailbox in read-only mode More...
 
#define MUTT_CLI_SELECT   (1 << 4)
 -y Start with a list of all mailboxes More...
 
#define MUTT_CLI_NEWS   (1 << 5)
 -g/-G Start with a list of all newsgroups More...
 

Typedefs

typedef uint8_t CliFlags
 Flags for command line options, e.g. MUTT_CLI_IGNORE. More...
 

Functions

static void reset_tilde (struct ConfigSet *cs)
 Temporary measure. More...
 
void mutt_exit (int code)
 Leave NeoMutt NOW. More...
 
static bool usage (void)
 Display NeoMutt command line. More...
 
static int start_curses (void)
 Start the Curses UI. More...
 
static void init_locale (void)
 Initialise the Locale/NLS settings. More...
 
static bool get_user_info (struct ConfigSet *cs)
 Find the user's name, home and shell. More...
 
static void log_translation (void)
 Log the translation being used. More...
 
int main (int argc, char *argv[], char *envp[])
 Start NeoMutt. More...
 

Variables

bool StartupComplete = false
 When the config has been read. More...
 

Detailed Description

Command line processing.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • g10 Code GmbH
  • Pietro Cerutti
  • R Primus

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file main.c.

Macro Definition Documentation

◆ GNULIB_defined_setlocale

#define GNULIB_defined_setlocale

Definition at line 134 of file main.c.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 203 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

Definition at line 204 of file main.c.

◆ MUTT_CLI_MAILBOX

#define MUTT_CLI_MAILBOX   (1 << 1)

-Z Open first mailbox if is has new mail

Definition at line 205 of file main.c.

◆ MUTT_CLI_NOSYSRC

#define MUTT_CLI_NOSYSRC   (1 << 2)

-n Do not read the system-wide config file

Definition at line 206 of file main.c.

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 207 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

Definition at line 208 of file main.c.

◆ MUTT_CLI_NEWS

#define MUTT_CLI_NEWS   (1 << 5)

-g/-G Start with a list of all newsgroups

Definition at line 210 of file main.c.

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

Flags for command line options, e.g. MUTT_CLI_IGNORE.

Definition at line 202 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 218 of file main.c.

219{
220 static const char *names[] = { "folder", "mbox", "postponed", "record" };
221
222 struct Buffer value = buf_make(256);
223 for (size_t i = 0; i < mutt_array_size(names); i++)
224 {
225 struct HashElem *he = cs_get_elem(cs, names[i]);
226 if (!he)
227 continue;
228 buf_reset(&value);
229 cs_he_initial_get(cs, he, &value);
230 buf_expand_path_regex(&value, false);
231 cs_he_initial_set(cs, he, value.data, NULL);
232 cs_he_reset(cs, he, NULL);
233 }
234 buf_dealloc(&value);
235}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:383
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:172
int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:390
int cs_he_initial_set(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:460
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition: set.c:528
#define mutt_array_size(x)
Definition: memory.h:36
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:136
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
The item stored in a Hash Table.
Definition: hash.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_exit()

void mutt_exit ( int  code)

Leave NeoMutt NOW.

Parameters
codeValue to return to the calling environment

Definition at line 241 of file main.c.

242{
243 mutt_endwin();
244#ifdef HAVE_LIBUNWIND
245 if (code != 0)
247#endif
248 exit(code);
249}
void show_backtrace(void)
Log the program's call stack.
Definition: backtrace.c:39
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:355
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ usage()

static bool usage ( void  )
static

Display NeoMutt command line.

Return values
trueText displayed

Definition at line 255 of file main.c.

256{
257 puts(mutt_make_version());
258
259 // clang-format off
260 /* L10N: Try to limit to 80 columns */
261 puts(_("usage:"));
262 puts(_(" neomutt [-Enx] [-e <command>] [-F <config>] [-H <draft>] [-i <include>]\n"
263 " [-b <address>] [-c <address>] [-s <subject>] [-a <file> [...] --]\n"
264 " <address> [...]"));
265 puts(_(" neomutt [-nx] [-e <command>] [-F <config>] [-b <address>] [-c <address>]\n"
266 " [-s <subject>] [-a <file> [...] --] <address> [...] < message"));
267 puts(_(" neomutt [-nRy] [-e <command>] [-F <config>] [-f <mailbox>] [-m <type>]"));
268 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -A <alias>"));
269 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -B"));
270 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -D [-S] [-O]"));
271 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -d <level> -l <file>"));
272 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -G"));
273 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -g <server>"));
274 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -p"));
275 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Q <variable> [-O]"));
276 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Z"));
277 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -z [-f <mailbox>]"));
278 puts(_(" neomutt -v[v]\n"));
279
280 /* L10N: Try to limit to 80 columns. If more space is needed add an indented line */
281 puts(_("options:"));
282 puts(_(" -- Special argument forces NeoMutt to stop option parsing and treat\n"
283 " remaining arguments as addresses even if they start with a dash"));
284 puts(_(" -A <alias> Print an expanded version of the given alias to stdout and exit"));
285 puts(_(" -a <file> Attach one or more files to a message (must be the last option)\n"
286 " Add any addresses after the '--' argument"));
287 puts(_(" -B Run in batch mode (do not start the ncurses UI)"));
288 puts(_(" -b <address> Specify a blind carbon copy (Bcc) recipient"));
289 puts(_(" -c <address> Specify a carbon copy (Cc) recipient"));
290 puts(_(" -D Dump all config variables as 'name=value' pairs to stdout"));
291 puts(_(" -D -O Like -D, but show one-liner documentation"));
292 puts(_(" -D -S Like -D, but hide the value of sensitive variables"));
293 puts(_(" -d <level> Log debugging output to a file (default is \"~/.neomuttdebug0\")\n"
294 " The level can range from 1-5 and affects verbosity"));
295 puts(_(" -E Edit draft (-H) or include (-i) file during message composition"));
296 puts(_(" -e <command> Specify a command to be run after reading the config files"));
297 puts(_(" -F <config> Specify an alternative initialization file to read"));
298 puts(_(" -f <mailbox> Specify a mailbox (as defined with 'mailboxes' command) to load"));
299 puts(_(" -G Start NeoMutt with a listing of subscribed newsgroups"));
300 puts(_(" -g <server> Like -G, but start at specified news server"));
301 puts(_(" -H <draft> Specify a draft file with header and body for message composing"));
302 puts(_(" -h Print this help message and exit"));
303 puts(_(" -i <include> Specify an include file to be embedded in the body of a message"));
304 puts(_(" -l <file> Specify a file for debugging output (default \"~/.neomuttdebug0\")"));
305 puts(_(" -m <type> Specify a default mailbox format type for newly created folders\n"
306 " The type is either MH, MMDF, Maildir or mbox (case-insensitive)"));
307 puts(_(" -n Do not read the system-wide configuration file"));
308 puts(_(" -p Resume a prior postponed message, if any"));
309 puts(_(" -Q <variable> Query a configuration variable and print its value to stdout\n"
310 " (after the config has been read and any commands executed)\n"
311 " Add -O for one-liner documentation"));
312 puts(_(" -R Open mailbox in read-only mode"));
313 puts(_(" -s <subject> Specify a subject (must be enclosed in quotes if it has spaces)"));
314 puts(_(" -v Print the NeoMutt version and compile-time definitions and exit"));
315 puts(_(" -vv Print the NeoMutt license and copyright information and exit"));
316 puts(_(" -y Start NeoMutt with a listing of all defined mailboxes"));
317 puts(_(" -Z Open the first mailbox with new message or exit immediately with\n"
318 " exit code 1 if none is found in all defined mailboxes"));
319 puts(_(" -z Open the first or specified (-f) mailbox if it holds any message\n"
320 " or exit immediately with exit code 1 otherwise"));
321 // clang-format on
322
323 fflush(stdout);
324 return !ferror(stdout);
325}
#define _(a)
Definition: message.h:28
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1439
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ start_curses()

static int start_curses ( void  )
static

Start the Curses UI.

Return values
0Success
1Failure

Definition at line 332 of file main.c.

333{
334 km_init(); /* must come before mutt_init */
335
336 /* should come before initscr() so that ncurses 4.2 doesn't try to install
337 * its own SIGWINCH handler */
339
340 if (!initscr())
341 {
342 mutt_error(_("Error initializing terminal"));
343 return 1;
344 }
347 keypad(stdscr, true);
348 cbreak();
349 noecho();
350 nonl();
351 typeahead(-1); /* simulate smooth scrolling */
352 meta(stdscr, true);
354 /* Now that curses is set up, we drop back to normal screen mode.
355 * This simplifies displaying error messages to the user.
356 * The first call to refresh() will swap us back to curses screen mode. */
357 endwin();
358 return 0;
359}
void mutt_colors_init(void)
Initialize colours.
Definition: color.c:82
#define mutt_error(...)
Definition: logging2.h:90
void km_init(void)
Initialise all the menu keybindings.
Definition: keymap.c:1041
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: keymap.c:1012
void mutt_signal_init(void)
Initialise the signal handling.
Definition: mutt_signal.c:131
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_locale()

static void init_locale ( void  )
static

Initialise the Locale/NLS settings.

Definition at line 364 of file main.c.

365{
366 setlocale(LC_ALL, "");
367
368#ifdef ENABLE_NLS
369 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
370 if (domdir)
371 bindtextdomain(PACKAGE, domdir);
372 else
373 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
374 textdomain(PACKAGE);
375#endif
376#ifndef LOCALES_HACK
377 /* Do we have a locale definition? */
378 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
379 {
380 OptLocales = true;
381 }
382#endif
383}
bool OptLocales
(pseudo) set if user has valid locale definition
Definition: mbyte.c:43
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:918
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_user_info()

static bool get_user_info ( struct ConfigSet cs)
static

Find the user's name, home and shell.

Parameters
csConfig Set
Return values
trueSuccess

Find the login name, real name, home directory and shell.

Definition at line 392 of file main.c.

393{
394 const char *shell = mutt_str_getenv("SHELL");
395 if (shell)
396 cs_str_initial_set(cs, "shell", shell, NULL);
397
398 /* Get some information about the user */
399 struct passwd *pw = getpwuid(getuid());
400 if (pw)
401 {
402 if (!Username)
403 Username = mutt_str_dup(pw->pw_name);
404 if (!HomeDir)
405 HomeDir = mutt_str_dup(pw->pw_dir);
406 if (!shell)
407 cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
408 }
409
410 if (!Username)
411 {
412 mutt_error(_("unable to determine username"));
413 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
414 }
415
416 if (!HomeDir)
417 {
418 mutt_error(_("unable to determine home directory"));
419 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
420 }
421
422 cs_str_reset(cs, "shell", NULL);
423 return true;
424}
char * HomeDir
User's home directory.
Definition: globals.c:39
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:502
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:437
char * Username
User's login name.
Definition: globals.c:42
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_translation()

static void log_translation ( void  )
static

Log the translation being used.

Read the header info from the translation file.

Note
Call bindtextdomain() first

Definition at line 433 of file main.c.

434{
435 const char *header = ""; // Do not merge these two lines
436 header = _(header); // otherwise the .po files will end up badly ordered
437 const char *label = "Language:"; // the start of the lookup/needle
438 const char *lang = mutt_istr_find(header, label);
439 int len = 64;
440 if (lang)
441 {
442 lang += strlen(label); // skip label
443 SKIPWS(lang);
444 char *nl = strchr(lang, '\n');
445 if (nl)
446 len = (nl - lang);
447 }
448 else
449 {
450 lang = "NONE";
451 }
452
453 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
454}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:593
#define SKIPWS(ch)
Definition: string2.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *  argv[],
char *  envp[] 
)

Start NeoMutt.

Parameters
argcNumber of command line arguments
argvList of command line arguments
envpCopy of the environment
Return values
0Success
1Error

Definition at line 468 of file main.c.

471{
472 char *subject = NULL;
473 char *include_file = NULL;
474 char *draft_file = NULL;
475 char *new_type = NULL;
476 char *dlevel = NULL;
477 char *dfile = NULL;
478#ifdef USE_NNTP
479 const char *cli_nntp = NULL;
480#endif
481 struct Email *e = NULL;
482 struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
483 struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
484 struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
485 struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
486 struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
487 struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
488 SendFlags sendflags = SEND_NO_FLAGS;
490 int version = 0;
491 int i;
492 bool explicit_folder = false;
493 bool dump_variables = false;
494 bool one_liner = false;
495 bool hide_sensitive = false;
496 bool batch_mode = false;
497 bool edit_infile = false;
498 int double_dash = argc, nargc = 1;
499 int rc = 1;
500 bool repeat_error = false;
501 struct Buffer folder = buf_make(0);
502 struct Buffer expanded_infile = buf_make(0);
503 struct Buffer tempfile = buf_make(0);
504 struct ConfigSet *cs = NULL;
505
507
508 /* sanity check against stupid administrators */
509 if (getegid() != getgid())
510 {
511 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
512 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
513 }
514
515 init_locale();
516
517 umask(077);
518
519 EnvList = envlist_init(envp);
520 for (optind = 1; optind < double_dash;)
521 {
522 /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
523 * encounters a non-option. That could be a file to attach
524 * (all non-options between -a and --) or it could be an address
525 * (which gets collapsed to the front of argv). */
526 for (; optind < argc; optind++)
527 {
528 if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
529 {
530 if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
531 double_dash = optind; /* quit outer loop after getopt */
532 break; /* drop through to getopt */
533 }
534
535 /* non-option, either an attachment or address */
536 if (!STAILQ_EMPTY(&attach))
537 mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
538 else
539 argv[nargc++] = argv[optind];
540 }
541
542 /* USE_NNTP 'g:G' */
543 i = getopt(argc, argv, "+A:a:Bb:F:f:c:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvxyzZ");
544 if (i != EOF)
545 {
546 switch (i)
547 {
548 case 'A':
549 mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
550 break;
551 case 'a':
552 mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
553 break;
554 case 'B':
555 batch_mode = true;
556 break;
557 case 'b':
558 mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
559 break;
560 case 'c':
561 mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
562 break;
563 case 'D':
564 dump_variables = true;
565 break;
566 case 'd':
567 dlevel = optarg;
568 break;
569 case 'E':
570 edit_infile = true;
571 break;
572 case 'e':
573 mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
574 break;
575 case 'F':
577 break;
578 case 'f':
579 buf_strcpy(&folder, optarg);
580 explicit_folder = true;
581 break;
582#ifdef USE_NNTP
583 case 'g': /* Specify a news server */
584 cli_nntp = optarg;
585 /* fallthrough */
586 case 'G': /* List of newsgroups */
588 break;
589#endif
590 case 'H':
591 draft_file = optarg;
592 break;
593 case 'i':
594 include_file = optarg;
595 break;
596 case 'l':
597 dfile = optarg;
598 break;
599 case 'm':
600 new_type = optarg;
601 break;
602 case 'n':
603 flags |= MUTT_CLI_NOSYSRC;
604 break;
605 case 'O':
606 one_liner = true;
607 break;
608 case 'p':
609 sendflags |= SEND_POSTPONED;
610 break;
611 case 'Q':
612 mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
613 break;
614 case 'R':
615 flags |= MUTT_CLI_RO; /* read-only mode */
616 break;
617 case 'S':
618 hide_sensitive = true;
619 break;
620 case 's':
621 subject = optarg;
622 break;
623 case 'v':
624 version++;
625 break;
626 case 'y': /* My special hack mode */
627 flags |= MUTT_CLI_SELECT;
628 break;
629 case 'Z':
631 break;
632 case 'z':
633 flags |= MUTT_CLI_IGNORE;
634 break;
635 default:
636 OptNoCurses = true;
637 if (usage())
638 goto main_ok; // TEST03: neomutt -9
639 else
640 goto main_curses;
641 }
642 }
643 }
644
645 /* collapse remaining argv */
646 while (optind < argc)
647 argv[nargc++] = argv[optind++];
648 optind = 1;
649 argc = nargc;
650
651 if (version > 0)
652 {
654 bool done;
655 if (version == 1)
656 done = print_version(stdout);
657 else
658 done = print_copyright();
659 OptNoCurses = true;
660 if (done)
661 goto main_ok; // TEST04: neomutt -v
662 else
663 goto main_curses;
664 }
665
668
669 cs = cs_new(500);
670 if (!cs)
671 goto main_curses;
672
673 NeoMutt = neomutt_new(cs);
674 init_config(cs);
675 subjrx_init();
676 attach_init();
678
679#ifdef USE_DEBUG_NOTIFY
681#endif
682
683 if (!get_user_info(cs))
684 goto main_exit;
685
686 reset_tilde(cs);
687
688 if (dfile)
689 {
690 cs_str_initial_set(cs, "debug_file", dfile, NULL);
691 cs_str_reset(cs, "debug_file", NULL);
692 }
693
694 if (dlevel)
695 {
696 short num = 0;
697 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
698 {
699 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
700 goto main_exit; // TEST07: neomutt -d xyz
701 }
702 cs_str_initial_set(cs, "debug_level", dlevel, NULL);
703 cs_str_reset(cs, "debug_level", NULL);
704 }
705
709
710 if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
711 {
712 e = email_new();
713 e->env = mutt_env_new();
714
715 struct ListNode *np = NULL;
716 STAILQ_FOREACH(np, &bcc_list, entries)
717 {
718 mutt_addrlist_parse(&e->env->bcc, np->data);
719 }
720
721 STAILQ_FOREACH(np, &cc_list, entries)
722 {
723 mutt_addrlist_parse(&e->env->cc, np->data);
724 }
725
726 mutt_list_free(&bcc_list);
727 mutt_list_free(&cc_list);
728 }
729
730 /* Check for a batch send. */
731 if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
732 dump_variables || batch_mode)
733 {
734 OptNoCurses = true;
735 sendflags = SEND_BATCH;
738 }
739
740 /* Check to make sure stdout is available in curses mode. */
741 if (!OptNoCurses && !isatty(1))
742 goto main_curses;
743
744 /* Always create the mutt_windows because batch mode has some shared code
745 * paths that end up referencing them. */
746 rootwin_new();
747
748 /* This must come before mutt_init() because curses needs to be started
749 * before calling the init_pair() function to set the color scheme. */
750 if (!OptNoCurses)
751 {
752 int crc = start_curses();
753 if (crc != 0)
754 goto main_curses; // TEST08: can't test -- fake term?
755
756 /* check whether terminal status is supported (must follow curses init) */
758 rootwin_set_size(COLS, LINES);
759 }
760
761 /* set defaults and read init files */
762 int rc2 = mutt_init(cs, flags & MUTT_CLI_NOSYSRC, &commands);
763 if (rc2 != 0)
764 goto main_curses;
765
767
768 /* The command line overrides the config */
769 if (dlevel)
770 cs_str_reset(cs, "debug_level", NULL);
771 if (dfile)
772 cs_str_reset(cs, "debug_file", NULL);
773
774 if (mutt_log_start() < 0)
775 {
776 mutt_perror("log file");
777 goto main_exit;
778 }
779
780#ifdef USE_NNTP
781 {
782 /* "$news_server" precedence: command line, config file, environment, system file */
783 if (!cli_nntp)
784 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
785
786 if (!cli_nntp)
787 cli_nntp = mutt_str_getenv("NNTPSERVER");
788
789 if (!cli_nntp)
790 {
791 char buf[1024] = { 0 };
792 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
793 }
794
795 if (cli_nntp)
796 {
797 cs_str_initial_set(cs, "news_server", cli_nntp, NULL);
798 cs_str_reset(cs, "news_server", NULL);
799 }
800 }
801#endif
802
803 /* Initialize crypto backends. */
804 crypt_init();
805
806 if (new_type)
807 {
808 struct Buffer err = buf_make(0);
809 int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
810 if (CSR_RESULT(r) != CSR_SUCCESS)
811 {
812 mutt_error(err.data);
813 buf_dealloc(&err);
814 goto main_curses;
815 }
816 cs_str_reset(cs, "mbox_type", NULL);
817 }
818
819 if (!STAILQ_EMPTY(&queries))
820 {
821 rc = mutt_query_variables(&queries, one_liner);
822 goto main_curses;
823 }
824
825 if (dump_variables)
826 {
828 if (hide_sensitive)
829 cdflags |= CS_DUMP_HIDE_SENSITIVE;
830 if (one_liner)
831 cdflags |= CS_DUMP_SHOW_DOCS;
832 dump_config(cs, cdflags, stdout);
833 goto main_ok; // TEST18: neomutt -D
834 }
835
836 if (!STAILQ_EMPTY(&alias_queries))
837 {
838 rc = 0;
839 for (; optind < argc; optind++)
840 mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
841 struct ListNode *np = NULL;
842 STAILQ_FOREACH(np, &alias_queries, entries)
843 {
844 struct AddressList *al = alias_lookup(np->data);
845 if (al)
846 {
847 /* output in machine-readable form */
848 mutt_addrlist_to_intl(al, NULL);
849 struct Buffer *buf = buf_pool_get();
850 mutt_addrlist_write(al, buf, false);
851 printf("%s\n", buf_string(buf));
852 buf_pool_release(&buf);
853 }
854 else
855 {
856 rc = 1;
857 printf("%s\n", np->data); // TEST19: neomutt -A unknown
858 }
859 }
860 mutt_list_free(&alias_queries);
861 goto main_curses; // TEST20: neomutt -A alias
862 }
863
864 if (!OptNoCurses)
865 {
867 clear();
871 }
872
873#ifdef USE_AUTOCRYPT
874 /* Initialize autocrypt after curses messages are working,
875 * because of the initial account setup screens. */
876 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
877 if (c_autocrypt)
878 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
879#endif
880
881 /* Create the `$folder` directory if it doesn't exist. */
882 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
883 if (!OptNoCurses && c_folder)
884 {
885 struct stat st = { 0 };
886 struct Buffer *fpath = buf_pool_get();
887
888 buf_strcpy(fpath, c_folder);
889 buf_expand_path(fpath);
890 bool skip = false;
891#ifdef USE_IMAP
892 /* we're not connected yet - skip mail folder creation */
893 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
894#endif
895#ifdef USE_POP
896 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
897#endif
898#ifdef USE_NNTP
899 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
900#endif
901 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
902 {
903 char msg2[256];
904 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
905 if (mutt_yesorno(msg2, MUTT_YES) == MUTT_YES)
906 {
907 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
908 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
909 }
910 }
911 buf_pool_release(&fpath);
912 }
913
914 if (batch_mode)
915 {
916 goto main_ok; // TEST22: neomutt -B
917 }
918 StartupComplete = true;
919
923
924 if (sendflags & SEND_POSTPONED)
925 {
926 if (!OptNoCurses)
928 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
929 rc = 0;
930 // TEST23: neomutt -p (postponed message, cancel)
931 // TEST24: neomutt -p (no postponed message)
933 repeat_error = true;
934 goto main_curses;
935 }
936 else if (subject || e || draft_file || include_file ||
937 !STAILQ_EMPTY(&attach) || (optind < argc))
938 {
939 FILE *fp_in = NULL;
940 FILE *fp_out = NULL;
941 char *infile = NULL;
942 char *bodytext = NULL;
943 const char *bodyfile = NULL;
944 int rv = 0;
945
946 if (!OptNoCurses)
948
949 if (!e)
950 e = email_new();
951 if (!e->env)
952 e->env = mutt_env_new();
953
954 for (i = optind; i < argc; i++)
955 {
956 if (url_check_scheme(argv[i]) == U_MAILTO)
957 {
958 if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
959 {
960 mutt_error(_("Failed to parse mailto: link"));
961 email_free(&e);
962 goto main_curses; // TEST25: neomutt mailto:?
963 }
964 }
965 else
966 {
967 mutt_addrlist_parse(&e->env->to, argv[i]);
968 }
969 }
970
971 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
972 if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
973 TAILQ_EMPTY(&e->env->cc))
974 {
975 mutt_error(_("No recipients specified"));
976 email_free(&e);
977 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
978 }
979
980 if (subject)
981 {
982 mutt_str_replace(&e->env->subject, subject);
983 }
984
985 if (draft_file)
986 {
987 infile = draft_file;
988 include_file = NULL;
989 }
990 else if (include_file)
991 {
992 infile = include_file;
993 }
994 else
995 {
996 edit_infile = false;
997 }
998
999 if (infile || bodytext)
1000 {
1001 /* Prepare fp_in and expanded_infile. */
1002 if (infile)
1003 {
1004 if (mutt_str_equal("-", infile))
1005 {
1006 if (edit_infile)
1007 {
1008 mutt_error(_("Can't use -E flag with stdin"));
1009 email_free(&e);
1010 goto main_curses; // TEST27: neomutt -E -H -
1011 }
1012 fp_in = stdin;
1013 }
1014 else
1015 {
1016 buf_strcpy(&expanded_infile, infile);
1017 buf_expand_path(&expanded_infile);
1018 fp_in = fopen(buf_string(&expanded_infile), "r");
1019 if (!fp_in)
1020 {
1021 mutt_perror(buf_string(&expanded_infile));
1022 email_free(&e);
1023 goto main_curses; // TEST28: neomutt -E -H missing
1024 }
1025 }
1026 }
1027
1028 if (edit_infile)
1029 {
1030 /* If editing the infile, keep it around afterwards so
1031 * it doesn't get unlinked, and we can rebuild the draft_file */
1032 sendflags |= SEND_NO_FREE_HEADER;
1033 }
1034 else
1035 {
1036 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1037 * Note: stdin is always copied to a tempfile, ensuring draft_file
1038 * can stat and get the correct st_size below. */
1039 buf_mktemp(&tempfile);
1040
1041 fp_out = mutt_file_fopen(buf_string(&tempfile), "w");
1042 if (!fp_out)
1043 {
1044 mutt_file_fclose(&fp_in);
1045 mutt_perror(buf_string(&tempfile));
1046 email_free(&e);
1047 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1048 }
1049 if (fp_in)
1050 {
1051 mutt_file_copy_stream(fp_in, fp_out);
1052 if (fp_in != stdin)
1053 mutt_file_fclose(&fp_in);
1054 }
1055 else if (bodytext)
1056 {
1057 fputs(bodytext, fp_out);
1058 }
1059 mutt_file_fclose(&fp_out);
1060
1061 fp_in = fopen(buf_string(&tempfile), "r");
1062 if (!fp_in)
1063 {
1064 mutt_perror(buf_string(&tempfile));
1065 email_free(&e);
1066 goto main_curses; // TEST30: can't test
1067 }
1068 }
1069
1070 /* Parse the draft_file into the full Email/Body structure.
1071 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1072 * our e->body. */
1073 if (draft_file)
1074 {
1075 struct Envelope *opts_env = e->env;
1076 struct stat st = { 0 };
1077
1078 sendflags |= SEND_DRAFT_FILE;
1079
1080 /* Set up a tmp Email with just enough information so that
1081 * mutt_prepare_template() can parse the message in fp_in. */
1082 struct Email *e_tmp = email_new();
1083 e_tmp->offset = 0;
1084 e_tmp->body = mutt_body_new();
1085 if (fstat(fileno(fp_in), &st) != 0)
1086 {
1087 mutt_perror(draft_file);
1088 email_free(&e);
1089 email_free(&e_tmp);
1090 goto main_curses; // TEST31: can't test
1091 }
1092 e_tmp->body->length = st.st_size;
1093
1094 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1095 {
1096 mutt_error(_("Can't parse message template: %s"), draft_file);
1097 email_free(&e);
1098 email_free(&e_tmp);
1099 goto main_curses;
1100 }
1101
1102 /* Scan for neomutt header to set `$resume_draft_files` */
1103 struct ListNode *np = NULL, *tmp = NULL;
1104 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1105 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1106 {
1107 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1108 {
1109 if (c_resume_edited_draft_files)
1110 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1111
1112 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1113 FREE(&np->data);
1114 FREE(&np);
1115 }
1116 }
1117
1118 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1119 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1120 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1121 if (opts_env->subject)
1122 mutt_str_replace(&e->env->subject, opts_env->subject);
1123
1124 mutt_env_free(&opts_env);
1125 email_free(&e_tmp);
1126 }
1127 /* Editing the include_file: pass it directly in.
1128 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1129 else if (edit_infile)
1130 bodyfile = buf_string(&expanded_infile);
1131 // For bodytext and unedited include_file: use the tempfile.
1132 else
1133 bodyfile = buf_string(&tempfile);
1134
1135 mutt_file_fclose(&fp_in);
1136 }
1137
1138 FREE(&bodytext);
1139
1140 if (!STAILQ_EMPTY(&attach))
1141 {
1142 struct Body *b = e->body;
1143
1144 while (b && b->next)
1145 b = b->next;
1146
1147 struct ListNode *np = NULL;
1148 STAILQ_FOREACH(np, &attach, entries)
1149 {
1150 if (b)
1151 {
1153 b = b->next;
1154 }
1155 else
1156 {
1158 e->body = b;
1159 }
1160 if (!b)
1161 {
1162 mutt_error(_("%s: unable to attach file"), np->data);
1163 mutt_list_free(&attach);
1164 email_free(&e);
1165 goto main_curses; // TEST32: neomutt john@example.com -a missing
1166 }
1167 }
1168 mutt_list_free(&attach);
1169 }
1170
1171 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1172 /* We WANT the "Mail sent." and any possible, later error */
1174 if (ErrorBufMessage)
1175 mutt_message("%s", ErrorBuf);
1176
1177 if (edit_infile)
1178 {
1179 if (draft_file)
1180 {
1181 if (truncate(buf_string(&expanded_infile), 0) == -1)
1182 {
1183 mutt_perror(buf_string(&expanded_infile));
1184 email_free(&e);
1185 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1186 }
1187 fp_out = mutt_file_fopen(buf_string(&expanded_infile), "a");
1188 if (!fp_out)
1189 {
1190 mutt_perror(buf_string(&expanded_infile));
1191 email_free(&e);
1192 goto main_curses; // TEST34: can't test
1193 }
1194
1195 /* If the message was sent or postponed, these will already
1196 * have been done. */
1197 if (rv < 0)
1198 {
1199 if (e->body->next)
1200 e->body = mutt_make_multipart(e->body);
1202 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1203 mutt_env_to_intl(e->env, NULL, NULL);
1204 }
1205
1206 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1208 c_crypt_protected_headers_read &&
1210 NeoMutt->sub);
1211 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1212 if (c_resume_edited_draft_files)
1213 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1214 fputc('\n', fp_out);
1215 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1216 {
1217 mutt_file_fclose(&fp_out);
1218 email_free(&e);
1219 goto main_curses; // TEST35: can't test
1220 }
1221 mutt_file_fclose(&fp_out);
1222 }
1223
1224 email_free(&e);
1225 }
1226
1227 /* !edit_infile && draft_file will leave the tempfile around */
1228 if (!buf_is_empty(&tempfile))
1229 unlink(buf_string(&tempfile));
1230
1231 rootwin_free();
1232
1233 if (rv != 0)
1234 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1235 }
1236 else if (sendflags & SEND_BATCH)
1237 {
1238 /* This guards against invoking `neomutt < /dev/null` and accidentally
1239 * sending an email due to a my_hdr or other setting. */
1240 mutt_error(_("No recipients specified"));
1241 goto main_curses;
1242 }
1243 else
1244 {
1245 if (flags & MUTT_CLI_MAILBOX)
1246 {
1247#ifdef USE_IMAP
1248 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1249 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1250#endif
1252 if (mutt_mailbox_check(NULL, csflags) == 0)
1253 {
1254 mutt_message(_("No mailbox with new mail"));
1255 goto main_curses; // TEST37: neomutt -Z (no new mail)
1256 }
1257 buf_reset(&folder);
1258 mutt_mailbox_next(NULL, &folder);
1259#ifdef USE_IMAP
1260 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1261#endif
1262 }
1263 else if (flags & MUTT_CLI_SELECT)
1264 {
1265#ifdef USE_NNTP
1266 if (flags & MUTT_CLI_NEWS)
1267 {
1268 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1269 OptNews = true;
1270 struct Mailbox *m_cur = get_current_mailbox();
1271 CurrentNewsSrv = nntp_select_server(m_cur, c_news_server, false);
1272 if (!CurrentNewsSrv)
1273 goto main_curses; // TEST38: neomutt -G (unset news_server)
1274 }
1275 else
1276#endif
1278 {
1279 mutt_error(_("No incoming mailboxes defined"));
1280 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1281 }
1282 buf_reset(&folder);
1283 struct Mailbox *m_cur = get_current_mailbox();
1284 buf_select_file(&folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, m_cur, NULL, NULL);
1285 if (buf_is_empty(&folder))
1286 {
1287 goto main_ok; // TEST40: neomutt -y (quit selection)
1288 }
1289 }
1290
1291 if (buf_is_empty(&folder))
1292 {
1293 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1294 if (c_spool_file)
1295 {
1296 // Check if `$spool_file` corresponds a mailboxes' description.
1297 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1298 if (m_desc)
1299 buf_strcpy(&folder, m_desc->realpath);
1300 else
1301 buf_strcpy(&folder, c_spool_file);
1302 }
1303 else if (c_folder)
1304 {
1305 buf_strcpy(&folder, c_folder);
1306 }
1307 /* else no folder */
1308 }
1309
1310#ifdef USE_NNTP
1311 if (OptNews)
1312 {
1313 OptNews = false;
1314 buf_alloc(&folder, PATH_MAX);
1316 }
1317 else
1318#endif
1319 buf_expand_path(&folder);
1320
1323
1324 if (flags & MUTT_CLI_IGNORE)
1325 {
1326 /* check to see if there are any messages in the folder */
1327 switch (mx_path_is_empty(buf_string(&folder)))
1328 {
1329 case -1:
1330 mutt_perror(buf_string(&folder));
1331 goto main_curses; // TEST41: neomutt -z -f missing
1332 case 1:
1333 mutt_error(_("Mailbox is empty"));
1334 goto main_curses; // TEST42: neomutt -z -f /dev/null
1335 }
1336 }
1337
1338 mutt_folder_hook(buf_string(&folder), NULL);
1340 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1342
1343 repeat_error = true;
1344 struct Mailbox *m = mx_resolve(buf_string(&folder));
1345 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1346 if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1347 {
1348 if (m->account)
1350
1351 mailbox_free(&m);
1352 mutt_error(_("Unable to open mailbox %s"), buf_string(&folder));
1353 repeat_error = false;
1354 }
1355 if (m || !explicit_folder)
1356 {
1357 struct MuttWindow *dlg = index_pager_init();
1358 dialog_push(dlg);
1359
1361 m = mutt_index_menu(dlg, m);
1363 mailbox_free(&m);
1364
1365 dialog_pop();
1366 mutt_window_free(&dlg);
1368 repeat_error = false;
1369 }
1370#ifdef USE_IMAP
1372#endif
1373#ifdef USE_SASL_CYRUS
1375#endif
1376#ifdef USE_SASL_GNU
1378#endif
1379#ifdef USE_AUTOCRYPT
1381#endif
1382 // TEST43: neomutt (no change to mailbox)
1383 // TEST44: neomutt (change mailbox)
1384 }
1385
1386main_ok:
1387 rc = 0;
1388main_curses:
1389 mutt_endwin();
1391 /* Repeat the last message to the user */
1392 if (repeat_error && ErrorBufMessage)
1393 puts(ErrorBuf);
1394main_exit:
1395 mutt_list_free(&commands);
1397 buf_dealloc(&folder);
1398 buf_dealloc(&expanded_infile);
1399 buf_dealloc(&tempfile);
1400 mutt_list_free(&queries);
1402 rootwin_free();
1403 buf_pool_free();
1407 menu_cleanup();
1408 crypt_cleanup();
1411 subjrx_free();
1412 attach_free();
1418 cs_free(&cs);
1421 mutt_log_stop();
1422 return rc;
1423}
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:96
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:750
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1195
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:472
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1282
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:279
void alternates_init(void)
Set up the alternates lists.
Definition: alternates.c:60
void alternates_free(void)
Free the alternates lists.
Definition: alternates.c:49
void attach_free(void)
Free the attachments lists.
Definition: attachments.c:91
void attach_init(void)
Set up the attachments lists.
Definition: attachments.c:105
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:139
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:97
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:56
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:58
void mutt_browser_cleanup(void)
Clean up working Buffers.
Definition: browser.c:160
void buf_select_file(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1160
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:401
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:347
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
void config_cache_free(void)
Cleanup the cache of charset config variables.
Definition: cache.c:120
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:138
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:124
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:781
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1090
void crypto_module_free(void)
Clean up the crypto modules.
Definition: crypt_mod.c:82
void crypt_cleanup(void)
Clean up backend.
Definition: cryptglue.c:142
void crypt_init(void)
Initialise the crypto backends.
Definition: cryptglue.c:94
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:593
int debug_all_observer(struct NotifyCallback *nc)
Definition: notify.c:204
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: dialog.c:103
void dialog_pop(void)
Hide a Window from the user.
Definition: dialog.c:137
struct Mailbox * mutt_index_menu(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails.
Definition: dlg_index.c:1062
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition: dlg_index.c:1408
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:34
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
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:328
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
void envlist_free(char ***envp)
Free the private copy of the environment.
Definition: envlist.c:41
char ** envlist_init(char **envp)
Create a copy of the environment.
Definition: envlist.c:57
void commands_cleanup(void)
Clean up commands globals.
Definition: external.c:80
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
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
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition: file.c:1425
bool OptNews
(pseudo) used to change reader mode
Definition: globals.c:79
char * LastFolder
Previously selected mailbox.
Definition: globals.c:45
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:82
bool ErrorBufMessage
true if the last message was an error
Definition: globals.c:36
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:44
char ErrorBuf[256]
Copy of the last error message.
Definition: globals.c:37
struct ListHead Muttrc
List of config files to read.
Definition: globals.c:53
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:91
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition: logging.c:442
int log_disp_curses(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Display a log line in the message line - Implements log_dispatcher_t -.
Definition: mutt_logging.c:87
log_dispatcher_t MuttLogger
The log dispatcher -.
Definition: logging.c:52
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to an internal queue - Implements log_dispatcher_t -.
Definition: logging.c:398
#define mutt_message(...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:91
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe() -.
Definition: nntp.c:2740
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe() -.
Definition: pop.c:1156
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2325
int main_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: keymap.c:895
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: mutt_history.c:61
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: mutt_logging.c:287
void mutt_gsasl_done(void)
Shutdown GNU SASL library.
Definition: gsasl.c:148
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:575
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition: header.h:42
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:928
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:589
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:57
void imap_logout_all(void)
Close all open connections.
Definition: imap.c:545
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:662
int mutt_query_variables(struct ListHead *queries, bool show_docs)
Implement the -Q command line flag.
Definition: init.c:611
void mutt_opts_free(void)
Clean up before quitting.
Definition: init.c:264
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:320
void init_config(struct ConfigSet *cs)
Initialise the config system.
Definition: mutt_config.c:742
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1930
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: keymap.c:873
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_MESSAGE
Log informational message.
Definition: logging2.h:42
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
@ LL_MAX
Definition: logging2.h:50
void log_queue_empty(void)
Free the contents of the queue.
Definition: logging.c:324
void log_queue_set_max_size(int size)
Set a upper limit for the queue length.
Definition: logging.c:312
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:346
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:88
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:177
@ MUTT_POP
'POP3' Mailbox type
Definition: mailbox.h:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
#define MUTT_CLI_SELECT
-y Start with a list of all mailboxes
Definition: main.c:208
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition: main.c:364
uint8_t CliFlags
Flags for command line options, e.g. MUTT_CLI_IGNORE.
Definition: main.c:202
static void log_translation(void)
Log the translation being used.
Definition: main.c:433
#define MUTT_CLI_MAILBOX
-Z Open first mailbox if is has new mail
Definition: main.c:205
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:218
static bool usage(void)
Display NeoMutt command line.
Definition: main.c:255
static int start_curses(void)
Start the Curses UI.
Definition: main.c:332
bool StartupComplete
When the config has been read.
Definition: main.c:199
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition: main.c:392
#define MUTT_CLI_RO
-R Open mailbox in read-only mode
Definition: main.c:207
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:203
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:204
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:210
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:206
#define FREE(x)
Definition: memory.h:43
void menu_cleanup(void)
Free the saved Menu searches.
Definition: menu.c:66
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: multipart.c:100
void mutt_ch_cache_cleanup(void)
Clean up the cached iconv handles and charset strings.
Definition: charset.c:1169
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:189
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
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:240
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
#define PATH_MAX
Definition: mutt.h:41
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1315
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:96
struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:81
@ MUTT_CURSOR_INVISIBLE
Hide the cursor.
Definition: mutt_curses.h:59
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition: mutt_curses.h:60
void mutt_log_stop(void)
Close the log file.
Definition: mutt_logging.c:183
int mutt_log_start(void)
Enable file logging.
Definition: mutt_logging.c:250
void mutt_log_prep(void)
Prepare to log.
Definition: mutt_logging.c:173
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:158
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Definition: mutt_mailbox.c:373
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:200
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:333
int mx_path_is_empty(const char *path)
Is the mailbox empty.
Definition: mx.c:1279
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:307
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition: mx.c:1767
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:64
#define MUTT_MAILBOX_CHECK_IMMEDIATE
Don't postpone the actual checking.
Definition: mxapi.h:77
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mxapi.h:61
#define MUTT_MAILBOX_CHECK_FORCE
Ignore MailboxTime and check for new mail.
Definition: mxapi.h:75
uint8_t CheckStatsFlags
Flags for mutt_mailbox_check.
Definition: mxapi.h:73
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the main NeoMutt object.
Definition: neomutt.c:44
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition: neomutt.c:64
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition: neomutt.h:52
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:564
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:78
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1021
@ 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
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1706
void buf_pool_free(void)
Release the Buffer pool.
Definition: pool.c:67
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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:491
void mutt_prex_free(void)
Cleanup heap memory allocated by compiled regexes.
Definition: prex.c:330
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
#define TAILQ_EMPTY(head)
Definition: queue.h:721
void rootwin_free(void)
Free all the default Windows.
Definition: rootwin.c:178
void rootwin_set_size(int cols, int rows)
Set the dimensions of the Root Window.
Definition: rootwin.c:226
void rootwin_new(void)
Create the default Windows.
Definition: rootwin.c:188
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:784
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:318
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
RFC2047 encode the content-descriptions.
Definition: send.c:1581
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:2128
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:45
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:49
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:50
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:44
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:39
uint16_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:38
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:601
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:774
The body of an email.
Definition: body.h:36
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct Body * next
next attachment in the list
Definition: body.h:71
size_t dsize
Length of data.
Definition: buffer.h:37
Container for lots of config items.
Definition: set.h:252
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
struct Body * body
List of MIME parts.
Definition: email.h:67
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:69
The header of an Email.
Definition: envelope.h:57
struct ListHead userhdrs
user defined headers
Definition: envelope.h:87
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
char * subject
Email's subject.
Definition: envelope.h:70
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:127
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
struct Connection * conn
Connection to NNTP Server.
Definition: adata.h:62
void subjrx_init(void)
Create new Subject Regex List.
Definition: subjectrx.c:55
void subjrx_free(void)
Free the Subject Regex List.
Definition: subjectrx.c:46
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:310
bool TsSupported
Terminal Setting is supported.
Definition: terminal.c:41
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition: terminal.c:55
#define buf_mktemp(buf)
Definition: tmp.h:37
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:225
@ U_MAILTO
Url is mailto://.
Definition: url.h:45
bool print_copyright(void)
Print copyright message.
Definition: version.c:548
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:420

Variable Documentation

◆ StartupComplete

bool StartupComplete = false

When the config has been read.

Definition at line 199 of file main.c.