NeoMutt  2024-04-25-34-g585158
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "history/lib.h"
#include "imap/lib.h"
#include "index/lib.h"
#include "key/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "nntp/lib.h"
#include "pop/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 "mutt_logging.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "nntp/adata.h"
#include "protos.h"
#include "subjectrx.h"
#include "version.h"
#include <libintl.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.
 
#define MUTT_CLI_IGNORE   (1 << 0)
 -z Open first mailbox if it has mail
 
#define MUTT_CLI_MAILBOX   (1 << 1)
 -Z Open first mailbox if is has new mail
 
#define MUTT_CLI_NOSYSRC   (1 << 2)
 -n Do not read the system-wide config file
 
#define MUTT_CLI_RO   (1 << 3)
 -R Open mailbox in read-only mode
 
#define MUTT_CLI_SELECT   (1 << 4)
 -y Start with a list of all mailboxes
 
#define MUTT_CLI_NEWS   (1 << 5)
 -g/-G Start with a list of all newsgroups
 

Typedefs

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

Functions

static void reset_tilde (struct ConfigSet *cs)
 Temporary measure.
 
static void localise_config (struct ConfigSet *cs)
 Localise some config.
 
void mutt_exit (int code)
 Leave NeoMutt NOW.
 
static bool usage (void)
 Display NeoMutt command line.
 
static int start_curses (void)
 Start the Curses UI.
 
static void init_locale (void)
 Initialise the Locale/NLS settings.
 
static bool get_user_info (struct ConfigSet *cs)
 Find the user's name, home and shell.
 
static void log_translation (void)
 Log the translation being used.
 
static void log_gui (void)
 Log info about the GUI.
 
int main_timeout_observer (struct NotifyCallback *nc)
 Notification that a timeout has occurred - Implements observer_t -.
 
int main (int argc, char *argv[], char *envp[])
 Start NeoMutt.
 

Variables

bool StartupComplete = false
 When the config has been read.
 

Detailed Description

Command line processing.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • g10 Code GmbH
  • Richard Russon
  • Pietro Cerutti
  • R Primus
  • Dennis Schön
  • Alejandro Colomar

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 132 of file main.c.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 195 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

Definition at line 196 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 197 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 198 of file main.c.

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 199 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

Definition at line 200 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 201 of file main.c.

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 194 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 208 of file main.c.

209{
210 static const char *names[] = { "folder", "mbox", "postponed", "record" };
211
212 struct Buffer *value = buf_pool_get();
213 for (size_t i = 0; i < mutt_array_size(names); i++)
214 {
215 struct HashElem *he = cs_get_elem(cs, names[i]);
216 if (!he)
217 continue;
218 buf_reset(value);
219 cs_he_initial_get(cs, he, value);
220 buf_expand_path_regex(value, false);
221 cs_he_initial_set(cs, he, value->data, NULL);
222 cs_he_reset(cs, he, NULL);
223 }
224 buf_pool_release(&value);
225}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:175
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:391
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:461
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:529
#define mutt_array_size(x)
Definition: memory.h:38
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:135
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
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
The item stored in a Hash Table.
Definition: hash.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ localise_config()

static void localise_config ( struct ConfigSet cs)
static

Localise some config.

Parameters
csConfig Set

Definition at line 232 of file main.c.

233{
234 static const char *names[] = {
235 "attribution_intro",
236 "compose_format",
237 "forward_attribution_intro",
238 "forward_attribution_trailer",
239 "reply_regex",
240 "status_format",
241 "ts_icon_format",
242 "ts_status_format",
243 };
244
245 struct Buffer *value = buf_pool_get();
246 for (size_t i = 0; i < mutt_array_size(names); i++)
247 {
248 struct HashElem *he = cs_get_elem(cs, names[i]);
249 if (!he)
250 continue;
251 buf_reset(value);
252 cs_he_initial_get(cs, he, value);
253
254 // Lookup the translation
255 const char *l10n = gettext(buf_string(value));
256
257 cs_he_initial_set(cs, he, l10n, NULL);
258 cs_he_reset(cs, he, NULL);
259 }
260 buf_pool_release(&value);
261}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
+ 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 268 of file main.c.

269{
270 mutt_endwin();
271#ifdef USE_DEBUG_BACKTRACE
272 if (code != 0)
274#endif
275 exit(code);
276}
void show_backtrace(void)
Log the program's call stack.
Definition: backtrace.c:39
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
+ 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 282 of file main.c.

