NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
main.c File Reference

Command line processing. More...

#include "config.h"
#include <errno.h>
#include <getopt.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 "index/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "alternates.h"
#include "attachments.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "hook.h"
#include "init.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_globals.h"
#include "mutt_history.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "myvar.h"
#include "options.h"
#include "protos.h"
#include "subjectrx.h"
#include "version.h"
#include <libintl.h>
#include "imap/lib.h"
#include "pop/lib.h"
#include "nntp/lib.h"
#include "nntp/adata.h"
#include "nntp/mdata.h"
#include "autocrypt/lib.h"

Go to the source code of this file.

Macros

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

Typedefs

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

Functions

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

Detailed Description

Command line processing.

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

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

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

Definition in file main.c.

Macro Definition Documentation

◆ MAIN_C

#define MAIN_C   1

Definition at line 169 of file main.c.

◆ GNULIB_defined_setlocale

#define GNULIB_defined_setlocale

Definition at line 170 of file main.c.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 241 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

Definition at line 242 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 243 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 244 of file main.c.

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 245 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

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

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 240 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 256 of file main.c.

257 {
258  static const char *names[] = { "folder", "mbox", "postponed", "record" };
259 
260  struct Buffer value = mutt_buffer_make(256);
261  for (size_t i = 0; i < mutt_array_size(names); i++)
262  {
263  struct HashElem *he = cs_get_elem(cs, names[i]);
264  if (!he)
265  continue;
266  mutt_buffer_reset(&value);
267  cs_he_initial_get(cs, he, &value);
268  mutt_buffer_expand_path_regex(&value, false);
269  cs_he_initial_set(cs, he, value.data, NULL);
270  cs_he_reset(cs, he, NULL);
271  }
272  mutt_buffer_dealloc(&value);
273 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:134
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:346
#define mutt_array_size(x)
Definition: memory.h:33
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:416
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
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:484
char * data
Pointer to data.
Definition: buffer.h:35
The item stored in a Hash Table.
Definition: hash.h:43
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:204
+ 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 279 of file main.c.

280 {
281  mutt_endwin();
282 #ifdef HAVE_LIBUNWIND
283  if (code != 0)
284  show_backtrace();
285 #endif
286  exit(code);
287 }
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
void show_backtrace(void)
Log the program&#39;s call stack.
Definition: backtrace.c:39
+ Here is the caller graph for this function:

◆ usage()

static void usage ( void  )
static

Display NeoMutt command line.

Definition at line 293 of file main.c.

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

Return values
0Success
1Failure

Definition at line 366 of file main.c.

367 {
368  km_init(); /* must come before mutt_init */
369 
370 #ifdef USE_SLANG_CURSES
371  SLtt_Ignore_Beep = 1; /* don't do that #*$@^! annoying visual beep! */
372  SLsmg_Display_Eight_Bit = 128; /* characters above this are printable */
373  SLtt_set_color(0, NULL, "default", "default");
374 #if (SLANG_VERSION >= 20000)
375  SLutf8_enable(-1);
376 #endif
377 #else
378  /* should come before initscr() so that ncurses 4.2 doesn't try to install
379  * its own SIGWINCH handler */
381 #endif
382  if (!initscr())
383  {
384  mutt_error(_("Error initializing terminal"));
385  return 1;
386  }
387  /* slang requires the signal handlers to be set after initializing */
390  keypad(stdscr, true);
391  cbreak();
392  noecho();
393  nonl();
394 #ifdef HAVE_TYPEAHEAD
395  typeahead(-1); /* simulate smooth scrolling */
396 #endif
397 #ifdef HAVE_META
398  meta(stdscr, true);
399 #endif
401  /* Now that curses is set up, we drop back to normal screen mode.
402  * This simplifies displaying error messages to the user.
403  * The first call to refresh() will swap us back to curses screen mode. */
404  endwin();
405  return 0;
406 }
void mutt_colors_init(void)
Initialize colours.
Definition: color.c:393
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
void km_init(void)
Initialise all the menu keybindings.
Definition: keymap.c:1017
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: keymap.c:988
void mutt_signal_init(void)
Initialise the signal handling.
Definition: mutt_signal.c:140
+ 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 411 of file main.c.

412 {
413  setlocale(LC_ALL, "");
414 
415 #ifdef ENABLE_NLS
416  const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
417  if (domdir)
418  bindtextdomain(PACKAGE, domdir);
419  else
420  bindtextdomain(PACKAGE, MUTTLOCALEDIR);
421  textdomain(PACKAGE);
422 #endif
423 #ifndef LOCALES_HACK
424  /* Do we have a locale definition? */
425  if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
426  {
427  OptLocales = true;
428  }
429 #endif
430 }
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
bool OptLocales
(pseudo) set if user has valid locale definition
Definition: mbyte.c:43
+ 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 439 of file main.c.

440 {
441  const char *shell = mutt_str_getenv("SHELL");
442  if (shell)
443  cs_str_initial_set(cs, "shell", shell, NULL);
444 
445  /* Get some information about the user */
446  struct passwd *pw = getpwuid(getuid());
447  if (pw)
448  {
449  if (!Username)
450  Username = mutt_str_dup(pw->pw_name);
451  if (!HomeDir)
452  HomeDir = mutt_str_dup(pw->pw_dir);
453  if (!shell)
454  cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
455  }
456 
457  if (!Username)
458  {
459  mutt_error(_("unable to determine username"));
460  return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
461  }
462 
463  if (!HomeDir)
464  {
465  mutt_error(_("unable to determine home directory"));
466  return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
467  }
468 
469  cs_str_reset(cs, "shell", NULL);
470  return true;
471 }
#define mutt_error(...)
Definition: logging.h:88
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
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:458
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:393
+ 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 480 of file main.c.

481 {
482  const char *header = ""; // Do not merge these two lines
483  header = _(header); // otherwise the .po files will end up badly ordered
484  const char *lang = strcasestr(header, "Language:");
485  int len = 64;
486  if (lang)
487  {
488  lang += 9; // skip label
489  SKIPWS(lang);
490  char *nl = strchr(lang, '\n');
491  if (nl)
492  len = (nl - lang);
493  }
494  else
495  {
496  lang = "NONE";
497  }
498 
499  mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
500 }
#define _(a)
Definition: message.h:28
#define SKIPWS(ch)
Definition: string2.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
+ 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 510 of file main.c.

511 {
512  char *subject = NULL;
513  char *include_file = NULL;
514  char *draft_file = NULL;
515  char *new_type = NULL;
516  char *dlevel = NULL;
517  char *dfile = NULL;
518 #ifdef USE_NNTP
519  const char *cli_nntp = NULL;
520 #endif
521  struct Email *e = NULL;
522  struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
523  struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
524  struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
525  struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
526  struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
527  struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
528  SendFlags sendflags = SEND_NO_FLAGS;
529  CliFlags flags = MUTT_CLI_NO_FLAGS;
530  int version = 0;
531  int i;
532  bool explicit_folder = false;
533  bool dump_variables = false;
534  bool one_liner = false;
535  bool hide_sensitive = false;
536  bool batch_mode = false;
537  bool edit_infile = false;
538 #ifdef USE_DEBUG_PARSE_TEST
539  bool test_config = false;
540 #endif
541  int double_dash = argc, nargc = 1;
542  int rc = 1;
543  bool repeat_error = false;
544  struct Buffer folder = mutt_buffer_make(0);
545  struct Buffer expanded_infile = mutt_buffer_make(0);
546  struct Buffer tempfile = mutt_buffer_make(0);
547  struct ConfigSet *cs = NULL;
548 
550 
551  /* sanity check against stupid administrators */
552  if (getegid() != getgid())
553  {
554  mutt_error("%s: I don't want to run with privileges!", argv[0]);
555  goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
556  }
557 
558  init_locale();
559 
560  umask(077);
561 
562  mutt_envlist_init(envp);
563  for (optind = 1; optind < double_dash;)
564  {
565  /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
566  * encounters a non-option. That could be a file to attach
567  * (all non-options between -a and --) or it could be an address
568  * (which gets collapsed to the front of argv). */
569  for (; optind < argc; optind++)
570  {
571  if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
572  {
573  if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
574  double_dash = optind; /* quit outer loop after getopt */
575  break; /* drop through to getopt */
576  }
577 
578  /* non-option, either an attachment or address */
579  if (!STAILQ_EMPTY(&attach))
580  mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
581  else
582  argv[nargc++] = argv[optind];
583  }
584 
585  /* USE_NNTP 'g:G' */
586  i = getopt(argc, argv, "+A:a:Bb:F:f:c: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  mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
605  break;
606  case 'D':
607  dump_variables = true;
608  break;
609  case 'd':
610  dlevel = optarg;
611  break;
612  case 'E':
613  edit_infile = true;
614  break;
615  case 'e':
616  mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
617  break;
618  case 'F':
619  mutt_list_insert_tail(&Muttrc, mutt_str_dup(optarg));
620  break;
621  case 'f':
622  mutt_buffer_strcpy(&folder, optarg);
623  explicit_folder = true;
624  break;
625 #ifdef USE_NNTP
626  case 'g': /* Specify a news server */
627  cli_nntp = optarg;
628  /* fallthrough */
629  case 'G': /* List of newsgroups */
630  flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
631  break;
632 #endif
633  case 'H':
634  draft_file = optarg;
635  break;
636  case 'i':
637  include_file = optarg;
638  break;
639  case 'l':
640  dfile = optarg;
641  break;
642  case 'm':
643  new_type = optarg;
644  break;
645  case 'n':
646  flags |= MUTT_CLI_NOSYSRC;
647  break;
648  case 'O':
649  one_liner = true;
650  break;
651  case 'p':
652  sendflags |= SEND_POSTPONED;
653  break;
654  case 'Q':
655  mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
656  break;
657  case 'R':
658  flags |= MUTT_CLI_RO; /* read-only mode */
659  break;
660  case 'S':
661  hide_sensitive = true;
662  break;
663  case 's':
664  subject = optarg;
665  break;
666 #ifdef USE_DEBUG_PARSE_TEST
667  case 'T':
668  test_config = true;
669  break;
670 #endif
671  case 'v':
672  version++;
673  break;
674  case 'y': /* My special hack mode */
675  flags |= MUTT_CLI_SELECT;
676  break;
677  case 'Z':
679  break;
680  case 'z':
681  flags |= MUTT_CLI_IGNORE;
682  break;
683  default:
684  usage();
685  OptNoCurses = true;
686  goto main_ok; // TEST03: neomutt -9
687  }
688  }
689  }
690 
691  /* collapse remaining argv */
692  while (optind < argc)
693  argv[nargc++] = argv[optind++];
694  optind = 1;
695  argc = nargc;
696 
697  if (version > 0)
698  {
700  if (version == 1)
701  print_version(stdout);
702  else
703  print_copyright();
704  OptNoCurses = true;
705  goto main_ok; // TEST04: neomutt -v
706  }
707 
710 
711  cs = cs_new(500);
712  if (!cs)
713  goto main_curses;
714 
715  NeoMutt = neomutt_new(cs);
716  init_config(cs);
717  subjrx_init();
718  attach_init();
719  alternates_init();
720 
721 #ifdef USE_DEBUG_NOTIFY
723 #endif
724 
725  if (!get_user_info(cs))
726  goto main_exit;
727 
728 #ifdef USE_DEBUG_PARSE_TEST
729  if (test_config)
730  {
731  cs_str_initial_set(cs, "from", "rich@flatcap.org", NULL);
732  cs_str_reset(cs, "from", NULL);
733  myvar_set("my_var", "foo");
734  test_parse_set();
735  goto main_ok;
736  }
737 #endif
738 
739  reset_tilde(cs);
740 
741  if (dfile)
742  {
743  cs_str_initial_set(cs, "debug_file", dfile, NULL);
744  cs_str_reset(cs, "debug_file", NULL);
745  }
746 
747  if (dlevel)
748  {
749  short num = 0;
750  if ((mutt_str_atos(dlevel, &num) < 0) || (num < LL_MESSAGE) || (num >= LL_MAX))
751  {
752  mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
753  goto main_exit; // TEST07: neomutt -d xyz
754  }
755  cs_str_initial_set(cs, "debug_level", dlevel, NULL);
756  cs_str_reset(cs, "debug_level", NULL);
757  }
758 
759  mutt_log_prep();
760  if (dlevel)
761  mutt_log_start();
762 
764 
765  log_translation();
766 
767  if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
768  {
769  e = email_new();
770  e->env = mutt_env_new();
771 
772  struct ListNode *np = NULL;
773  STAILQ_FOREACH(np, &bcc_list, entries)
774  {
775  mutt_addrlist_parse(&e->env->bcc, np->data);
776  }
777 
778  STAILQ_FOREACH(np, &cc_list, entries)
779  {
780  mutt_addrlist_parse(&e->env->cc, np->data);
781  }
782 
783  mutt_list_free(&bcc_list);
784  mutt_list_free(&cc_list);
785  }
786 
787  /* Check for a batch send. */
788  if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
789  dump_variables || batch_mode)
790  {
791  OptNoCurses = true;
792  sendflags = SEND_BATCH;
795  }
796 
797  /* Always create the mutt_windows because batch mode has some shared code
798  * paths that end up referencing them. */
799  rootwin_new();
800 
801  /* This must come before mutt_init() because curses needs to be started
802  * before calling the init_pair() function to set the color scheme. */
803  if (!OptNoCurses)
804  {
805  int crc = start_curses();
806  if (crc != 0)
807  goto main_curses; // TEST08: can't test -- fake term?
808 
809  /* check whether terminal status is supported (must follow curses init) */
811  rootwin_set_size(COLS, LINES);
812  }
813 
814  /* set defaults and read init files */
815  int rc2 = mutt_init(cs, flags & MUTT_CLI_NOSYSRC, &commands);
816  mutt_list_free(&commands);
817  if (rc2 != 0)
818  goto main_curses;
819 
821 
822  /* The command line overrides the config */
823  if (dlevel)
824  cs_str_reset(cs, "debug_level", NULL);
825  if (dfile)
826  cs_str_reset(cs, "debug_file", NULL);
827 
828  if (mutt_log_start() < 0)
829  {
830  mutt_perror("log file");
831  goto main_exit;
832  }
833 
834 #ifdef USE_NNTP
835  {
836  /* "$news_server" precedence: command line, config file, environment, system file */
837  if (!cli_nntp)
838  cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
839 
840  if (!cli_nntp)
841  cli_nntp = mutt_str_getenv("NNTPSERVER");
842 
843  char buf[1024] = { 0 };
844  if (!cli_nntp)
845  cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
846 
847  if (cli_nntp)
848  {
849  cs_str_initial_set(cs, "news_server", cli_nntp, NULL);
850  cs_str_reset(cs, "news_server", NULL);
851  }
852  }
853 #endif
854 
855  /* Initialize crypto backends. */
856  crypt_init();
857 
858  if (new_type)
859  {
860  struct Buffer err = mutt_buffer_make(0);
861  int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
862  if (CSR_RESULT(r) != CSR_SUCCESS)
863  {
864  mutt_error(err.data);
865  mutt_buffer_dealloc(&err);
866  goto main_curses;
867  }
868  cs_str_reset(cs, "mbox_type", NULL);
869  }
870 
871  if (!STAILQ_EMPTY(&queries))
872  {
873  rc = mutt_query_variables(&queries, one_liner);
874  goto main_curses;
875  }
876 
877  if (dump_variables)
878  {
880  if (hide_sensitive)
881  cdflags |= CS_DUMP_HIDE_SENSITIVE;
882  if (one_liner)
883  cdflags |= CS_DUMP_SHOW_DOCS;
884  dump_config(cs, cdflags, stdout);
885  goto main_ok; // TEST18: neomutt -D
886  }
887 
888  if (!STAILQ_EMPTY(&alias_queries))
889  {
890  rc = 0;
891  for (; optind < argc; optind++)
892  mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
893  struct ListNode *np = NULL;
894  STAILQ_FOREACH(np, &alias_queries, entries)
895  {
896  struct AddressList *al = alias_lookup(np->data);
897  if (al)
898  {
899  /* output in machine-readable form */
900  mutt_addrlist_to_intl(al, NULL);
901  mutt_addrlist_write_file(al, stdout, 0, false);
902  }
903  else
904  {
905  rc = 1;
906  printf("%s\n", np->data); // TEST19: neomutt -A unknown
907  }
908  }
909  mutt_list_free(&alias_queries);
910  goto main_curses; // TEST20: neomutt -A alias
911  }
912 
913  if (!OptNoCurses)
914  {
916  clear();
920  }
921 
922 #ifdef USE_AUTOCRYPT
923  /* Initialize autocrypt after curses messages are working,
924  * because of the initial account setup screens. */
925  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
926  if (c_autocrypt)
927  mutt_autocrypt_init(NULL, !(sendflags & SEND_BATCH));
928 #endif
929 
930  /* Create the `$folder` directory if it doesn't exist. */
931  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
932  if (!OptNoCurses && c_folder)
933  {
934  struct stat sb;
935  struct Buffer *fpath = mutt_buffer_pool_get();
936 
937  mutt_buffer_strcpy(fpath, c_folder);
939  bool skip = false;
940 #ifdef USE_IMAP
941  /* we're not connected yet - skip mail folder creation */
942  skip |= (imap_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_IMAP);
943 #endif
944 #ifdef USE_POP
945  skip |= (pop_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_POP);
946 #endif
947 #ifdef USE_NNTP
948  skip |= (nntp_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_NNTP);
949 #endif
950  if (!skip && (stat(mutt_buffer_string(fpath), &sb) == -1) && (errno == ENOENT))
951  {
952  char msg2[256];
953  snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
954  if (mutt_yesorno(msg2, MUTT_YES) == MUTT_YES)
955  {
956  if ((mkdir(mutt_buffer_string(fpath), 0700) == -1) && (errno != EEXIST))
957  mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
958  }
959  }
960  mutt_buffer_pool_release(&fpath);
961  }
962 
963  if (batch_mode)
964  {
965  goto main_ok; // TEST22: neomutt -B
966  }
967 
971 
972  if (sendflags & SEND_POSTPONED)
973  {
974  if (!OptNoCurses)
975  mutt_flushinp();
976  if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
977  rc = 0;
978  // TEST23: neomutt -p (postponed message, cancel)
979  // TEST24: neomutt -p (no postponed message)
980  log_queue_empty();
981  repeat_error = true;
982  goto main_curses;
983  }
984  else if (subject || e || sendflags || draft_file || include_file ||
985  !STAILQ_EMPTY(&attach) || (optind < argc))
986  {
987  FILE *fp_in = NULL;
988  FILE *fp_out = NULL;
989  char *infile = NULL;
990  char *bodytext = NULL;
991  const char *bodyfile = NULL;
992  int rv = 0;
993 
994  if (!OptNoCurses)
995  mutt_flushinp();
996 
997  if (!e)
998  e = email_new();
999  if (!e->env)
1000  e->env = mutt_env_new();
1001 
1002  for (i = optind; i < argc; i++)
1003  {
1004  if (url_check_scheme(argv[i]) == U_MAILTO)
1005  {
1006  if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
1007  {
1008  mutt_error(_("Failed to parse mailto: link"));
1009  email_free(&e);
1010  goto main_curses; // TEST25: neomutt mailto:?
1011  }
1012  }
1013  else
1014  mutt_addrlist_parse(&e->env->to, argv[i]);
1015  }
1016 
1017  const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1018  if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
1019  TAILQ_EMPTY(&e->env->cc))
1020  {
1021  mutt_error(_("No recipients specified"));
1022  email_free(&e);
1023  goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1024  }
1025 
1026  if (subject)
1027  e->env->subject = mutt_str_dup(subject);
1028 
1029  if (draft_file)
1030  {
1031  infile = draft_file;
1032  include_file = NULL;
1033  }
1034  else if (include_file)
1035  infile = include_file;
1036  else
1037  edit_infile = false;
1038 
1039  if (infile || bodytext)
1040  {
1041  /* Prepare fp_in and expanded_infile. */
1042  if (infile)
1043  {
1044  if (mutt_str_equal("-", infile))
1045  {
1046  if (edit_infile)
1047  {
1048  mutt_error(_("Can't use -E flag with stdin"));
1049  email_free(&e);
1050  goto main_curses; // TEST27: neomutt -E -H -
1051  }
1052  fp_in = stdin;
1053  }
1054  else
1055  {
1056  mutt_buffer_strcpy(&expanded_infile, infile);
1057  mutt_buffer_expand_path(&expanded_infile);
1058  fp_in = fopen(mutt_buffer_string(&expanded_infile), "r");
1059  if (!fp_in)
1060  {
1061  mutt_perror(mutt_buffer_string(&expanded_infile));
1062  email_free(&e);
1063  goto main_curses; // TEST28: neomutt -E -H missing
1064  }
1065  }
1066  }
1067 
1068  /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1069  * Note: stdin is always copied to a tempfile, ensuring draft_file
1070  * can stat and get the correct st_size below. */
1071  if (!edit_infile)
1072  {
1073  mutt_buffer_mktemp(&tempfile);
1074 
1075  fp_out = mutt_file_fopen(mutt_buffer_string(&tempfile), "w");
1076  if (!fp_out)
1077  {
1078  mutt_file_fclose(&fp_in);
1079  mutt_perror(mutt_buffer_string(&tempfile));
1080  email_free(&e);
1081  goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1082  }
1083  if (fp_in)
1084  {
1085  mutt_file_copy_stream(fp_in, fp_out);
1086  if (fp_in != stdin)
1087  mutt_file_fclose(&fp_in);
1088  }
1089  else if (bodytext)
1090  fputs(bodytext, fp_out);
1091  mutt_file_fclose(&fp_out);
1092 
1093  fp_in = fopen(mutt_buffer_string(&tempfile), "r");
1094  if (!fp_in)
1095  {
1096  mutt_perror(mutt_buffer_string(&tempfile));
1097  email_free(&e);
1098  goto main_curses; // TEST30: can't test
1099  }
1100  }
1101  /* If editing the infile, keep it around afterwards so
1102  * it doesn't get unlinked, and we can rebuild the draft_file */
1103  else
1104  sendflags |= SEND_NO_FREE_HEADER;
1105 
1106  /* Parse the draft_file into the full Email/Body structure.
1107  * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1108  * our e->body. */
1109  if (draft_file)
1110  {
1111  struct Envelope *opts_env = e->env;
1112  struct stat st;
1113 
1114  sendflags |= SEND_DRAFT_FILE;
1115 
1116  /* Set up a tmp Email with just enough information so that
1117  * mutt_prepare_template() can parse the message in fp_in. */
1118  struct Email *e_tmp = email_new();
1119  e_tmp->offset = 0;
1120  e_tmp->body = mutt_body_new();
1121  if (fstat(fileno(fp_in), &st) != 0)
1122  {
1123  mutt_perror(draft_file);
1124  email_free(&e);
1125  email_free(&e_tmp);
1126  goto main_curses; // TEST31: can't test
1127  }
1128  e_tmp->body->length = st.st_size;
1129 
1130  if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1131  {
1132  mutt_error(_("Can't parse message template: %s"), draft_file);
1133  email_free(&e);
1134  email_free(&e_tmp);
1135  goto main_curses;
1136  }
1137 
1138  /* Scan for neomutt header to set `$resume_draft_files` */
1139  struct ListNode *np = NULL, *tmp = NULL;
1140  STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1141  {
1142  if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1143  {
1144  const bool c_resume_edited_draft_files =
1145  cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1146  if (c_resume_edited_draft_files)
1147  cs_str_native_set(cs, "resume_draft_files", true, NULL);
1148 
1149  STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1150  FREE(&np->data);
1151  FREE(&np);
1152  }
1153  }
1154 
1155  mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1156  mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1157  mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1158  if (opts_env->subject)
1159  mutt_str_replace(&e->env->subject, opts_env->subject);
1160 
1161  mutt_env_free(&opts_env);
1162  email_free(&e_tmp);
1163  }
1164  /* Editing the include_file: pass it directly in.
1165  * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1166  else if (edit_infile)
1167  bodyfile = mutt_buffer_string(&expanded_infile);
1168  // For bodytext and unedited include_file: use the tempfile.
1169  else
1170  bodyfile = mutt_buffer_string(&tempfile);
1171 
1172  mutt_file_fclose(&fp_in);
1173  }
1174 
1175  FREE(&bodytext);
1176 
1177  if (!STAILQ_EMPTY(&attach))
1178  {
1179  struct Body *b = e->body;
1180 
1181  while (b && b->next)
1182  b = b->next;
1183 
1184  struct ListNode *np = NULL;
1185  STAILQ_FOREACH(np, &attach, entries)
1186  {
1187  if (b)
1188  {
1190  b = b->next;
1191  }
1192  else
1193  {
1195  e->body = b;
1196  }
1197  if (!b)
1198  {
1199  mutt_error(_("%s: unable to attach file"), np->data);
1200  mutt_list_free(&attach);
1201  email_free(&e);
1202  goto main_curses; // TEST32: neomutt john@example.com -a missing
1203  }
1204  }
1205  mutt_list_free(&attach);
1206  }
1207 
1208  rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1209  /* We WANT the "Mail sent." and any possible, later error */
1210  log_queue_empty();
1211  if (ErrorBufMessage)
1212  mutt_message("%s", ErrorBuf);
1213 
1214  if (edit_infile)
1215  {
1216  if (include_file)
1217  e->body->unlink = false;
1218  else if (draft_file)
1219  {
1220  if (truncate(mutt_buffer_string(&expanded_infile), 0) == -1)
1221  {
1222  mutt_perror(mutt_buffer_string(&expanded_infile));
1223  email_free(&e);
1224  goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1225  }
1226  fp_out = mutt_file_fopen(mutt_buffer_string(&expanded_infile), "a");
1227  if (!fp_out)
1228  {
1229  mutt_perror(mutt_buffer_string(&expanded_infile));
1230  email_free(&e);
1231  goto main_curses; // TEST34: can't test
1232  }
1233 
1234  /* If the message was sent or postponed, these will already
1235  * have been done. */
1236  if (rv < 0)
1237  {
1238  if (e->body->next)
1239  e->body = mutt_make_multipart(e->body);
1241  mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1242  mutt_env_to_intl(e->env, NULL, NULL);
1243  }
1244 
1245  const bool c_crypt_protected_headers_read =
1246  cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1248  fp_out, e->env, e->body, MUTT_WRITE_HEADER_POSTPONE, false,
1249  c_crypt_protected_headers_read && mutt_should_hide_protected_subject(e),
1250  NeoMutt->sub);
1251  const bool c_resume_edited_draft_files =
1252  cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1253  if (c_resume_edited_draft_files)
1254  fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1255  fputc('\n', fp_out);
1256  if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1257  {
1258  mutt_file_fclose(&fp_out);
1259  email_free(&e);
1260  goto main_curses; // TEST35: can't test
1261  }
1262  mutt_file_fclose(&fp_out);
1263  }
1264 
1265  email_free(&e);
1266  }
1267 
1268  /* !edit_infile && draft_file will leave the tempfile around */
1269  if (!mutt_buffer_is_empty(&tempfile))
1270  unlink(mutt_buffer_string(&tempfile));
1271 
1272  rootwin_free();
1273 
1274  if (rv != 0)
1275  goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1276  }
1277  else
1278  {
1279  if (flags & MUTT_CLI_MAILBOX)
1280  {
1281 #ifdef USE_IMAP
1282  const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1283  cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1284 #endif
1285  if (mutt_mailbox_check(NULL, 0) == 0)
1286  {
1287  mutt_message(_("No mailbox with new mail"));
1288  goto main_curses; // TEST37: neomutt -Z (no new mail)
1289  }
1290  mutt_buffer_reset(&folder);
1291  mutt_mailbox_next(NULL, &folder);
1292 #ifdef USE_IMAP
1293  cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1294 #endif
1295  }
1296  else if (flags & MUTT_CLI_SELECT)
1297  {
1298 #ifdef USE_NNTP
1299  if (flags & MUTT_CLI_NEWS)
1300  {
1301  const char *const c_news_server =
1302  cs_subset_string(NeoMutt->sub, "news_server");
1303  OptNews = true;
1305  c_news_server, false);
1306  if (!CurrentNewsSrv)
1307  goto main_curses; // TEST38: neomutt -G (unset news_server)
1308  }
1309  else
1310 #endif
1311  if (TAILQ_EMPTY(&NeoMutt->accounts))
1312  {
1313  mutt_error(_("No incoming mailboxes defined"));
1314  goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1315  }
1316  mutt_buffer_reset(&folder);
1318  ctx_mailbox(Context), NULL, NULL);
1319  if (mutt_buffer_is_empty(&folder))
1320  {
1321  goto main_ok; // TEST40: neomutt -y (quit selection)
1322  }
1323  }
1324 
1325  if (mutt_buffer_is_empty(&folder))
1326  {
1327  const char *const c_spool_file =
1328  cs_subset_string(NeoMutt->sub, "spool_file");
1329  if (c_spool_file)
1330  {
1331  // Check if `$spool_file` corresponds a mailboxes' description.
1332  struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1333  if (m_desc)
1334  mutt_buffer_strcpy(&folder, m_desc->realpath);
1335  else
1336  mutt_buffer_strcpy(&folder, c_spool_file);
1337  }
1338  else if (c_folder)
1339  mutt_buffer_strcpy(&folder, c_folder);
1340  /* else no folder */
1341  }
1342 
1343 #ifdef USE_NNTP
1344  if (OptNews)
1345  {
1346  OptNews = false;
1347  mutt_buffer_alloc(&folder, PATH_MAX);
1348  nntp_expand_path(folder.data, folder.dsize, &CurrentNewsSrv->conn->account);
1349  }
1350  else
1351 #endif
1352  mutt_buffer_expand_path(&folder);
1353 
1356 
1357  if (flags & MUTT_CLI_IGNORE)
1358  {
1359  /* check to see if there are any messages in the folder */
1360  switch (mx_path_is_empty(mutt_buffer_string(&folder)))
1361  {
1362  case -1:
1363  mutt_perror(mutt_buffer_string(&folder));
1364  goto main_curses; // TEST41: neomutt -z -f missing
1365  case 1:
1366  mutt_error(_("Mailbox is empty"));
1367  goto main_curses; // TEST42: neomutt -z -f /dev/null
1368  }
1369  }
1370 
1371  mutt_folder_hook(mutt_buffer_string(&folder), NULL);
1373  mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1375 
1376  repeat_error = true;
1377  struct Mailbox *m = mx_resolve(mutt_buffer_string(&folder));
1378  const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1379  if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1380  {
1381  if (m->account)
1383 
1384  mailbox_free(&m);
1385  mutt_error(_("Unable to open mailbox %s"), mutt_buffer_string(&folder));
1386  repeat_error = false;
1387  }
1388  if (m || !explicit_folder)
1389  {
1390  struct MuttWindow *dlg = index_pager_init();
1391  dialog_push(dlg);
1392 
1393  struct EventMailbox ev_m = { m };
1394  mutt_debug(LL_NOTIFY, "NT_MAILBOX_SWITCH: %p\n", m);
1396 
1397  mutt_index_menu(dlg, m);
1398  dialog_pop();
1399  mutt_window_free(&dlg);
1400  log_queue_empty();
1401  repeat_error = false;
1402  }
1403 #ifdef USE_IMAP
1404  imap_logout_all();
1405 #endif
1406 #ifdef USE_SASL
1407  mutt_sasl_done();
1408 #endif
1409 #ifdef USE_AUTOCRYPT
1411 #endif
1412  // TEST43: neomutt (no change to mailbox)
1413  // TEST44: neomutt (change mailbox)
1414  }
1415 
1416 main_ok:
1417  rc = 0;
1418 main_curses:
1419  mutt_endwin();
1421  /* Repeat the last message to the user */
1422  if (repeat_error && ErrorBufMessage)
1423  puts(ErrorBuf);
1424 main_exit:
1426  mutt_buffer_dealloc(&folder);
1427  mutt_buffer_dealloc(&expanded_infile);
1428  mutt_buffer_dealloc(&tempfile);
1429  mutt_list_free(&queries);
1431  rootwin_free();
1436  menu_cleanup();
1437  crypt_cleanup();
1438  mutt_opts_free();
1439  subjrx_free();
1440  attach_free();
1441  alternates_free();
1442  mutt_keys_free();
1444  mutt_prex_free();
1446  cs_free(&cs);
1448  log_queue_empty();
1449  mutt_log_stop();
1450  return rc;
1451 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
int mx_path_is_empty(const char *path)
Is the mailbox empty.
Definition: mx.c:1247
The "current" mailbox.
Definition: context.h:37
uint8_t CliFlags
Flags for command line options, e.g. MUTT_CLI_IGNORE.
Definition: main.c:240
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:244
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
Container for lots of config items.
Definition: set.h:259
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
The envelope/body of an email.
Definition: email.h:37
int mutt_log_start(void)
Enable file logging.
Definition: mutt_logging.c:284
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
void crypt_cleanup(void)
Clean up backend.
Definition: cryptglue.c:143
A postponed Email, just the envelope info.
Definition: header.h:42
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
struct Body * body
List of MIME parts.
Definition: email.h:91
void mutt_browser_cleanup(void)
Clean up working Buffers.
Definition: browser.c:160
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:444
Log of notifications.
Definition: logging.h:45
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
#define mutt_error(...)
Definition: logging.h:88
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:50
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:56
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe() -.
Definition: pop.c:1165
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition: terminal.c:55
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to an internal queue - Implements log_dispatcher_t -This log dispatcher saves a line ...
Definition: logging.c:400
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:668
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1108
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
void mutt_envlist_init(char *envp[])
Create a copy of the environment.
Definition: envlist.c:56
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:309
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
void print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:424
log_dispatcher_t MuttLogger
The log dispatcher -This function pointer controls where log messages are redirected.
Definition: logging.c:52
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition: neomutt.c:64
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
static void log_translation(void)
Log the translation being used.
Definition: main.c:480
#define _(a)
Definition: message.h:28
int debug_all_observer(struct NotifyCallback *nc)
Definition: notify.c:318
struct Body * next
next attachment in the list
Definition: body.h:53
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
Definition: logging.h:47
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Log informational message.
Definition: logging.h:39
WHERE char ErrorBuf[256]
Copy of the last error message.
Definition: mutt_globals.h:43
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:314
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1275
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:348
An Event that happened to a Mailbox.
Definition: mailbox.h:190
uint16_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:36
int mutt_str_atos(const char *str, short *dst)
Convert ASCII string to a short.
Definition: string.c:222
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:44
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
The body of an email.
Definition: body.h:34
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition: dump.h:37
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:39
#define CSR_RESULT(x)
Definition: set.h:52
void imap_logout_all(void)
close all open connections
Definition: imap.c:564
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:200
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:39
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:256
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
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:305
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:529
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition: hook.c:863
static bool get_user_info(struct ConfigSet *cs)
Find the user&#39;s name, home and shell.
Definition: main.c:439
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition: set.c:156
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
struct Mailbox * mailbox
Definition: context.h:49
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: mutt_history.c:61
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:1243
bool mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1612
int main_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: keymap.c:871
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, int start_col, bool display)
Wrapper for mutt_write_address()
Definition: address.c:1231
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition: mx.c:1738
struct Envelope * env
Envelope information.
Definition: email.h:90
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:1088
struct MyVarList MyVars
List of all the user&#39;s custom config variables.
Definition: myvar.c:34
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2125
#define MUTT_CLI_RO
-R Open mailbox in read-only mode
Definition: main.c:245
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
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:458
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: dialog.c:105
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: mutt_logging.c:321
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1017
void rootwin_new(void)
Create the default Windows.
Definition: rootwin.c:186
static int start_curses(void)
Start the curses or slang UI.
Definition: main.c:366
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: multipart.c:100
Plain text.
Definition: color.h:58
void test_parse_set(void)
Test the config parsing.
Definition: parse_test.c:39
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t -This log dispatcher saves a line of te...
Definition: logging.c:441
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define MUTT_CLI_SELECT
-y Start with a list of all mailboxes
Definition: main.c:246
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:141
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: keymap.c:849
void log_queue_set_max_size(int size)
Set a upper limit for the queue length.
Definition: logging.c:314
int mutt_query_variables(struct ListHead *queries, bool show_docs)
Implement the -Q command line flag.
Definition: init.c:1063
int mutt_autocrypt_init(struct Mailbox *m, bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:98
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:715
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:162
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1743
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:40
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:137
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
void myvarlist_free(struct MyVarList *list)
Free a List of MyVars.
Definition: myvar.c:161
#define MUTT_CLI_MAILBOX
-Z Open first mailbox if is has new mail
Definition: main.c:243
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition: dlg_index.c:1406
void init_config(struct ConfigSet *cs)
Initialise the config system.
Definition: mutt_config.c:770
void log_queue_empty(void)
Free the contents of the queue.
Definition: logging.c:326
char * data
Pointer to data.
Definition: buffer.h:35
#define MUTT_READONLY
Open in read-only mode.
Definition: mxapi.h:63
void subjrx_init(void)
Create new Subject Regex List.
Definition: subjectrx.c:55
Not object-related, NotifyGlobal.
Definition: notify_type.h:45
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
struct Mailbox * mutt_index_menu(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails.
Definition: dlg_index.c:1035
void myvar_set(const char *var, const char *val)
Set the value of a "my_" variable.
Definition: myvar.c:109
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
void mutt_log_stop(void)
Close the log file.
Definition: mutt_logging.c:221
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
void crypt_init(void)
Initialise the crypto backends.
Definition: cryptglue.c:94
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
bool TsSupported
Terminal Setting is supported.
Definition: terminal.c:43
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void mutt_opts_free(void)
clean up before quitting
Definition: init.c:638
void mutt_envlist_free(void)
Free the private copy of the environment.
Definition: envlist.c:41
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition: file.c:1385
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:51
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:49
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:37
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:241
struct Connection * conn
Definition: adata.h:63
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:170
char * data
String.
Definition: list.h:36
char * subject
Email&#39;s subject.
Definition: envelope.h:66
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
NeoMutt is initialised.
Definition: neomutt.h:50
Register for all notifications.
Definition: notify_type.h:33
static void usage(void)
Display NeoMutt command line.
Definition: main.c:293
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
void mutt_prex_free(void)
Cleanup heap memory allocated by compiled regexes.
Definition: prex.c:342
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:779
Current Mailbox has changed.
Definition: mailbox.h:182
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition: main.c:411
void dialog_pop(void)
Hide a Window from the user.
Definition: dialog.c:139
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:32
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe() -.
Definition: nntp.c:2709
void alternates_init(void)
Set up the alternates lists.
Definition: alternates.c:61
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:50
int log_disp_curses(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Display a log line in the message line - Implements log_dispatcher_t -.
Definition: mutt_logging.c:126
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1254
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:248
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:95
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:48
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mxapi.h:60
Url is mailto://.
Definition: url.h:45
#define STAILQ_EMPTY(head)
Definition: queue.h:348
void subjrx_free(void)
Free the Subject Regex List.
Definition: subjectrx.c:46
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:78
void mutt_commands_cleanup(void)
Clean up commands globals.
Definition: commands.c:95
void crypto_module_free(void)
Clean up the crypto modules.
Definition: crypt_mod.c:81
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
void attach_free(void)
Free the attachments lists.
Definition: attachments.c:92
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:737
void mutt_log_prep(void)
Prepare to log.
Definition: mutt_logging.c:211
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:393
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
WHERE bool ErrorBufMessage
true if the last message was an error
Definition: mutt_globals.h:42
void attach_init(void)
Set up the attachments lists.
Definition: attachments.c:106
#define TAILQ_EMPTY(head)
Definition: queue.h:721
void mutt_buffer_pool_free(void)
Release the Buffer pool.
Definition: pool.c:87
void rootwin_set_size(int cols, int rows)
Set the dimensions of the Root Window.
Definition: rootwin.c:222
void alternates_free(void)
Free the alternates lists.
Definition: alternates.c:50
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
A List node for strings.
Definition: list.h:34
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:559
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the main NeoMutt object.
Definition: neomutt.c:44
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:44
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
rfc2047 encode the content-descriptions
Definition: send.c:1573
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:242
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:58
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:736
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition: header.c:574
void rootwin_free(void)
Free all the default Windows.
Definition: rootwin.c:176
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:45
The header of an Email.
Definition: envelope.h:54
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
void print_copyright(void)
Print copyright message.
Definition: version.c:541