NeoMutt  2024-03-23-23-gec7045
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.
 
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:93
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:

◆ mutt_exit()

void mutt_exit ( int  code)

Leave NeoMutt NOW.

Parameters
codeValue to return to the calling environment

Definition at line 231 of file main.c.

232{
233 mutt_endwin();
234#ifdef USE_DEBUG_BACKTRACE
235 if (code != 0)
237#endif
238 exit(code);
239}
void show_backtrace(void)
Log the program's call stack.
Definition: backtrace.c:39
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:153
+ 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 245 of file main.c.

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

324{
325 km_init(); /* must come before mutt_init */
326
327 /* should come before initscr() so that ncurses 4.2 doesn't try to install
328 * its own SIGWINCH handler */
330
331 if (!initscr())
332 {
333 mutt_error(_("Error initializing terminal"));
334 return 1;
335 }
338 keypad(stdscr, true);
339 cbreak();
340 noecho();
341 nonl();
342 typeahead(-1); /* simulate smooth scrolling */
343 meta(stdscr, true);
345 /* Now that curses is set up, we drop back to normal screen mode.
346 * This simplifies displaying error messages to the user.
347 * The first call to refresh() will swap us back to curses screen mode. */
348 endwin();
349 return 0;
350}
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 355 of file main.c.

356{
357 setlocale(LC_ALL, "");
358
359#ifdef ENABLE_NLS
360 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
361 if (domdir)
362 bindtextdomain(PACKAGE, domdir);
363 else
364 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
365 textdomain(PACKAGE);
366#endif
367#ifndef LOCALES_HACK
368 /* Do we have a locale definition? */
369 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
370 {
371 OptLocales = true;
372 }
373#endif
374}
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:775
+ 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 383 of file main.c.

384{
385 const char *shell = mutt_str_getenv("SHELL");
386 if (shell)
387 cs_str_initial_set(cs, "shell", shell, NULL);
388
389 /* Get some information about the user */
390 struct passwd *pw = getpwuid(getuid());
391 if (pw)
392 {
393 if (!Username)
394 Username = mutt_str_dup(pw->pw_name);
395 if (!HomeDir)
396 HomeDir = mutt_str_dup(pw->pw_dir);
397 if (!shell)
398 cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
399 }
400
401 if (!Username)
402 {
403 mutt_error(_("unable to determine username"));
404 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
405 }
406
407 if (!HomeDir)
408 {
409 mutt_error(_("unable to determine home directory"));
410 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
411 }
412
413 cs_str_reset(cs, "shell", NULL);
414 return true;
415}
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:253
+ 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 424 of file main.c.

425{
426 const char *header = ""; // Do not merge these two lines
427 header = _(header); // otherwise the .po files will end up badly ordered
428 const char *label = "Language:"; // the start of the lookup/needle
429 const char *lang = mutt_istr_find(header, label);
430 int len = 64;
431 if (lang)
432 {
433 lang += strlen(label); // skip label
434 SKIPWS(lang);
435 char *nl = strchr(lang, '\n');
436 if (nl)
437 len = (nl - lang);
438 }
439 else
440 {
441 lang = "NONE";
442 }
443
444 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
445}
#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:570
#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 450 of file main.c.

451{
452 const char *term = mutt_str_getenv("TERM");
453 const char *color_term = mutt_str_getenv("COLORTERM");
454 bool true_color = false;
455#ifdef NEOMUTT_DIRECT_COLORS
456 true_color = true;
457#endif
458
459 mutt_debug(LL_DEBUG1, "GUI:\n");
460 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
461 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
462 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
463 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
464 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
465 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
466 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
468}
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 514 of file main.c.