283{
284 puts(mutt_make_version());
285
286 // clang-format off
287 /* L10N: Try to limit to 80 columns */
288 puts(_("usage:"));
289 puts(_(" neomutt [-CEnx] [-e <command>] [-F <config>] [-H <draft>] [-i <include>]\n"
290 " [-b <address>] [-c <address>] [-s <subject>] [-a <file> [...] --]\n"
291 " <address> [...]"));
292 puts(_(" neomutt [-Cnx] [-e <command>] [-F <config>] [-b <address>] [-c <address>]\n"
293 " [-s <subject>] [-a <file> [...] --] <address> [...] < message"));
294 puts(_(" neomutt [-nRy] [-e <command>] [-F <config>] [-f <mailbox>] [-m <type>]"));
295 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -A <alias>"));
296 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -B"));
297 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -D [-S] [-O]"));
298 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -d <level> -l <file>"));
299 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -G"));
300 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -g <server>"));
301 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -p"));
302 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Q <variable> [-O]"));
303 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Z"));
304 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -z [-f <mailbox>]"));
305 puts(_(" neomutt -v[v]\n"));
306
307 /* L10N: Try to limit to 80 columns. If more space is needed add an indented line */
308 puts(_("options:"));
309 puts(_(" -- Special argument forces NeoMutt to stop option parsing and treat\n"
310 " remaining arguments as addresses even if they start with a dash"));
311 puts(_(" -A <alias> Print an expanded version of the given alias to stdout and exit"));
312 puts(_(" -a <file> Attach one or more files to a message (must be the last option)\n"
313 " Add any addresses after the '--' argument"));
314 puts(_(" -B Run in batch mode (do not start the ncurses UI)"));
315 puts(_(" -b <address> Specify a blind carbon copy (Bcc) recipient"));
316 puts(_(" -c <address> Specify a carbon copy (Cc) recipient"));
317 puts(_(" -C Enable Command-line Crypto (signing/encryption)"));
318 puts(_(" -D Dump all config variables as 'name=value' pairs to stdout"));
319 puts(_(" -D -O Like -D, but show one-liner documentation"));
320 puts(_(" -D -S Like -D, but hide the value of sensitive variables"));
321 puts(_(" -d <level> Log debugging output to a file (default is \"~/.neomuttdebug0\")\n"
322 " The level can range from 1-5 and affects verbosity"));
323 puts(_(" -E Edit draft (-H) or include (-i) file during message composition"));
324 puts(_(" -e <command> Specify a command to be run after reading the config files"));
325 puts(_(" -F <config> Specify an alternative initialization file to read"));
326 puts(_(" -f <mailbox> Specify a mailbox (as defined with 'mailboxes' command) to load"));
327 puts(_(" -G Start NeoMutt with a listing of subscribed newsgroups"));
328 puts(_(" -g <server> Like -G, but start at specified news server"));
329 puts(_(" -H <draft> Specify a draft file with header and body for message composing"));
330 puts(_(" -h Print this help message and exit"));
331 puts(_(" -i <include> Specify an include file to be embedded in the body of a message"));
332 puts(_(" -l <file> Specify a file for debugging output (default \"~/.neomuttdebug0\")"));
333 puts(_(" -m <type> Specify a default mailbox format type for newly created folders\n"
334 " The type is either MH, MMDF, Maildir or mbox (case-insensitive)"));
335 puts(_(" -n Do not read the system-wide configuration file"));
336 puts(_(" -p Resume a prior postponed message, if any"));
337 puts(_(" -Q <variable> Query a configuration variable and print its value to stdout\n"
338 " (after the config has been read and any commands executed)\n"
339 " Add -O for one-liner documentation"));
340 puts(_(" -R Open mailbox in read-only mode"));
341 puts(_(" -s <subject> Specify a subject (must be enclosed in quotes if it has spaces)"));
342 puts(_(" -v Print the NeoMutt version and compile-time definitions and exit"));
343 puts(_(" -vv Print the NeoMutt license and copyright information and exit"));
344 puts(_(" -y Start NeoMutt with a listing of all defined mailboxes"));
345 puts(_(" -Z Open the first mailbox with new message or exit immediately with\n"
346 " exit code 1 if none is found in all defined mailboxes"));
347 puts(_(" -z Open the first or specified (-f) mailbox if it holds any message\n"
348 " or exit immediately with exit code 1 otherwise"));
349 // clang-format on
350
351 fflush(stdout);
352 return !ferror(stdout);
353}
#define _(a)
Definition: message.h:28
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:893
+ 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 360 of file main.c.

361{
362 km_init(); /* must come before mutt_init */
363
364 /* should come before initscr() so that ncurses 4.2 doesn't try to install
365 * its own SIGWINCH handler */
367
368 if (!initscr())
369 {
370 mutt_error(_("Error initializing terminal"));
371 return 1;
372 }
373
375 keypad(stdscr, true);
376 cbreak();
377 noecho();
378 nonl();
379 typeahead(-1); /* simulate smooth scrolling */
380 meta(stdscr, true);
382 /* Now that curses is set up, we drop back to normal screen mode.
383 * This simplifies displaying error messages to the user.
384 * The first call to refresh() will swap us back to curses screen mode. */
385 endwin();
386 return 0;
387}
void mutt_colors_init(void)
Initialize colours.
Definition: color.c:74
#define mutt_error(...)
Definition: logging2.h:92
void km_init(void)
Initialise all the menu keybindings.
Definition: init.c:180
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: init.c:137
void mutt_signal_init(void)
Initialise the signal handling.
Definition: mutt_signal.c:130
+ 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 392 of file main.c.

393{
394 setlocale(LC_ALL, "");
395
396#ifdef ENABLE_NLS
397 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
398 if (domdir)
399 bindtextdomain(PACKAGE, domdir);
400 else
401 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
402 textdomain(PACKAGE);
403#endif
404#ifndef LOCALES_HACK
405 /* Do we have a locale definition? */
406 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
407 {
408 OptLocales = true;
409 }
410#endif
411}
bool OptLocales
(pseudo) set if user has valid locale definition
Definition: mbyte.c:44
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:727
+ 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 420 of file main.c.

421{
422 const char *shell = mutt_str_getenv("SHELL");
423 if (shell)
424 cs_str_initial_set(cs, "shell", shell, NULL);
425
426 /* Get some information about the user */
427 struct passwd *pw = getpwuid(getuid());
428 if (pw)
429 {
430 if (!Username)
431 Username = mutt_str_dup(pw->pw_name);
432 if (!HomeDir)
433 HomeDir = mutt_str_dup(pw->pw_dir);
434 if (!shell)
435 cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
436 }
437
438 if (!Username)
439 {
440 mutt_error(_("unable to determine username"));
441 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
442 }
443
444 if (!HomeDir)
445 {
446 mutt_error(_("unable to determine home directory"));
447 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
448 }
449
450 cs_str_reset(cs, "shell", NULL);
451 return true;
452}
char * HomeDir
User's home directory.
Definition: globals.c:38
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:503
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:438
char * Username
User's login name.
Definition: globals.c:41
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
+ 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 461 of file main.c.

462{
463 const char *header = ""; // Do not merge these two lines
464 header = _(header); // otherwise the .po files will end up badly ordered
465 const char *label = "Language:"; // the start of the lookup/needle
466 const char *lang = mutt_istr_find(header, label);
467 int len = 64;
468 if (lang)
469 {
470 lang += strlen(label); // skip label
471 SKIPWS(lang);
472 char *nl = strchr(lang, '\n');
473 if (nl)
474 len = (nl - lang);
475 }
476 else
477 {
478 lang = "NONE";
479 }
480
481 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
482}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ 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:522
#define SKIPWS(ch)
Definition: string2.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_gui()

static void log_gui ( void  )
static

Log info about the GUI.

Definition at line 487 of file main.c.

488{
489 const char *term = mutt_str_getenv("TERM");
490 const char *color_term = mutt_str_getenv("COLORTERM");
491 bool true_color = false;
492#ifdef NEOMUTT_DIRECT_COLORS
493 true_color = true;
494#endif
495
496 mutt_debug(LL_DEBUG1, "GUI:\n");
497 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
498 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
499 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
500 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
501 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
502 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
503 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
505}
struct MuttWindow * RootWindow
Parent of all Windows.
Definition: rootwin.c:106
#define NONULL(x)
Definition: string2.h:37
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61
+ 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 551 of file main.c.