517{
518 char *subject = NULL;
519 char *include_file = NULL;
520 char *draft_file = NULL;
521 char *new_type = NULL;
522 char *dlevel = NULL;
523 char *dfile = NULL;
524 const char *cli_nntp = NULL;
525 struct Email *e = NULL;
526 struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
527 struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
528 struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
529 struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
530 struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
531 struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
532 SendFlags sendflags = SEND_NO_FLAGS;
534 int version = 0;
535 int i;
536 bool explicit_folder = false;
537 bool dump_variables = false;
538 bool one_liner = false;
539 bool hide_sensitive = false;
540 bool batch_mode = false;
541 bool edit_infile = false;
542 int double_dash = argc, nargc = 1;
543 int rc = 1;
544 bool repeat_error = false;
545 struct Buffer folder = buf_make(0);
546 struct Buffer expanded_infile = buf_make(0);
547 struct Buffer tempfile = buf_make(0);
548 struct ConfigSet *cs = NULL;
549
551
552 /* sanity check against stupid administrators */
553 if (getegid() != getgid())
554 {
555 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
556 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
557 }
558
559 init_locale();
560
561 umask(077);
562
563 EnvList = envlist_init(envp);
564 for (optind = 1; optind < double_dash;)
565 {
566 /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
567 * encounters a non-option. That could be a file to attach
568 * (all non-options between -a and --) or it could be an address
569 * (which gets collapsed to the front of argv). */
570 for (; optind < argc; optind++)
571 {
572 if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
573 {
574 if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
575 double_dash = optind; /* quit outer loop after getopt */
576 break; /* drop through to getopt */
577 }
578
579 /* non-option, either an attachment or address */
580 if (!STAILQ_EMPTY(&attach))
581 mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
582 else
583 argv[nargc++] = argv[optind];
584 }
585
586 i = getopt(argc, argv, "+A:a:Bb:F:f:Cc:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvxyzZ");
587 if (i != EOF)
588 {
589 switch (i)
590 {
591 case 'A':
592 mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
593 break;
594 case 'a':
595 mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
596 break;
597 case 'B':
598 batch_mode = true;
599 break;
600 case 'b':
601 mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
602 break;
603 case 'C':
604 sendflags |= SEND_CLI_CRYPTO;
605 break;
606 case 'c':
607 mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
608 break;
609 case 'D':
610 dump_variables = true;
611 break;
612 case 'd':
613 dlevel = optarg;
614 break;
615 case 'E':
616 edit_infile = true;
617 break;
618 case 'e':
619 mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
620 break;
621 case 'F':
623 break;
624 case 'f':
625 buf_strcpy(&folder, optarg);
626 explicit_folder = true;
627 break;
628 case 'g': /* Specify a news server */
629 cli_nntp = optarg;
631
632 case 'G': /* List of newsgroups */
634 break;
635 case 'H':
636 draft_file = optarg;
637 break;
638 case 'i':
639 include_file = optarg;
640 break;
641 case 'l':
642 dfile = optarg;
643 break;
644 case 'm':
645 new_type = optarg;
646 break;
647 case 'n':
648 flags |= MUTT_CLI_NOSYSRC;
649 break;
650 case 'O':
651 one_liner = true;
652 break;
653 case 'p':
654 sendflags |= SEND_POSTPONED;
655 break;
656 case 'Q':
657 mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
658 break;
659 case 'R':
660 flags |= MUTT_CLI_RO; /* read-only mode */
661 break;
662 case 'S':
663 hide_sensitive = true;
664 break;
665 case 's':
666 subject = optarg;
667 break;
668 case 'v':
669 version++;
670 break;
671 case 'y': /* My special hack mode */
672 flags |= MUTT_CLI_SELECT;
673 break;
674 case 'Z':
676 break;
677 case 'z':
678 flags |= MUTT_CLI_IGNORE;
679 break;
680 default:
681 OptNoCurses = true;
682 if (usage())
683 goto main_ok; // TEST03: neomutt -9
684 else
685 goto main_curses;
686 }
687 }
688 }
689
690 /* collapse remaining argv */
691 while (optind < argc)
692 argv[nargc++] = argv[optind++];
693 optind = 1;
694 argc = nargc;
695
696 if (version > 0)
697 {
699 bool done;
700 if (version == 1)
701 done = print_version(stdout);
702 else
703 done = print_copyright();
704 OptNoCurses = true;
705 if (done)
706 goto main_ok; // TEST04: neomutt -v
707 else
708 goto main_curses;
709 }
710
713
714 cs = cs_new(500);
715 if (!cs)
716 goto main_curses;
717
718 NeoMutt = neomutt_new(cs);
719 init_config(cs);
720 subjrx_init();
721 attach_init();
723
724#ifdef USE_DEBUG_NOTIFY
726#endif
727
728 if (!get_user_info(cs))
729 goto main_exit;
730
731 reset_tilde(cs);
732
733 if (dfile)
734 {
735 cs_str_initial_set(cs, "debug_file", dfile, NULL);
736 cs_str_reset(cs, "debug_file", NULL);
737 }
738
739 if (dlevel)
740 {
741 short num = 0;
742 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
743 {
744 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
745 goto main_exit; // TEST07: neomutt -d xyz
746 }
747 cs_str_initial_set(cs, "debug_level", dlevel, NULL);
748 cs_str_reset(cs, "debug_level", NULL);
749 }
750
754
755 if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
756 {
757 e = email_new();
758 e->env = mutt_env_new();
759
760 struct ListNode *np = NULL;
761 STAILQ_FOREACH(np, &bcc_list, entries)
762 {
763 mutt_addrlist_parse(&e->env->bcc, np->data);
764 }
765
766 STAILQ_FOREACH(np, &cc_list, entries)
767 {
768 mutt_addrlist_parse(&e->env->cc, np->data);
769 }
770
771 mutt_list_free(&bcc_list);
772 mutt_list_free(&cc_list);
773 }
774
775 /* Check for a batch send. */
776 if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
777 dump_variables || batch_mode)
778 {
779 OptNoCurses = true;
780 sendflags |= SEND_BATCH;
783 }
784
785 /* Check to make sure stdout is available in curses mode. */
786 if (!OptNoCurses && !isatty(1))
787 goto main_curses;
788
789 /* This must come before mutt_init() because curses needs to be started
790 * before calling the init_pair() function to set the color scheme. */
791 if (!OptNoCurses)
792 {
793 int crc = start_curses();
794 if (crc != 0)
795 goto main_curses; // TEST08: can't test -- fake term?
796 }
797
798 /* Always create the mutt_windows because batch mode has some shared code
799 * paths that end up referencing them. */
800 rootwin_new();
801
802 if (!OptNoCurses)
803 {
804 /* check whether terminal status is supported (must follow curses init) */
807 log_gui();
808 }
809
810 /* set defaults and read init files */
811 int rc2 = mutt_init(cs, dlevel, dfile, flags & MUTT_CLI_NOSYSRC, &commands);
812 if (rc2 != 0)
813 goto main_curses;
814
816
817 /* "$news_server" precedence: command line, config file, environment, system file */
818 if (!cli_nntp)
819 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
820
821 if (!cli_nntp)
822 cli_nntp = mutt_str_getenv("NNTPSERVER");
823
824 if (!cli_nntp)
825 {
826 char buf[1024] = { 0 };
827 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
828 }
829
830 if (cli_nntp)
831 {
832 cs_str_initial_set(cs, "news_server", cli_nntp, NULL);
833 cs_str_reset(cs, "news_server", NULL);
834 }
835
836 /* Initialize crypto backends. */
837 crypt_init();
838
839 if (new_type)
840 {
841 struct Buffer err = buf_make(0);
842 int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
843 if (CSR_RESULT(r) != CSR_SUCCESS)
844 {
845 mutt_error("%s", err.data);
846 buf_dealloc(&err);
847 goto main_curses;
848 }
849 cs_str_reset(cs, "mbox_type", NULL);
850 }
851
852 if (!STAILQ_EMPTY(&queries))
853 {
854 rc = mutt_query_variables(&queries, one_liner);
855 goto main_curses;
856 }
857
858 if (dump_variables)
859 {
861 if (hide_sensitive)
862 cdflags |= CS_DUMP_HIDE_SENSITIVE;
863 if (one_liner)
864 cdflags |= CS_DUMP_SHOW_DOCS;
865 dump_config(cs, cdflags, stdout);
866 goto main_ok; // TEST18: neomutt -D
867 }
868
869 if (!STAILQ_EMPTY(&alias_queries))
870 {
871 rc = 0;
872 for (; optind < argc; optind++)
873 mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
874 struct ListNode *np = NULL;
875 STAILQ_FOREACH(np, &alias_queries, entries)
876 {
877 struct AddressList *al = alias_lookup(np->data);
878 if (al)
879 {
880 /* output in machine-readable form */
881 mutt_addrlist_to_intl(al, NULL);
882 struct Buffer *buf = buf_pool_get();
883 mutt_addrlist_write(al, buf, false);
884 printf("%s\n", buf_string(buf));
885 buf_pool_release(&buf);
886 }
887 else
888 {
889 rc = 1;
890 printf("%s\n", np->data); // TEST19: neomutt -A unknown
891 }
892 }
893 mutt_list_free(&alias_queries);
894 goto main_curses; // TEST20: neomutt -A alias
895 }
896
897 if (!OptNoCurses)
898 {
900 clear();
904 }
905
906#ifdef USE_AUTOCRYPT
907 /* Initialize autocrypt after curses messages are working,
908 * because of the initial account setup screens. */
909 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
910 if (c_autocrypt)
911 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
912#endif
913
914 /* Create the `$folder` directory if it doesn't exist. */
915 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
916 if (!OptNoCurses && c_folder)
917 {
918 struct stat st = { 0 };
919 struct Buffer *fpath = buf_pool_get();
920
921 buf_strcpy(fpath, c_folder);
922 buf_expand_path(fpath);
923 bool skip = false;
924 /* we're not connected yet - skip mail folder creation */
925 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
926 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
927 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
928 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
929 {
930 char msg2[256] = { 0 };
931 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
932 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
933 {
934 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
935 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
936 }
937 }
938 buf_pool_release(&fpath);
939 }
940
941 if (batch_mode)
942 {
943 goto main_ok; // TEST22: neomutt -B
944 }
945 StartupComplete = true;
946
951
952 if (sendflags & SEND_POSTPONED)
953 {
954 if (!OptNoCurses)
956 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
957 rc = 0;
958 // TEST23: neomutt -p (postponed message, cancel)
959 // TEST24: neomutt -p (no postponed message)
961 repeat_error = true;
962 goto main_curses;
963 }
964 else if (subject || e || draft_file || include_file ||
965 !STAILQ_EMPTY(&attach) || (optind < argc))
966 {
967 FILE *fp_in = NULL;
968 FILE *fp_out = NULL;
969 char *infile = NULL;
970 char *bodytext = NULL;
971 const char *bodyfile = NULL;
972 int rv = 0;
973
974 if (!OptNoCurses)
976
977 if (!e)
978 e = email_new();
979 if (!e->env)
980 e->env = mutt_env_new();
981
982 for (i = optind; i < argc; i++)
983 {
984 if (url_check_scheme(argv[i]) == U_MAILTO)
985 {
986 if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
987 {
988 mutt_error(_("Failed to parse mailto: link"));
989 email_free(&e);
990 goto main_curses; // TEST25: neomutt mailto:?
991 }
992 }
993 else
994 {
995 mutt_addrlist_parse(&e->env->to, argv[i]);
996 }
997 }
998
999 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1000 if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
1001 TAILQ_EMPTY(&e->env->cc))
1002 {
1003 mutt_error(_("No recipients specified"));
1004 email_free(&e);
1005 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1006 }
1007
1008 if (subject)
1009 {
1010 mutt_env_set_subject(e->env, subject);
1011 }
1012
1013 if (draft_file)
1014 {
1015 infile = draft_file;
1016 include_file = NULL;
1017 }
1018 else if (include_file)
1019 {
1020 infile = include_file;
1021 }
1022 else
1023 {
1024 edit_infile = false;
1025 }
1026
1027 if (infile || bodytext)
1028 {
1029 /* Prepare fp_in and expanded_infile. */
1030 if (infile)
1031 {
1032 if (mutt_str_equal("-", infile))
1033 {
1034 if (edit_infile)
1035 {
1036 mutt_error(_("Can't use -E flag with stdin"));
1037 email_free(&e);
1038 goto main_curses; // TEST27: neomutt -E -H -
1039 }
1040 fp_in = stdin;
1041 }
1042 else
1043 {
1044 buf_strcpy(&expanded_infile, infile);
1045 buf_expand_path(&expanded_infile);
1046 fp_in = mutt_file_fopen(buf_string(&expanded_infile), "r");
1047 if (!fp_in)
1048 {
1049 mutt_perror("%s", buf_string(&expanded_infile));
1050 email_free(&e);
1051 goto main_curses; // TEST28: neomutt -E -H missing
1052 }
1053 }
1054 }
1055
1056 if (edit_infile)
1057 {
1058 /* If editing the infile, keep it around afterwards so
1059 * it doesn't get unlinked, and we can rebuild the draft_file */
1060 sendflags |= SEND_NO_FREE_HEADER;
1061 }
1062 else
1063 {
1064 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1065 * Note: stdin is always copied to a tempfile, ensuring draft_file
1066 * can stat and get the correct st_size below. */
1067 buf_mktemp(&tempfile);
1068
1069 fp_out = mutt_file_fopen(buf_string(&tempfile), "w");
1070 if (!fp_out)
1071 {
1072 mutt_file_fclose(&fp_in);
1073 mutt_perror("%s", buf_string(&tempfile));
1074 email_free(&e);
1075 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1076 }
1077 if (fp_in)
1078 {
1079 mutt_file_copy_stream(fp_in, fp_out);
1080 if (fp_in == stdin)
1081 sendflags |= SEND_CONSUMED_STDIN;
1082 else
1083 mutt_file_fclose(&fp_in);
1084 }
1085 else if (bodytext)
1086 {
1087 fputs(bodytext, fp_out);
1088 }
1089 mutt_file_fclose(&fp_out);
1090
1091 fp_in = mutt_file_fopen(buf_string(&tempfile), "r");
1092 if (!fp_in)
1093 {
1094 mutt_perror("%s", buf_string(&tempfile));
1095 email_free(&e);
1096 goto main_curses; // TEST30: can't test
1097 }
1098 }
1099
1100 /* Parse the draft_file into the full Email/Body structure.
1101 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1102 * our e->body. */
1103 if (draft_file)
1104 {
1105 struct Envelope *opts_env = e->env;
1106 struct stat st = { 0 };
1107
1108 sendflags |= SEND_DRAFT_FILE;
1109
1110 /* Set up a tmp Email with just enough information so that
1111 * mutt_prepare_template() can parse the message in fp_in. */
1112 struct Email *e_tmp = email_new();
1113 e_tmp->offset = 0;
1114 e_tmp->body = mutt_body_new();
1115 if (fstat(fileno(fp_in), &st) != 0)
1116 {
1117 mutt_perror("%s", draft_file);
1118 email_free(&e);
1119 email_free(&e_tmp);
1120 goto main_curses; // TEST31: can't test
1121 }
1122 e_tmp->body->length = st.st_size;
1123
1124 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1125 {
1126 mutt_error(_("Can't parse message template: %s"), draft_file);
1127 email_free(&e);
1128 email_free(&e_tmp);
1129 goto main_curses;
1130 }
1131
1132 /* Scan for neomutt header to set `$resume_draft_files` */
1133 struct ListNode *np = NULL, *tmp = NULL;
1134 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1135 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1136 {
1137 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1138 {
1139 if (c_resume_edited_draft_files)
1140 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1141
1142 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1143 FREE(&np->data);
1144 FREE(&np);
1145 }
1146 }
1147
1148 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1149 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1150 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1151 if (opts_env->subject)
1152 mutt_env_set_subject(e->env, opts_env->subject);
1153
1154 mutt_env_free(&opts_env);
1155 email_free(&e_tmp);
1156 }
1157 /* Editing the include_file: pass it directly in.
1158 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1159 else if (edit_infile)
1160 bodyfile = buf_string(&expanded_infile);
1161 // For bodytext and unedited include_file: use the tempfile.
1162 else
1163 bodyfile = buf_string(&tempfile);
1164
1165 mutt_file_fclose(&fp_in);
1166 }
1167
1168 FREE(&bodytext);
1169
1170 if (!STAILQ_EMPTY(&attach))
1171 {
1172 struct Body *b = e->body;
1173
1174 while (b && b->next)
1175 b = b->next;
1176
1177 struct ListNode *np = NULL;
1178 STAILQ_FOREACH(np, &attach, entries)
1179 {
1180 if (b)
1181 {
1183 b = b->next;
1184 }
1185 else
1186 {
1188 e->body = b;
1189 }
1190 if (!b)
1191 {
1192 mutt_error(_("%s: unable to attach file"), np->data);
1193 mutt_list_free(&attach);
1194 email_free(&e);
1195 goto main_curses; // TEST32: neomutt john@example.com -a missing
1196 }
1197 }
1198 mutt_list_free(&attach);
1199 }
1200
1201 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1202 /* We WANT the "Mail sent." and any possible, later error */
1204 if (ErrorBufMessage)
1205 mutt_message("%s", ErrorBuf);
1206
1207 if (edit_infile)
1208 {
1209 if (draft_file)
1210 {
1211 if (truncate(buf_string(&expanded_infile), 0) == -1)
1212 {
1213 mutt_perror("%s", buf_string(&expanded_infile));
1214 email_free(&e);
1215 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1216 }
1217 fp_out = mutt_file_fopen(buf_string(&expanded_infile), "a");
1218 if (!fp_out)
1219 {
1220 mutt_perror("%s", buf_string(&expanded_infile));
1221 email_free(&e);
1222 goto main_curses; // TEST34: can't test
1223 }
1224
1225 /* If the message was sent or postponed, these will already
1226 * have been done. */
1227 if (rv < 0)
1228 {
1229 if (e->body->next)
1230 e->body = mutt_make_multipart(e->body);
1232 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1233 mutt_env_to_intl(e->env, NULL, NULL);
1234 }
1235
1236 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1238 c_crypt_protected_headers_read &&
1240 NeoMutt->sub);
1241 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1242 if (c_resume_edited_draft_files)
1243 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1244 fputc('\n', fp_out);
1245 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1246 {
1247 mutt_file_fclose(&fp_out);
1248 email_free(&e);
1249 goto main_curses; // TEST35: can't test
1250 }
1251 mutt_file_fclose(&fp_out);
1252 }
1253
1254 email_free(&e);
1255 }
1256
1257 /* !edit_infile && draft_file will leave the tempfile around */
1258 if (!buf_is_empty(&tempfile))
1259 unlink(buf_string(&tempfile));
1260
1262
1263 if (rv != 0)
1264 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1265 }
1266 else if (sendflags & SEND_BATCH)
1267 {
1268 /* This guards against invoking `neomutt < /dev/null` and accidentally
1269 * sending an email due to a my_hdr or other setting. */
1270 mutt_error(_("No recipients specified"));
1271 goto main_curses;
1272 }
1273 else
1274 {
1275 if (flags & MUTT_CLI_MAILBOX)
1276 {
1277 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1278 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1280 if (mutt_mailbox_check(NULL, csflags) == 0)
1281 {
1282 mutt_message(_("No mailbox with new mail"));
1283 goto main_curses; // TEST37: neomutt -Z (no new mail)
1284 }
1285 buf_reset(&folder);
1286 mutt_mailbox_next(NULL, &folder);
1287 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1288 }
1289 else if (flags & MUTT_CLI_SELECT)
1290 {
1291 if (flags & MUTT_CLI_NEWS)
1292 {
1293 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1294 OptNews = true;
1295 struct Mailbox *m_cur = get_current_mailbox();
1296 CurrentNewsSrv = nntp_select_server(m_cur, c_news_server, false);
1297 if (!CurrentNewsSrv)
1298 goto main_curses; // TEST38: neomutt -G (unset news_server)
1299 }
1300 else if (TAILQ_EMPTY(&NeoMutt->accounts))
1301 {
1302 mutt_error(_("No incoming mailboxes defined"));
1303 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1304 }
1305 buf_reset(&folder);
1306 struct Mailbox *m_cur = get_current_mailbox();
1307 dlg_browser(&folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, m_cur, NULL, NULL);
1308 if (buf_is_empty(&folder))
1309 {
1310 goto main_ok; // TEST40: neomutt -y (quit selection)
1311 }
1312 }
1313
1314 if (buf_is_empty(&folder))
1315 {
1316 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1317 if (c_spool_file)
1318 {
1319 // Check if `$spool_file` corresponds a mailboxes' description.
1320 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1321 if (m_desc)
1322 buf_strcpy(&folder, m_desc->realpath);
1323 else
1324 buf_strcpy(&folder, c_spool_file);
1325 }
1326 else if (c_folder)
1327 {
1328 buf_strcpy(&folder, c_folder);
1329 }
1330 /* else no folder */
1331 }
1332
1333 if (OptNews)
1334 {
1335 OptNews = false;
1336 buf_alloc(&folder, PATH_MAX);
1338 }
1339 else
1340 {
1341 buf_expand_path(&folder);
1342 }
1343
1346
1347 if (flags & MUTT_CLI_IGNORE)
1348 {
1349 /* check to see if there are any messages in the folder */
1350 switch (mx_path_is_empty(&folder))
1351 {
1352 case -1:
1353 mutt_perror("%s", buf_string(&folder));
1354 goto main_curses; // TEST41: neomutt -z -f missing
1355 case 1:
1356 mutt_error(_("Mailbox is empty"));
1357 goto main_curses; // TEST42: neomutt -z -f /dev/null
1358 }
1359 }
1360
1361 struct Mailbox *m_cur = mailbox_find(buf_string(&folder));
1362 mutt_folder_hook(buf_string(&folder), m_cur ? m_cur->name : NULL);
1364 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1366
1368 window_redraw(NULL);
1369
1370 repeat_error = true;
1371 struct Mailbox *m = mx_resolve(buf_string(&folder));
1372 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1373 if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1374 {
1375 if (m->account)
1377
1378 mailbox_free(&m);
1379 mutt_error(_("Unable to open mailbox %s"), buf_string(&folder));
1380 repeat_error = false;
1381 }
1382 if (m || !explicit_folder)
1383 {
1384 struct MuttWindow *dlg = index_pager_init();
1385 dialog_push(dlg);
1386
1388 m = dlg_index(dlg, m);
1390 mailbox_free(&m);
1391
1392 dialog_pop();
1393 mutt_window_free(&dlg);
1395 repeat_error = false;
1396 }
1398#ifdef USE_SASL_CYRUS
1400#endif
1401#ifdef USE_SASL_GNU
1403#endif
1404#ifdef USE_AUTOCRYPT
1406#endif
1407 // TEST43: neomutt (no change to mailbox)
1408 // TEST44: neomutt (change mailbox)
1409 }
1410
1411main_ok:
1412 rc = 0;
1413main_curses:
1414 mutt_endwin();
1416 /* Repeat the last message to the user */
1417 if (repeat_error && ErrorBufMessage)
1418 puts(ErrorBuf);
1419main_exit:
1420 if (NeoMutt && NeoMutt->sub)
1421 {
1426 }
1427 mutt_list_free(&commands);
1429 buf_dealloc(&folder);
1430 buf_dealloc(&expanded_infile);
1431 buf_dealloc(&tempfile);
1432 mutt_list_free(&queries);
1439 menu_cleanup();
1440 crypt_cleanup();
1450 cs_free(&cs);
1452 mutt_log_stop();
1453 return rc;
1454}
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:1210
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:1297
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
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
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:394
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:75
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:354
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
@ 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:1406
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:1682
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:282
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition: file.c:1447
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
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:2738
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:2342
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:696
int main_timeout_observer(struct NotifyCallback *nc)
Notification that a timeout has occurred - Implements observer_t -.
Definition: main.c:473
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:555
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:715
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:1035
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_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:355
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:424
#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:450
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:208
static bool usage(void)
Display NeoMutt command line.
Definition: main.c:245
static int start_curses(void)
Start the Curses UI.
Definition: main.c:323
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:383
#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:71
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:1177
#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:709
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:242
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
#define PATH_MAX
Definition: mutt.h:42
void mutt_temp_attachments_cleanup(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1307
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:359
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:45
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition: neomutt.c:81
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition: neomutt.h:59
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:567
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:1070
@ 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
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:56
#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:518
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.