554{
555 char *subject = NULL;
556 char *include_file = NULL;
557 char *draft_file = NULL;
558 char *new_type = NULL;
559 char *dlevel = NULL;
560 char *dfile = NULL;
561 const char *cli_nntp = NULL;
562 struct Email *e = NULL;
563 struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
564 struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
565 struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
566 struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
567 struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
568 struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
569 SendFlags sendflags = SEND_NO_FLAGS;
571 int version = 0;
572 int i;
573 bool explicit_folder = false;
574 bool dump_variables = false;
575 bool one_liner = false;
576 bool hide_sensitive = false;
577 bool batch_mode = false;
578 bool edit_infile = false;
579 int double_dash = argc, nargc = 1;
580 int rc = 1;
581 bool repeat_error = false;
582 struct Buffer *folder = buf_pool_get();
583 struct Buffer *expanded_infile = buf_pool_get();
584 struct Buffer *tempfile = buf_pool_get();
585 struct ConfigSet *cs = NULL;
586
588
589 /* sanity check against stupid administrators */
590 if (getegid() != getgid())
591 {
592 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
593 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
594 }
595
596 init_locale();
597
598 EnvList = envlist_init(envp);
599 for (optind = 1; optind < double_dash;)
600 {
601 /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
602 * encounters a non-option. That could be a file to attach
603 * (all non-options between -a and --) or it could be an address
604 * (which gets collapsed to the front of argv). */
605 for (; optind < argc; optind++)
606 {
607 if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
608 {
609 if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
610 double_dash = optind; /* quit outer loop after getopt */
611 break; /* drop through to getopt */
612 }
613
614 /* non-option, either an attachment or address */
615 if (!STAILQ_EMPTY(&attach))
616 mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
617 else
618 argv[nargc++] = argv[optind];
619 }
620
621 i = getopt(argc, argv, "+A:a:Bb:F:f:Cc:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvxyzZ");
622 if (i != EOF)
623 {
624 switch (i)
625 {
626 case 'A':
627 mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
628 break;
629 case 'a':
630 mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
631 break;
632 case 'B':
633 batch_mode = true;
634 break;
635 case 'b':
636 mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
637 break;
638 case 'C':
639 sendflags |= SEND_CLI_CRYPTO;
640 break;
641 case 'c':
642 mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
643 break;
644 case 'D':
645 dump_variables = true;
646 break;
647 case 'd':
648 dlevel = optarg;
649 break;
650 case 'E':
651 edit_infile = true;
652 break;
653 case 'e':
654 mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
655 break;
656 case 'F':
658 break;
659 case 'f':
660 buf_strcpy(folder, optarg);
661 explicit_folder = true;
662 break;
663 case 'g': /* Specify a news server */
664 cli_nntp = optarg;
666
667 case 'G': /* List of newsgroups */
669 break;
670 case 'H':
671 draft_file = optarg;
672 break;
673 case 'i':
674 include_file = optarg;
675 break;
676 case 'l':
677 dfile = optarg;
678 break;
679 case 'm':
680 new_type = optarg;
681 break;
682 case 'n':
683 flags |= MUTT_CLI_NOSYSRC;
684 break;
685 case 'O':
686 one_liner = true;
687 break;
688 case 'p':
689 sendflags |= SEND_POSTPONED;
690 break;
691 case 'Q':
692 mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
693 break;
694 case 'R':
695 flags |= MUTT_CLI_RO; /* read-only mode */
696 break;
697 case 'S':
698 hide_sensitive = true;
699 break;
700 case 's':
701 subject = optarg;
702 break;
703 case 'v':
704 version++;
705 break;
706 case 'y': /* My special hack mode */
707 flags |= MUTT_CLI_SELECT;
708 break;
709 case 'Z':
711 break;
712 case 'z':
713 flags |= MUTT_CLI_IGNORE;
714 break;
715 default:
716 OptNoCurses = true;
717 if (usage())
718 goto main_ok; // TEST03: neomutt -9
719 else
720 goto main_curses;
721 }
722 }
723 }
724
725 /* collapse remaining argv */
726 while (optind < argc)
727 argv[nargc++] = argv[optind++];
728 optind = 1;
729 argc = nargc;
730
731 if (version > 0)
732 {
734 bool done;
735 if (version == 1)
736 done = print_version(stdout);
737 else
738 done = print_copyright();
739 OptNoCurses = true;
740 if (done)
741 goto main_ok; // TEST04: neomutt -v
742 else
743 goto main_curses;
744 }
745
748
749 cs = cs_new(500);
750 if (!cs)
751 goto main_curses;
752
753 NeoMutt = neomutt_new(cs);
754 init_config(cs);
755
756 // Change the current umask, and save the original one
757 NeoMutt->user_default_umask = umask(077);
758 subjrx_init();
759 attach_init();
761
762#ifdef USE_DEBUG_NOTIFY
764#endif
765
766 if (!get_user_info(cs))
767 goto main_exit;
768
769 reset_tilde(cs);
770#ifdef ENABLE_NLS
771 localise_config(cs);
772#endif
773
774 if (dfile)
775 {
776 cs_str_initial_set(cs, "debug_file", dfile, NULL);
777 cs_str_reset(cs, "debug_file", NULL);
778 }
779
780 if (dlevel)
781 {
782 short num = 0;
783 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
784 {
785 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
786 goto main_exit; // TEST07: neomutt -d xyz
787 }
788 cs_str_initial_set(cs, "debug_level", dlevel, NULL);
789 cs_str_reset(cs, "debug_level", NULL);
790 }
791
795 mutt_debug(LL_DEBUG1, "user's umask %03o\n", NeoMutt->user_default_umask);
796 mutt_debug(LL_DEBUG3, "umask set to 077\n");
797
798 if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
799 {
800 e = email_new();
801 e->env = mutt_env_new();
802
803 struct ListNode *np = NULL;
804 STAILQ_FOREACH(np, &bcc_list, entries)
805 {
806 mutt_addrlist_parse(&e->env->bcc, np->data);
807 }
808
809 STAILQ_FOREACH(np, &cc_list, entries)
810 {
811 mutt_addrlist_parse(&e->env->cc, np->data);
812 }
813
814 mutt_list_free(&bcc_list);
815 mutt_list_free(&cc_list);
816 }
817
818 /* Check for a batch send. */
819 if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
820 dump_variables || batch_mode)
821 {
822 OptNoCurses = true;
823 sendflags |= SEND_BATCH;
826 }
827
828 /* Check to make sure stdout is available in curses mode. */
829 if (!OptNoCurses && !isatty(1))
830 goto main_curses;
831
832 /* This must come before mutt_init() because curses needs to be started
833 * before calling the init_pair() function to set the color scheme. */
834 if (!OptNoCurses)
835 {
836 int crc = start_curses();
837 if (crc != 0)
838 goto main_curses; // TEST08: can't test -- fake term?
839 }
840
841 /* Always create the mutt_windows because batch mode has some shared code
842 * paths that end up referencing them. */
843 rootwin_new();
844
845 if (!OptNoCurses)
846 {
847 /* check whether terminal status is supported (must follow curses init) */
850 log_gui();
851 }
852
853 /* set defaults and read init files */
854 int rc2 = mutt_init(cs, dlevel, dfile, flags & MUTT_CLI_NOSYSRC, &commands);
855 if (rc2 != 0)
856 goto main_curses;
857
859
860 /* "$news_server" precedence: command line, config file, environment, system file */
861 if (!cli_nntp)
862 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
863
864 if (!cli_nntp)
865 cli_nntp = mutt_str_getenv("NNTPSERVER");
866
867 if (!cli_nntp)
868 {
869 char buf[1024] = { 0 };
870 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
871 }
872
873 if (cli_nntp)
874 {
875 cs_str_initial_set(cs, "news_server", cli_nntp, NULL);
876 cs_str_reset(cs, "news_server", NULL);
877 }
878
879 /* Initialize crypto backends. */
880 crypt_init();
881
882 if (new_type)
883 {
884 struct Buffer *err = buf_pool_get();
885 int r = cs_str_initial_set(cs, "mbox_type", new_type, err);
886 if (CSR_RESULT(r) != CSR_SUCCESS)
887 {
888 mutt_error("%s", buf_string(err));
889 buf_pool_release(&err);
890 goto main_curses;
891 }
892 cs_str_reset(cs, "mbox_type", NULL);
893 }
894
895 if (!STAILQ_EMPTY(&queries))
896 {
897 rc = mutt_query_variables(&queries, one_liner);
898 goto main_curses;
899 }
900
901 if (dump_variables)
902 {
904 if (hide_sensitive)
905 cdflags |= CS_DUMP_HIDE_SENSITIVE;
906 if (one_liner)
907 cdflags |= CS_DUMP_SHOW_DOCS;
908 dump_config(cs, cdflags, stdout);
909 goto main_ok; // TEST18: neomutt -D
910 }
911
912 if (!STAILQ_EMPTY(&alias_queries))
913 {
914 rc = 0;
915 for (; optind < argc; optind++)
916 mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
917 struct ListNode *np = NULL;
918 STAILQ_FOREACH(np, &alias_queries, entries)
919 {
920 struct AddressList *al = alias_lookup(np->data);
921 if (al)
922 {
923 /* output in machine-readable form */
924 mutt_addrlist_to_intl(al, NULL);
925 struct Buffer *buf = buf_pool_get();
926 mutt_addrlist_write(al, buf, false);
927 printf("%s\n", buf_string(buf));
928 buf_pool_release(&buf);
929 }
930 else
931 {
932 rc = 1;
933 printf("%s\n", np->data); // TEST19: neomutt -A unknown
934 }
935 }
936 mutt_list_free(&alias_queries);
937 goto main_curses; // TEST20: neomutt -A alias
938 }
939
940 if (!OptNoCurses)
941 {
943 clear();
947 }
948
949#ifdef USE_AUTOCRYPT
950 /* Initialize autocrypt after curses messages are working,
951 * because of the initial account setup screens. */
952 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
953 if (c_autocrypt)
954 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
955#endif
956
957 /* Create the `$folder` directory if it doesn't exist. */
958 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
959 if (!OptNoCurses && c_folder)
960 {
961 struct stat st = { 0 };
962 struct Buffer *fpath = buf_pool_get();
963
964 buf_strcpy(fpath, c_folder);
965 buf_expand_path(fpath);
966 bool skip = false;
967 /* we're not connected yet - skip mail folder creation */
968 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
969 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
970 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
971 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
972 {
973 char msg2[256] = { 0 };
974 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
975 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
976 {
977 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
978 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
979 }
980 }
981 buf_pool_release(&fpath);
982 }
983
984 if (batch_mode)
985 {
986 goto main_ok; // TEST22: neomutt -B
987 }
988 StartupComplete = true;
989
994
995 if (sendflags & SEND_POSTPONED)
996 {
997 if (!OptNoCurses)
999 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1000 rc = 0;
1001 // TEST23: neomutt -p (postponed message, cancel)
1002 // TEST24: neomutt -p (no postponed message)
1004 repeat_error = true;
1005 goto main_curses;
1006 }
1007 else if (subject || e || draft_file || include_file ||
1008 !STAILQ_EMPTY(&attach) || (optind < argc))
1009 {
1010 FILE *fp_in = NULL;
1011 FILE *fp_out = NULL;
1012 char *infile = NULL;
1013 char *bodytext = NULL;
1014 const char *bodyfile = NULL;
1015 int rv = 0;
1016
1017 if (!OptNoCurses)
1018 mutt_flushinp();
1019
1020 if (!e)
1021 e = email_new();
1022 if (!e->env)
1023 e->env = mutt_env_new();
1024
1025 for (i = optind; i < argc; i++)
1026 {
1027 if (url_check_scheme(argv[i]) == U_MAILTO)
1028 {
1029 if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
1030 {
1031 mutt_error(_("Failed to parse mailto: link"));
1032 email_free(&e);
1033 goto main_curses; // TEST25: neomutt mailto:?
1034 }
1035 }
1036 else
1037 {
1038 mutt_addrlist_parse(&e->env->to, argv[i]);
1039 }
1040 }
1041
1042 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1043 if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
1044 TAILQ_EMPTY(&e->env->cc))
1045 {
1046 mutt_error(_("No recipients specified"));
1047 email_free(&e);
1048 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1049 }
1050
1051 if (subject)
1052 {
1053 /* prevent header injection */
1055 mutt_env_set_subject(e->env, subject);
1056 }
1057
1058 if (draft_file)
1059 {
1060 infile = draft_file;
1061 include_file = NULL;
1062 }
1063 else if (include_file)
1064 {
1065 infile = include_file;
1066 }
1067 else
1068 {
1069 edit_infile = false;
1070 }
1071
1072 if (infile || bodytext)
1073 {
1074 /* Prepare fp_in and expanded_infile. */
1075 if (infile)
1076 {
1077 if (mutt_str_equal("-", infile))
1078 {
1079 if (edit_infile)
1080 {
1081 mutt_error(_("Can't use -E flag with stdin"));
1082 email_free(&e);
1083 goto main_curses; // TEST27: neomutt -E -H -
1084 }
1085 fp_in = stdin;
1086 }
1087 else
1088 {
1089 buf_strcpy(expanded_infile, infile);
1090 buf_expand_path(expanded_infile);
1091 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1092 if (!fp_in)
1093 {
1094 mutt_perror("%s", buf_string(expanded_infile));
1095 email_free(&e);
1096 goto main_curses; // TEST28: neomutt -E -H missing
1097 }
1098 }
1099 }
1100
1101 if (edit_infile)
1102 {
1103 /* If editing the infile, keep it around afterwards so
1104 * it doesn't get unlinked, and we can rebuild the draft_file */
1105 sendflags |= SEND_NO_FREE_HEADER;
1106 }
1107 else
1108 {
1109 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1110 * Note: stdin is always copied to a tempfile, ensuring draft_file
1111 * can stat and get the correct st_size below. */
1112 buf_mktemp(tempfile);
1113
1114 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1115 if (!fp_out)
1116 {
1117 mutt_file_fclose(&fp_in);
1118 mutt_perror("%s", buf_string(tempfile));
1119 email_free(&e);
1120 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1121 }
1122 if (fp_in)
1123 {
1124 mutt_file_copy_stream(fp_in, fp_out);
1125 if (fp_in == stdin)
1126 sendflags |= SEND_CONSUMED_STDIN;
1127 else
1128 mutt_file_fclose(&fp_in);
1129 }
1130 else if (bodytext)
1131 {
1132 fputs(bodytext, fp_out);
1133 }
1134 mutt_file_fclose(&fp_out);
1135
1136 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1137 if (!fp_in)
1138 {
1139 mutt_perror("%s", buf_string(tempfile));
1140 email_free(&e);
1141 goto main_curses; // TEST30: can't test
1142 }
1143 }
1144
1145 /* Parse the draft_file into the full Email/Body structure.
1146 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1147 * our e->body. */
1148 if (draft_file)
1149 {
1150 struct Envelope *opts_env = e->env;
1151 struct stat st = { 0 };
1152
1153 sendflags |= SEND_DRAFT_FILE;
1154
1155 /* Set up a tmp Email with just enough information so that
1156 * mutt_prepare_template() can parse the message in fp_in. */
1157 struct Email *e_tmp = email_new();
1158 e_tmp->offset = 0;
1159 e_tmp->body = mutt_body_new();
1160 if (fstat(fileno(fp_in), &st) != 0)
1161 {
1162 mutt_perror("%s", draft_file);
1163 email_free(&e);
1164 email_free(&e_tmp);
1165 goto main_curses; // TEST31: can't test
1166 }
1167 e_tmp->body->length = st.st_size;
1168
1169 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1170 {
1171 mutt_error(_("Can't parse message template: %s"), draft_file);
1172 email_free(&e);
1173 email_free(&e_tmp);
1174 goto main_curses;
1175 }
1176
1177 /* Scan for neomutt header to set `$resume_draft_files` */
1178 struct ListNode *np = NULL, *tmp = NULL;
1179 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1180 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1181 {
1182 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1183 {
1184 if (c_resume_edited_draft_files)
1185 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1186
1187 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1188 FREE(&np->data);
1189 FREE(&np);
1190 }
1191 }
1192
1193 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1194 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1195 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1196 if (opts_env->subject)
1197 mutt_env_set_subject(e->env, opts_env->subject);
1198
1199 mutt_env_free(&opts_env);
1200 email_free(&e_tmp);
1201 }
1202 /* Editing the include_file: pass it directly in.
1203 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1204 else if (edit_infile)
1205 bodyfile = buf_string(expanded_infile);
1206 // For bodytext and unedited include_file: use the tempfile.
1207 else
1208 bodyfile = buf_string(tempfile);
1209
1210 mutt_file_fclose(&fp_in);
1211 }
1212
1213 FREE(&bodytext);
1214
1215 if (!STAILQ_EMPTY(&attach))
1216 {
1217 struct Body *b = e->body;
1218
1219 while (b && b->next)
1220 b = b->next;
1221
1222 struct ListNode *np = NULL;
1223 STAILQ_FOREACH(np, &attach, entries)
1224 {
1225 if (b)
1226 {
1228 b = b->next;
1229 }
1230 else
1231 {
1233 e->body = b;
1234 }
1235 if (!b)
1236 {
1237 mutt_error(_("%s: unable to attach file"), np->data);
1238 mutt_list_free(&attach);
1239 email_free(&e);
1240 goto main_curses; // TEST32: neomutt john@example.com -a missing
1241 }
1242 }
1243 mutt_list_free(&attach);
1244 }
1245
1246 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1247 /* We WANT the "Mail sent." and any possible, later error */
1249 if (ErrorBufMessage)
1250 mutt_message("%s", ErrorBuf);
1251
1252 if (edit_infile)
1253 {
1254 if (draft_file)
1255 {
1256 if (truncate(buf_string(expanded_infile), 0) == -1)
1257 {
1258 mutt_perror("%s", buf_string(expanded_infile));
1259 email_free(&e);
1260 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1261 }
1262 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1263 if (!fp_out)
1264 {
1265 mutt_perror("%s", buf_string(expanded_infile));
1266 email_free(&e);
1267 goto main_curses; // TEST34: can't test
1268 }
1269
1270 /* If the message was sent or postponed, these will already
1271 * have been done. */
1272 if (rv < 0)
1273 {
1274 if (e->body->next)
1275 e->body = mutt_make_multipart(e->body);
1277 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1278 mutt_env_to_intl(e->env, NULL, NULL);
1279 }
1280
1281 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1283 c_crypt_protected_headers_read &&
1285 NeoMutt->sub);
1286 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1287 if (c_resume_edited_draft_files)
1288 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1289 fputc('\n', fp_out);
1290 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1291 {
1292 mutt_file_fclose(&fp_out);
1293 email_free(&e);
1294 goto main_curses; // TEST35: can't test
1295 }
1296 mutt_file_fclose(&fp_out);
1297 }
1298
1299 email_free(&e);
1300 }
1301
1302 /* !edit_infile && draft_file will leave the tempfile around */
1303 if (!buf_is_empty(tempfile))
1304 unlink(buf_string(tempfile));
1305
1307
1308 if (rv != 0)
1309 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1310 }
1311 else if (sendflags & SEND_BATCH)
1312 {
1313 /* This guards against invoking `neomutt < /dev/null` and accidentally
1314 * sending an email due to a my_hdr or other setting. */
1315 mutt_error(_("No recipients specified"));
1316 goto main_curses;
1317 }
1318 else
1319 {
1320 if (flags & MUTT_CLI_MAILBOX)
1321 {
1322 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1323 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1325 if (mutt_mailbox_check(NULL, csflags) == 0)
1326 {
1327 mutt_message(_("No mailbox with new mail"));
1328 goto main_curses; // TEST37: neomutt -Z (no new mail)
1329 }
1330 buf_reset(folder);
1331 mutt_mailbox_next(NULL, folder);
1332 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1333 }
1334 else if (flags & MUTT_CLI_SELECT)
1335 {
1336 if (flags & MUTT_CLI_NEWS)
1337 {
1338 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1339 OptNews = true;
1340 CurrentNewsSrv = nntp_select_server(NULL, c_news_server, false);
1341 if (!CurrentNewsSrv)
1342 goto main_curses; // TEST38: neomutt -G (unset news_server)
1343 }
1344 else if (TAILQ_EMPTY(&NeoMutt->accounts))
1345 {
1346 mutt_error(_("No incoming mailboxes defined"));
1347 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1348 }
1349 buf_reset(folder);
1350 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1351 if (buf_is_empty(folder))
1352 {
1353 goto main_ok; // TEST40: neomutt -y (quit selection)
1354 }
1355 }
1356
1357 if (buf_is_empty(folder))
1358 {
1359 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1360 if (c_spool_file)
1361 {
1362 // Check if `$spool_file` corresponds a mailboxes' description.
1363 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1364 if (m_desc)
1365 buf_strcpy(folder, m_desc->realpath);
1366 else
1367 buf_strcpy(folder, c_spool_file);
1368 }
1369 else if (c_folder)
1370 {
1371 buf_strcpy(folder, c_folder);
1372 }
1373 /* else no folder */
1374 }
1375
1376 if (OptNews)
1377 {
1378 OptNews = false;
1379 buf_alloc(folder, PATH_MAX);
1380 nntp_expand_path(folder->data, folder->dsize, &CurrentNewsSrv->conn->account);
1381 }
1382 else
1383 {
1384 buf_expand_path(folder);
1385 }
1386
1389
1390 if (flags & MUTT_CLI_IGNORE)
1391 {
1392 /* check to see if there are any messages in the folder */
1393 switch (mx_path_is_empty(folder))
1394 {
1395 case -1:
1396 mutt_perror("%s", buf_string(folder));
1397 goto main_curses; // TEST41: neomutt -z -f missing
1398 case 1:
1399 mutt_error(_("Mailbox is empty"));
1400 goto main_curses; // TEST42: neomutt -z -f /dev/null
1401 }
1402 }
1403
1404 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1405 mutt_folder_hook(buf_string(folder), m_cur ? m_cur->name : NULL);
1407 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1409
1411 window_redraw(NULL);
1412
1413 repeat_error = true;
1414 struct Mailbox *m = mx_resolve(buf_string(folder));
1415 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1416 if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1417 {
1418 if (m->account)
1420
1421 mailbox_free(&m);
1422 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1423 repeat_error = false;
1424 }
1425 if (m || !explicit_folder)
1426 {
1427 struct MuttWindow *dlg = index_pager_init();
1428 dialog_push(dlg);
1429
1431 m = dlg_index(dlg, m);
1433 mailbox_free(&m);
1434
1435 dialog_pop();
1436 mutt_window_free(&dlg);
1438 repeat_error = false;
1439 }
1441#ifdef USE_SASL_CYRUS
1443#endif
1444#ifdef USE_SASL_GNU
1446#endif
1447#ifdef USE_AUTOCRYPT
1449#endif
1450 // TEST43: neomutt (no change to mailbox)
1451 // TEST44: neomutt (change mailbox)
1452 }
1453
1454main_ok:
1455 rc = 0;
1456main_curses:
1457 mutt_endwin();
1459 /* Repeat the last message to the user */
1460 if (repeat_error && ErrorBufMessage)
1461 puts(ErrorBuf);
1462main_exit:
1463 if (NeoMutt && NeoMutt->sub)
1464 {
1469 }
1470 mutt_list_free(&commands);
1472 buf_pool_release(&folder);
1473 buf_pool_release(&expanded_infile);
1474 buf_pool_release(&tempfile);
1475 mutt_list_free(&queries);
1482 menu_cleanup();
1483 crypt_cleanup();
1493 cs_free(&cs);
1495 mutt_log_stop();
1496 return rc;
1497}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:765
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1206
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1293
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
void alternates_cleanup(void)
Free the alternates lists.
Definition: alternates.c:49
void alternates_init(void)
Set up the alternates lists.
Definition: alternates.c:60
void attach_init(void)
Set up the attachments lists.
Definition: attachments.c:106
void attach_cleanup(void)
Free the attachments lists.
Definition: attachments.c:92
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:131
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:99
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: lib.h:58
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: lib.h:60
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:59
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:167
#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
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:141
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:127
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:760
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void config_cache_cleanup(void)
Cleanup the cache of charset config variables.
Definition: config_cache.c:145
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:98
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:188
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:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1086
void crypto_module_cleanup(void)
Clean up the crypto modules.
Definition: crypt_mod.c:84
void crypt_cleanup(void)
Clean up backend.
Definition: cryptglue.c:141
void crypt_init(void)
Initialise the crypto backends.
Definition: cryptglue.c:93
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:57
int debug_all_observer(struct NotifyCallback *nc)
Definition: notify.c:205
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:142
void mutt_browser_cleanup(void)
Clean up working Buffers.
Definition: dlg_browser.c:163
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition: dlg_index.c:1405
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:80
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:46
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1749
void mutt_filter_commandline_header_value(char *header)
Sanitise characters in a header value.
Definition: parse.c:93
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:355
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition: envelope.c:69
void envlist_free(char ***envp)
Free the private copy of the environment.
Definition: envlist.c:42
char ** envlist_init(char **envp)
Create a copy of the environment.
Definition: envlist.c:58
void external_cleanup(void)
Clean up commands globals.
Definition: external.c:81
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:286
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition: file.c:1405
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
bool OptNews
(pseudo) used to change reader mode
Definition: globals.c:70
char * LastFolder
Previously selected mailbox.
Definition: globals.c:44
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:72
char ErrorBuf[1024]
Copy of the last error message.
Definition: globals.c:36
bool ErrorBufMessage
true if the last message was an error
Definition: globals.c:35
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:43
struct ListHead Muttrc
List of config files to read.
Definition: globals.c:52
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
void dlg_browser(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file -.
Definition: dlg_browser.c:1296
struct Mailbox * dlg_index(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails -.
Definition: dlg_index.c:1071
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:398
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:441
int log_disp_curses(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Display a log line in the message line - Implements log_dispatcher_t -.
Definition: mutt_logging.c:88
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_perror(...)
Definition: logging2.h:93
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe() -.
Definition: nntp.c:2786
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe() -.
Definition: pop.c:1157
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2345
int main_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: init.c:265
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has change - Implements observer_t -.
Definition: history.c:704
int main_timeout_observer(struct NotifyCallback *nc)
Notification that a timeout has occurred - Implements observer_t -.
Definition: main.c:510
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: mutt_logging.c:285
void mutt_gsasl_cleanup(void)
Shutdown GNU SASL library.
Definition: gsasl.c:148
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:577
@ 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:956
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:623
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:54
void imap_logout_all(void)
Close all open connections.
Definition: imap.c:554
int mutt_query_variables(struct ListHead *queries, bool show_docs)
Implement the -Q command line flag.
Definition: init.c:621
int mutt_init(struct ConfigSet *cs, const char *dlevel, const char *dfile, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:318
void mutt_opts_cleanup(void)
Clean up before quitting.
Definition: init.c:262
void init_config(struct ConfigSet *cs)
Initialise the config system.
Definition: mutt_config.c:1055
void mutt_keys_cleanup(void)
Free the key maps.
Definition: init.c:230
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: init.c:243
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
int(*) log_dispatcher_ MuttLogger)
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_MESSAGE
Log informational message.
Definition: logging2.h:42
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
@ LL_MAX
Definition: logging2.h:50
#define MUTT_CLI_SELECT
-y Start with a list of all mailboxes
Definition: main.c:200
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition: main.c:392
static void localise_config(struct ConfigSet *cs)
Localise some config.
Definition: main.c:232
uint8_t CliFlags
Flags for command line options, e.g. MUTT_CLI_IGNORE.
Definition: main.c:194
static void log_translation(void)
Log the translation being used.
Definition: main.c:461
#define MUTT_CLI_MAILBOX
-Z Open first mailbox if is has new mail
Definition: main.c:197
static void log_gui(void)
Log info about the GUI.
Definition: main.c:487
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:208
static bool usage(void)
Display NeoMutt command line.
Definition: main.c:282
static int start_curses(void)
Start the Curses UI.
Definition: main.c:360
bool StartupComplete
When the config has been read.
Definition: main.c:191
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition: main.c:420
#define MUTT_CLI_RO
-R Open mailbox in read-only mode
Definition: main.c:199
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:195
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:196
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:201
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:198
#define FREE(x)
Definition: memory.h:45
void menu_cleanup(void)
Free the saved Menu searches.
Definition: menu.c:70
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:1178
#define FALLTHROUGH
Definition: lib.h:111
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
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
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:243
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:281
#define PATH_MAX
Definition: mutt.h:42
void mutt_temp_attachments_cleanup(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1308
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition: mutt_curses.c:94
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:79
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size.
Definition: resize.c:75
@ 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.
Definition: mutt_logging.c:181
void mutt_log_prep(void)
Prepare to log.
Definition: mutt_logging.c:171
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:168
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Definition: mutt_mailbox.c:360
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:634
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:202
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:328
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:286
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition: mx.c:1703
int mx_path_is_empty(struct Buffer *path)
Is the mailbox empty.
Definition: mx.c:1250
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:43
#define MUTT_MAILBOX_CHECK_IMMEDIATE
Don't postpone the actual checking.
Definition: mxapi.h:56
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mxapi.h:40
#define MUTT_MAILBOX_CHECK_FORCE
Ignore MailboxTime and check for new mail.
Definition: mxapi.h:54
uint8_t CheckStatsFlags
Flags for mutt_mailbox_check.
Definition: mxapi.h:52
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the main NeoMutt object.
Definition: neomutt.c:47
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition: neomutt.c:83
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition: neomutt.h:60
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:557
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1062
@ NT_TIMEOUT
Timeout has occurred.
Definition: notify_type.h:56
@ 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:52
void buf_pool_cleanup(void)
Release the Buffer pool.
Definition: pool.c:67
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:483
void mutt_prex_cleanup(void)
Cleanup heap memory allocated by compiled regexes.
Definition: prex.c:336
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:327
#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_cleanup(void)
Free all the default Windows.
Definition: rootwin.c:202
void rootwin_new(void)
Create the default Windows.
Definition: rootwin.c:214
void mutt_sasl_cleanup(void)
Invoke when processing is complete.
Definition: sasl.c:786
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:300
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
RFC2047 encode the content-descriptions.
Definition: send.c:1575
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:2120
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:47
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:51
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:52
uint32_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:40
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:46
#define SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
Definition: send.h:57
#define SEND_CLI_CRYPTO
Enable message security in modes that by default don't enable it.
Definition: send.h:58
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:41
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:606
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:779
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:39
Container for lots of config items.
Definition: set.h:252
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
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
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
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:127
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct Notify * notify_resize
Window resize notifications handler.
Definition: neomutt.h:43
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:46
mode_t user_default_umask
User's default file writing permissions (inferred from umask)
Definition: neomutt.h:48
struct Notify * notify
Notifications handler.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
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_cleanup(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:297
bool TsSupported
Terminal Setting is supported.
Definition: terminal.c:42
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition: terminal.c:72
#define buf_mktemp(buf)
Definition: tmp.h:33
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:226
@ U_MAILTO
Url is mailto://.
Definition: url.h:45
bool print_copyright(void)
Print copyright message.
Definition: version.c:525
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:393

Variable Documentation

◆ StartupComplete

bool StartupComplete = false

When the config has been read.

Definition at line 191 of file main.c.