NeoMutt  2020-11-20
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 "debug/lib.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "hook.h"
#include "index.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 "mutt_menu.h"
#include "muttlib.h"
#include "mx.h"
#include "myvar.h"
#include "options.h"
#include "protos.h"
#include "version.h"
#include <libintl.h>
#include "imap/lib.h"
#include "pop/lib.h"
#include "nntp/lib.h"
#include "autocrypt/lib.h"
+ Include dependency graph for main.c:

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...
 

Variables

bool C_ResumeEditedDraftFiles
 Config: Resume editing previously saved draft files. More...
 

Detailed Description

Command line processing.

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

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

◆ GNULIB_defined_setlocale

#define GNULIB_defined_setlocale

Definition at line 33 of file main.c.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 99 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

Definition at line 100 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 101 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 102 of file main.c.

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 103 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

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

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 98 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 114 of file main.c.

115 {
116  static const char *names[] = { "folder", "mbox", "postponed", "record" };
117 
118  struct Buffer value = mutt_buffer_make(256);
119  for (size_t i = 0; i < mutt_array_size(names); i++)
120  {
121  struct HashElem *he = cs_get_elem(cs, names[i]);
122  if (!he)
123  continue;
124  mutt_buffer_reset(&value);
125  cs_he_initial_get(cs, he, &value);
126  mutt_buffer_expand_path_regex(&value, false);
127  cs_he_initial_set(cs, he, value.data, NULL);
128  cs_he_reset(cs, he, NULL);
129  }
130  mutt_buffer_dealloc(&value);
131 }
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:140
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:356
#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:431
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:499
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:214
+ 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 137 of file main.c.

138 {
139  mutt_endwin();
140 #ifdef HAVE_LIBUNWIND
141  if (code != 0)
142  show_backtrace();
143 #endif
144  exit(code);
145 }
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
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 151 of file main.c.

152 {
153  puts(mutt_make_version());
154 
155  /* L10N: Try to limit to 80 columns */
156  puts(_("usage:"));
157  puts(_(" neomutt [-Enx] [-e <command>] [-F <config>] [-H <draft>] [-i <include>]\n"
158  " [-b <address>] [-c <address>] [-s <subject>] [-a <file> [...] --]\n"
159  " <address> [...]"));
160  puts(_(" neomutt [-nx] [-e <command>] [-F <config>] [-b <address>] [-c <address>]\n"
161  " [-s <subject>] [-a <file> [...] --] <address> [...] < message"));
162  puts(_(" neomutt [-nRy] [-e <command>] [-F <config>] [-f <mailbox>] [-m <type>]"));
163  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -A <alias>"));
164  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -B"));
165  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -D [-S] [-O]"));
166  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -d <level> -l <file>"));
167  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -G"));
168  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -g <server>"));
169  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -p"));
170  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Q <variable> [-O]"));
171  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Z"));
172  puts(_(" neomutt [-n] [-e <command>] [-F <config>] -z [-f <mailbox>]"));
173  puts(_(" neomutt -v[v]\n"));
174 
175  /* L10N: Try to limit to 80 columns. If more space is needed add an indented line */
176  puts(_("options:"));
177  puts(_(" -- Special argument forces NeoMutt to stop option parsing and treat\n"
178  " remaining arguments as addresses even if they start with a dash"));
179  puts(_(" -A <alias> Print an expanded version of the given alias to stdout and exit"));
180  puts(_(" -a <file> Attach one or more files to a message (must be the last option)\n"
181  " Add any addresses after the '--' argument"));
182  puts(_(" -B Run in batch mode (do not start the ncurses UI)"));
183  puts(_(" -b <address> Specify a blind carbon copy (Bcc) recipient"));
184  puts(_(" -c <address> Specify a carbon copy (Cc) recipient"));
185  puts(_(" -D Dump all config variables as 'name=value' pairs to stdout"));
186  puts(_(" -D -O Like -D, but show one-liner documentation"));
187  puts(_(" -D -S Like -D, but hide the value of sensitive variables"));
188  puts(_(" -d <level> Log debugging output to a file (default is \"~/.neomuttdebug0\")\n"
189  " The level can range from 1-5 and affects verbosity"));
190  puts(_(" -E Edit draft (-H) or include (-i) file during message composition"));
191  puts(_(" -e <command> Specify a command to be run after reading the config files"));
192  puts(_(" -F <config> Specify an alternative initialization file to read"));
193  puts(_(" -f <mailbox> Specify a mailbox (as defined with 'mailboxes' command) to load"));
194  puts(_(" -G Start NeoMutt with a listing of subscribed newsgroups"));
195  puts(_(" -g <server> Like -G, but start at specified news server"));
196  puts(_(" -H <draft> Specify a draft file with header and body for message composing"));
197  puts(_(" -h Print this help message and exit"));
198  puts(_(" -i <include> Specify an include file to be embedded in the body of a message"));
199  puts(_(" -l <file> Specify a file for debugging output (default \"~/.neomuttdebug0\")"));
200  puts(_(" -m <type> Specify a default mailbox format type for newly created folders\n"
201  " The type is either MH, MMDF, Maildir or mbox (case-insensitive)"));
202  puts(_(" -n Do not read the system-wide configuration file"));
203  puts(_(" -p Resume a prior postponed message, if any"));
204  puts(_(" -Q <variable> Query a configuration variable and print its value to stdout\n"
205  " (after the config has been read and any commands executed)\n"
206  " Add -O for one-liner documentation"));
207  puts(_(" -R Open mailbox in read-only mode"));
208  puts(_(" -s <subject> Specify a subject (must be enclosed in quotes if it has spaces)"));
209  puts(_(" -v Print the NeoMutt version and compile-time definitions and exit"));
210  puts(_(" -vv Print the NeoMutt license and copyright information and exit"));
211  puts(_(" -y Start NeoMutt with a listing of all defined mailboxes"));
212  puts(_(" -Z Open the first mailbox with new message or exit immediately with\n"
213  " exit code 1 if none is found in all defined mailboxes"));
214  puts(_(" -z Open the first or specified (-f) mailbox if it holds any message\n"
215  " or exit immediately with exit code 1 otherwise"));
216 }
#define _(a)
Definition: message.h:28
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1460
+ 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 224 of file main.c.

225 {
226  km_init(); /* must come before mutt_init */
227 
228 #ifdef USE_SLANG_CURSES
229  SLtt_Ignore_Beep = 1; /* don't do that #*$@^! annoying visual beep! */
230  SLsmg_Display_Eight_Bit = 128; /* characters above this are printable */
231  SLtt_set_color(0, NULL, "default", "default");
232 #if (SLANG_VERSION >= 20000)
233  SLutf8_enable(-1);
234 #endif
235 #else
236  /* should come before initscr() so that ncurses 4.2 doesn't try to install
237  * its own SIGWINCH handler */
239 #endif
240  if (!initscr())
241  {
242  mutt_error(_("Error initializing terminal"));
243  return 1;
244  }
245  /* slang requires the signal handlers to be set after initializing */
248  keypad(stdscr, true);
249  cbreak();
250  noecho();
251  nonl();
252 #ifdef HAVE_TYPEAHEAD
253  typeahead(-1); /* simulate smooth scrolling */
254 #endif
255 #ifdef HAVE_META
256  meta(stdscr, true);
257 #endif
259  /* Now that curses is set up, we drop back to normal screen mode.
260  * This simplifies displaying error messages to the user.
261  * The first call to refresh() will swap us back to curses screen mode. */
262  endwin();
263  return 0;
264 }
#define _(a)
Definition: message.h:28
void km_init(void)
Initialise all the menu keybindings.
Definition: keymap.c:1010
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: keymap.c:981
void mutt_signal_init(void)
Initialise the signal handling.
Definition: mutt_signal.c:132
struct Colors * mutt_colors_new(void)
Create new colours.
Definition: color.c:373
Definition: color.h:129
#define mutt_error(...)
Definition: logging.h:84
+ 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 269 of file main.c.

270 {
271  setlocale(LC_ALL, "");
272 
273 #ifdef ENABLE_NLS
274  const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
275  if (domdir)
276  bindtextdomain(PACKAGE, domdir);
277  else
278  bindtextdomain(PACKAGE, MUTTLOCALEDIR);
279  textdomain(PACKAGE);
280 #endif
281 #ifndef LOCALES_HACK
282  /* Do we have a locale definition? */
283  if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
284  {
285  OptLocales = true;
286  }
287 #endif
288 }
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
bool OptLocales
(pseudo) set if user has valid locale definition
Definition: mbyte.c:44
+ 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 297 of file main.c.

298 {
299  const char *shell = mutt_str_getenv("SHELL");
300  if (shell)
301  cs_str_initial_set(cs, "shell", shell, NULL);
302 
303  /* Get some information about the user */
304  struct passwd *pw = getpwuid(getuid());
305  if (pw)
306  {
307  if (!Username)
308  Username = mutt_str_dup(pw->pw_name);
309  if (!HomeDir)
310  HomeDir = mutt_str_dup(pw->pw_dir);
311  if (!shell)
312  cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
313  }
314 
315  if (!Username)
316  {
317  mutt_error(_("unable to determine username"));
318  return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
319  }
320 
321  if (!HomeDir)
322  {
323  mutt_error(_("unable to determine home directory"));
324  return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
325  }
326 
327  cs_str_reset(cs, "shell", NULL);
328  return true;
329 }
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:49
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
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:473
#define mutt_error(...)
Definition: logging.h:84
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:408
+ 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 338 of file main.c.

339 {
340  const char *header = ""; // Do not merge these two lines
341  header = _(header); // otherwise the .po files will end up badly ordered
342  const char *lang = strcasestr(header, "Language:");
343  int len = 64;
344  if (lang)
345  {
346  lang += 9; // skip label
347  SKIPWS(lang);
348  char *nl = strchr(lang, '\n');
349  if (nl)
350  len = (nl - lang);
351  }
352  else
353  {
354  lang = "NONE";
355  }
356 
357  mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
358 }
#define _(a)
Definition: message.h:28
#define SKIPWS(ch)
Definition: string2.h:46
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ 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 368 of file main.c.

369 {
370  char *subject = NULL;
371  char *include_file = NULL;
372  char *draft_file = NULL;
373  char *new_type = NULL;
374  char *dlevel = NULL;
375  char *dfile = NULL;
376 #ifdef USE_NNTP
377  char *cli_nntp = NULL;
378 #endif
379  struct Email *e = NULL;
380  struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
381  struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
382  struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
383  struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
384  struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
385  struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
386  SendFlags sendflags = SEND_NO_FLAGS;
387  CliFlags flags = MUTT_CLI_NO_FLAGS;
388  int version = 0;
389  int i;
390  bool explicit_folder = false;
391  bool dump_variables = false;
392  bool one_liner = false;
393  bool hide_sensitive = false;
394  bool batch_mode = false;
395  bool edit_infile = false;
396 #ifdef USE_DEBUG_PARSE_TEST
397  bool test_config = false;
398 #endif
399  int double_dash = argc, nargc = 1;
400  int rc = 1;
401  bool repeat_error = false;
402  struct Buffer folder = mutt_buffer_make(0);
403  struct Buffer expanded_infile = mutt_buffer_make(0);
404  struct Buffer tempfile = mutt_buffer_make(0);
405  struct ConfigSet *cs = NULL;
406 
408 
409  /* sanity check against stupid administrators */
410  if (getegid() != getgid())
411  {
412  mutt_error("%s: I don't want to run with privileges!", argv[0]);
413  goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
414  }
415 
416  init_locale();
417 
418  umask(077);
419 
420  mutt_envlist_init(envp);
421  for (optind = 1; optind < double_dash;)
422  {
423  /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
424  * encounters a non-option. That could be a file to attach
425  * (all non-options between -a and --) or it could be an address
426  * (which gets collapsed to the front of argv). */
427  for (; optind < argc; optind++)
428  {
429  if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
430  {
431  if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
432  double_dash = optind; /* quit outer loop after getopt */
433  break; /* drop through to getopt */
434  }
435 
436  /* non-option, either an attachment or address */
437  if (!STAILQ_EMPTY(&attach))
438  mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
439  else
440  argv[nargc++] = argv[optind];
441  }
442 
443  /* USE_NNTP 'g:G' */
444  i = getopt(argc, argv, "+A:a:Bb:F:f:c:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvxyzZ");
445  if (i != EOF)
446  {
447  switch (i)
448  {
449  case 'A':
450  mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
451  break;
452  case 'a':
453  mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
454  break;
455  case 'B':
456  batch_mode = true;
457  break;
458  case 'b':
459  mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
460  break;
461  case 'c':
462  mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
463  break;
464  case 'D':
465  dump_variables = true;
466  break;
467  case 'd':
468  dlevel = optarg;
469  break;
470  case 'E':
471  edit_infile = true;
472  break;
473  case 'e':
474  mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
475  break;
476  case 'F':
477  mutt_list_insert_tail(&Muttrc, mutt_str_dup(optarg));
478  break;
479  case 'f':
480  mutt_buffer_strcpy(&folder, optarg);
481  explicit_folder = true;
482  break;
483 #ifdef USE_NNTP
484  case 'g': /* Specify a news server */
485  cli_nntp = optarg;
486  /* fallthrough */
487  case 'G': /* List of newsgroups */
488  flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
489  break;
490 #endif
491  case 'H':
492  draft_file = optarg;
493  break;
494  case 'i':
495  include_file = optarg;
496  break;
497  case 'l':
498  dfile = optarg;
499  break;
500  case 'm':
501  new_type = optarg;
502  break;
503  case 'n':
504  flags |= MUTT_CLI_NOSYSRC;
505  break;
506  case 'O':
507  one_liner = true;
508  break;
509  case 'p':
510  sendflags |= SEND_POSTPONED;
511  break;
512  case 'Q':
513  mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
514  break;
515  case 'R':
516  flags |= MUTT_CLI_RO; /* read-only mode */
517  break;
518  case 'S':
519  hide_sensitive = true;
520  break;
521  case 's':
522  subject = optarg;
523  break;
524 #ifdef USE_DEBUG_PARSE_TEST
525  case 'T':
526  test_config = true;
527  break;
528 #endif
529  case 'v':
530  version++;
531  break;
532  case 'y': /* My special hack mode */
533  flags |= MUTT_CLI_SELECT;
534  break;
535  case 'Z':
537  break;
538  case 'z':
539  flags |= MUTT_CLI_IGNORE;
540  break;
541  default:
542  usage();
543  OptNoCurses = true;
544  goto main_ok; // TEST03: neomutt -9
545  }
546  }
547  }
548 
549  /* collapse remaining argv */
550  while (optind < argc)
551  argv[nargc++] = argv[optind++];
552  optind = 1;
553  argc = nargc;
554 
555  if (version > 0)
556  {
558  if (version == 1)
559  print_version(stdout);
560  else
561  print_copyright();
562  OptNoCurses = true;
563  goto main_ok; // TEST04: neomutt -v
564  }
565 
568 
569  cs = init_config(500);
570  if (!cs)
571  goto main_curses;
572  NeoMutt = neomutt_new(cs);
573 
574 #ifdef USE_DEBUG_NOTIFY
576 #endif
577 
578  if (!get_user_info(cs))
579  goto main_exit;
580 
581 #ifdef USE_DEBUG_PARSE_TEST
582  if (test_config)
583  {
584  cs_str_initial_set(cs, "from", "rich@flatcap.org", NULL);
585  cs_str_reset(cs, "from", NULL);
586  myvar_set("my_var", "foo");
587  test_parse_set();
588  goto main_ok;
589  }
590 #endif
591 
592  reset_tilde(cs);
593 
594  if (dfile)
595  {
596  cs_str_initial_set(cs, "debug_file", dfile, NULL);
597  cs_str_reset(cs, "debug_file", NULL);
598  }
599 
600  if (dlevel)
601  {
602  short num = 0;
603  if ((mutt_str_atos(dlevel, &num) < 0) || (num < LL_MESSAGE) || (num >= LL_MAX))
604  {
605  mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
606  goto main_exit; // TEST07: neomutt -d xyz
607  }
608  cs_str_initial_set(cs, "debug_level", dlevel, NULL);
609  cs_str_reset(cs, "debug_level", NULL);
610  }
611 
612  mutt_log_prep();
613  if (dlevel)
614  mutt_log_start();
615 
617 
618  log_translation();
619 
620  if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
621  {
622  e = email_new();
623  e->env = mutt_env_new();
624 
625  struct ListNode *np = NULL;
626  STAILQ_FOREACH(np, &bcc_list, entries)
627  {
628  mutt_addrlist_parse(&e->env->bcc, np->data);
629  }
630 
631  STAILQ_FOREACH(np, &cc_list, entries)
632  {
633  mutt_addrlist_parse(&e->env->cc, np->data);
634  }
635 
636  mutt_list_free(&bcc_list);
637  mutt_list_free(&cc_list);
638  }
639 
640  /* Check for a batch send. */
641  if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
642  dump_variables || batch_mode)
643  {
644  OptNoCurses = true;
645  sendflags = SEND_BATCH;
648  }
649 
650  /* Always create the mutt_windows because batch mode has some shared code
651  * paths that end up referencing them. */
653 
654  /* This must come before mutt_init() because curses needs to be started
655  * before calling the init_pair() function to set the color scheme. */
656  if (!OptNoCurses)
657  {
658  int crc = start_curses();
659  if (crc != 0)
660  goto main_curses; // TEST08: can't test -- fake term?
661 
662  /* check whether terminal status is supported (must follow curses init) */
664  mutt_window_set_root(COLS, LINES);
665  }
666 
667  /* set defaults and read init files */
668  int rc2 = mutt_init(cs, flags & MUTT_CLI_NOSYSRC, &commands);
669  mutt_list_free(&commands);
670  if (rc2 != 0)
671  goto main_curses;
672 
674 
675  /* The command line overrides the config */
676  if (dlevel)
677  cs_str_reset(cs, "debug_level", NULL);
678  if (dfile)
679  cs_str_reset(cs, "debug_file", NULL);
680 
681  if (mutt_log_start() < 0)
682  {
683  mutt_perror("log file");
684  goto main_exit;
685  }
686 
687 #ifdef USE_NNTP
688  /* "$news_server" precedence: command line, config file, environment, system file */
689  if (cli_nntp)
690  cs_str_string_set(cs, "news_server", cli_nntp, NULL);
691  if (!C_NewsServer)
692  {
693  const char *env_nntp = mutt_str_getenv("NNTPSERVER");
694  cs_str_string_set(cs, "news_server", env_nntp, NULL);
695  }
696  if (!C_NewsServer)
697  {
698  char buf[1024];
699  char *server = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
700  cs_str_string_set(cs, "news_server", server, NULL);
701  }
702  if (C_NewsServer)
703  cs_str_initial_set(cs, "news_server", C_NewsServer, NULL);
704 #endif
705 
706  /* Initialize crypto backends. */
707  crypt_init();
708 
709  if (new_type)
710  {
711  struct Buffer err = mutt_buffer_make(0);
712  int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
713  if (CSR_RESULT(r) != CSR_SUCCESS)
714  {
715  mutt_error(err.data);
716  mutt_buffer_dealloc(&err);
717  goto main_curses;
718  }
719  cs_str_reset(cs, "mbox_type", NULL);
720  }
721 
722  if (!STAILQ_EMPTY(&queries))
723  {
724  rc = mutt_query_variables(&queries, one_liner);
725  goto main_curses;
726  }
727 
728  if (dump_variables)
729  {
731  if (hide_sensitive)
732  cdflags |= CS_DUMP_HIDE_SENSITIVE;
733  if (one_liner)
734  cdflags |= CS_DUMP_SHOW_DOCS;
735  dump_config(cs, cdflags, stdout);
736  goto main_ok; // TEST18: neomutt -D
737  }
738 
739  if (!STAILQ_EMPTY(&alias_queries))
740  {
741  rc = 0;
742  for (; optind < argc; optind++)
743  mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
744  struct ListNode *np = NULL;
745  STAILQ_FOREACH(np, &alias_queries, entries)
746  {
747  struct AddressList *al = alias_lookup(np->data);
748  if (al)
749  {
750  /* output in machine-readable form */
751  mutt_addrlist_to_intl(al, NULL);
752  mutt_addrlist_write_file(al, stdout, 0, false);
753  }
754  else
755  {
756  rc = 1;
757  printf("%s\n", np->data); // TEST19: neomutt -A unknown
758  }
759  }
760  mutt_list_free(&alias_queries);
761  goto main_curses; // TEST20: neomutt -A alias
762  }
763 
764  if (!OptNoCurses)
765  {
767  clear();
771  }
772 
773 #ifdef USE_AUTOCRYPT
774  /* Initialize autocrypt after curses messages are working,
775  * because of the initial account setup screens. */
776  if (C_Autocrypt)
777  mutt_autocrypt_init(!(sendflags & SEND_BATCH));
778 #endif
779 
780  /* Create the `$folder` directory if it doesn't exist. */
781  if (!OptNoCurses && C_Folder)
782  {
783  struct stat sb;
784  struct Buffer *fpath = mutt_buffer_pool_get();
785 
788  bool skip = false;
789 #ifdef USE_IMAP
790  /* we're not connected yet - skip mail folder creation */
791  skip |= (imap_path_probe(mutt_b2s(fpath), NULL) == MUTT_IMAP);
792 #endif
793 #ifdef USE_POP
794  skip |= (pop_path_probe(mutt_b2s(fpath), NULL) == MUTT_POP);
795 #endif
796 #ifdef USE_NNTP
797  skip |= (nntp_path_probe(mutt_b2s(fpath), NULL) == MUTT_NNTP);
798 #endif
799  if (!skip && (stat(mutt_b2s(fpath), &sb) == -1) && (errno == ENOENT))
800  {
801  char msg2[256];
802  snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), C_Folder);
803  if (mutt_yesorno(msg2, MUTT_YES) == MUTT_YES)
804  {
805  if ((mkdir(mutt_b2s(fpath), 0700) == -1) && (errno != EEXIST))
806  mutt_error(_("Can't create %s: %s"), C_Folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
807  }
808  }
809  mutt_buffer_pool_release(&fpath);
810  }
811 
812  if (batch_mode)
813  {
814  goto main_ok; // TEST22: neomutt -B
815  }
816 
822  if (Colors)
824 
825  if (sendflags & SEND_POSTPONED)
826  {
827  if (!OptNoCurses)
828  mutt_flushinp();
829  if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
830  rc = 0;
831  // TEST23: neomutt -p (postponed message, cancel)
832  // TEST24: neomutt -p (no postponed message)
833  log_queue_empty();
834  repeat_error = true;
835  goto main_curses;
836  }
837  else if (subject || e || sendflags || draft_file || include_file ||
838  !STAILQ_EMPTY(&attach) || (optind < argc))
839  {
840  FILE *fp_in = NULL;
841  FILE *fp_out = NULL;
842  char *infile = NULL;
843  char *bodytext = NULL;
844  const char *bodyfile = NULL;
845  int rv = 0;
846 
847  if (!OptNoCurses)
848  mutt_flushinp();
849 
850  if (!e)
851  e = email_new();
852  if (!e->env)
853  e->env = mutt_env_new();
854 
855  for (i = optind; i < argc; i++)
856  {
857  if (url_check_scheme(argv[i]) == U_MAILTO)
858  {
859  if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
860  {
861  mutt_error(_("Failed to parse mailto: link"));
862  email_free(&e);
863  goto main_curses; // TEST25: neomutt mailto:?
864  }
865  }
866  else
867  mutt_addrlist_parse(&e->env->to, argv[i]);
868  }
869 
870  if (!draft_file && C_Autoedit && TAILQ_EMPTY(&e->env->to) &&
871  TAILQ_EMPTY(&e->env->cc))
872  {
873  mutt_error(_("No recipients specified"));
874  email_free(&e);
875  goto main_curses; // TEST26: neomutt -s test (with autoedit=yes)
876  }
877 
878  if (subject)
879  e->env->subject = mutt_str_dup(subject);
880 
881  if (draft_file)
882  {
883  infile = draft_file;
884  include_file = NULL;
885  }
886  else if (include_file)
887  infile = include_file;
888  else
889  edit_infile = false;
890 
891  if (infile || bodytext)
892  {
893  /* Prepare fp_in and expanded_infile. */
894  if (infile)
895  {
896  if (mutt_str_equal("-", infile))
897  {
898  if (edit_infile)
899  {
900  mutt_error(_("Can't use -E flag with stdin"));
901  email_free(&e);
902  goto main_curses; // TEST27: neomutt -E -H -
903  }
904  fp_in = stdin;
905  }
906  else
907  {
908  mutt_buffer_strcpy(&expanded_infile, infile);
909  mutt_buffer_expand_path(&expanded_infile);
910  fp_in = fopen(mutt_b2s(&expanded_infile), "r");
911  if (!fp_in)
912  {
913  mutt_perror(mutt_b2s(&expanded_infile));
914  email_free(&e);
915  goto main_curses; // TEST28: neomutt -E -H missing
916  }
917  }
918  }
919 
920  /* Copy input to a tempfile, and re-point fp_in to the tempfile.
921  * Note: stdin is always copied to a tempfile, ensuring draft_file
922  * can stat and get the correct st_size below. */
923  if (!edit_infile)
924  {
925  mutt_buffer_mktemp(&tempfile);
926 
927  fp_out = mutt_file_fopen(mutt_b2s(&tempfile), "w");
928  if (!fp_out)
929  {
930  mutt_file_fclose(&fp_in);
931  mutt_perror(mutt_b2s(&tempfile));
932  email_free(&e);
933  goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
934  }
935  if (fp_in)
936  {
937  mutt_file_copy_stream(fp_in, fp_out);
938  if (fp_in != stdin)
939  mutt_file_fclose(&fp_in);
940  }
941  else if (bodytext)
942  fputs(bodytext, fp_out);
943  mutt_file_fclose(&fp_out);
944 
945  fp_in = fopen(mutt_b2s(&tempfile), "r");
946  if (!fp_in)
947  {
948  mutt_perror(mutt_b2s(&tempfile));
949  email_free(&e);
950  goto main_curses; // TEST30: can't test
951  }
952  }
953  /* If editing the infile, keep it around afterwards so
954  * it doesn't get unlinked, and we can rebuild the draft_file */
955  else
956  sendflags |= SEND_NO_FREE_HEADER;
957 
958  /* Parse the draft_file into the full Email/Body structure.
959  * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
960  * our e->body. */
961  if (draft_file)
962  {
963  struct Envelope *opts_env = e->env;
964  struct stat st;
965 
966  sendflags |= SEND_DRAFT_FILE;
967 
968  /* Set up a tmp Email with just enough information so that
969  * mutt_prepare_template() can parse the message in fp_in. */
970  struct Email *e_tmp = email_new();
971  e_tmp->offset = 0;
972  e_tmp->body = mutt_body_new();
973  if (fstat(fileno(fp_in), &st) != 0)
974  {
975  mutt_perror(draft_file);
976  email_free(&e);
977  email_free(&e_tmp);
978  goto main_curses; // TEST31: can't test
979  }
980  e_tmp->body->length = st.st_size;
981 
982  if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
983  {
984  mutt_error(_("Can't parse message template: %s"), draft_file);
985  email_free(&e);
986  email_free(&e_tmp);
987  goto main_curses;
988  }
989 
990  /* Scan for neomutt header to set `$resume_draft_files` */
991  struct ListNode *np = NULL, *tmp = NULL;
992  STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
993  {
994  if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
995  {
997  cs_str_native_set(cs, "resume_draft_files", true, NULL);
998 
999  STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1000  FREE(&np->data);
1001  FREE(&np);
1002  }
1003  }
1004 
1005  mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1006  mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1007  mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1008  if (opts_env->subject)
1009  mutt_str_replace(&e->env->subject, opts_env->subject);
1010 
1011  mutt_env_free(&opts_env);
1012  email_free(&e_tmp);
1013  }
1014  /* Editing the include_file: pass it directly in.
1015  * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1016  else if (edit_infile)
1017  bodyfile = mutt_b2s(&expanded_infile);
1018  // For bodytext and unedited include_file: use the tempfile.
1019  else
1020  bodyfile = mutt_b2s(&tempfile);
1021 
1022  mutt_file_fclose(&fp_in);
1023  }
1024 
1025  FREE(&bodytext);
1026 
1027  if (!STAILQ_EMPTY(&attach))
1028  {
1029  struct Body *b = e->body;
1030 
1031  while (b && b->next)
1032  b = b->next;
1033 
1034  struct ListNode *np = NULL;
1035  STAILQ_FOREACH(np, &attach, entries)
1036  {
1037  if (b)
1038  {
1040  b = b->next;
1041  }
1042  else
1043  {
1045  e->body = b;
1046  }
1047  if (!b)
1048  {
1049  mutt_error(_("%s: unable to attach file"), np->data);
1050  mutt_list_free(&attach);
1051  email_free(&e);
1052  goto main_curses; // TEST32: neomutt john@example.com -a missing
1053  }
1054  }
1055  mutt_list_free(&attach);
1056  }
1057 
1058  rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1059  /* We WANT the "Mail sent." and any possible, later error */
1060  log_queue_empty();
1061  if (ErrorBufMessage)
1062  mutt_message("%s", ErrorBuf);
1063 
1064  if (edit_infile)
1065  {
1066  if (include_file)
1067  e->body->unlink = false;
1068  else if (draft_file)
1069  {
1070  if (truncate(mutt_b2s(&expanded_infile), 0) == -1)
1071  {
1072  mutt_perror(mutt_b2s(&expanded_infile));
1073  email_free(&e);
1074  goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1075  }
1076  fp_out = mutt_file_fopen(mutt_b2s(&expanded_infile), "a");
1077  if (!fp_out)
1078  {
1079  mutt_perror(mutt_b2s(&expanded_infile));
1080  email_free(&e);
1081  goto main_curses; // TEST34: can't test
1082  }
1083 
1084  /* If the message was sent or postponed, these will already
1085  * have been done. */
1086  if (rv < 0)
1087  {
1088  if (e->body->next)
1089  e->body = mutt_make_multipart(e->body);
1091  mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1092  mutt_env_to_intl(e->env, NULL, NULL);
1093  }
1094 
1096  fp_out, e->env, e->body, MUTT_WRITE_HEADER_POSTPONE, false,
1098  NeoMutt->sub);
1100  fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1101  fputc('\n', fp_out);
1102  if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1103  {
1104  mutt_file_fclose(&fp_out);
1105  email_free(&e);
1106  goto main_curses; // TEST35: can't test
1107  }
1108  mutt_file_fclose(&fp_out);
1109  }
1110 
1111  email_free(&e);
1112  }
1113 
1114  /* !edit_infile && draft_file will leave the tempfile around */
1115  if (!mutt_buffer_is_empty(&tempfile))
1116  unlink(mutt_b2s(&tempfile));
1117 
1119 
1120  if (rv != 0)
1121  goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1122  }
1123  else
1124  {
1125  if (flags & MUTT_CLI_MAILBOX)
1126  {
1127 #ifdef USE_IMAP
1128  bool passive = C_ImapPassive;
1129  C_ImapPassive = false;
1130 #endif
1131  if (mutt_mailbox_check(Context ? Context->mailbox : NULL, 0) == 0)
1132  {
1133  mutt_message(_("No mailbox with new mail"));
1134  goto main_curses; // TEST37: neomutt -Z (no new mail)
1135  }
1136  mutt_buffer_reset(&folder);
1137  mutt_mailbox_next(Context ? Context->mailbox : NULL, &folder);
1138 #ifdef USE_IMAP
1139  C_ImapPassive = passive;
1140 #endif
1141  }
1142  else if (flags & MUTT_CLI_SELECT)
1143  {
1144 #ifdef USE_NNTP
1145  if (flags & MUTT_CLI_NEWS)
1146  {
1147  OptNews = true;
1148  CurrentNewsSrv =
1150  if (!CurrentNewsSrv)
1151  goto main_curses; // TEST38: neomutt -G (unset news_server)
1152  }
1153  else
1154 #endif
1155  if (TAILQ_EMPTY(&NeoMutt->accounts))
1156  {
1157  mutt_error(_("No incoming mailboxes defined"));
1158  goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1159  }
1160  mutt_buffer_reset(&folder);
1162  if (mutt_buffer_is_empty(&folder))
1163  {
1164  goto main_ok; // TEST40: neomutt -y (quit selection)
1165  }
1166  }
1167 
1168  if (mutt_buffer_is_empty(&folder))
1169  {
1170  if (C_Spoolfile)
1171  {
1172  // Check if `$spoolfile` corresponds a mailboxes' description.
1173  struct Mailbox *m_desc = mailbox_find_name(C_Spoolfile);
1174  if (m_desc)
1175  mutt_buffer_strcpy(&folder, m_desc->realpath);
1176  else
1177  mutt_buffer_strcpy(&folder, C_Spoolfile);
1178  }
1179  else if (C_Folder)
1180  mutt_buffer_strcpy(&folder, C_Folder);
1181  /* else no folder */
1182  }
1183 
1184 #ifdef USE_NNTP
1185  if (OptNews)
1186  {
1187  OptNews = false;
1188  mutt_buffer_alloc(&folder, PATH_MAX);
1189  nntp_expand_path(folder.data, folder.dsize, &CurrentNewsSrv->conn->account);
1190  }
1191  else
1192 #endif
1193  mutt_buffer_expand_path(&folder);
1194 
1196  mutt_str_replace(&LastFolder, mutt_b2s(&folder));
1197 
1198  if (flags & MUTT_CLI_IGNORE)
1199  {
1200  /* check to see if there are any messages in the folder */
1201  switch (mx_path_is_empty(mutt_b2s(&folder)))
1202  {
1203  case -1:
1204  mutt_perror(mutt_b2s(&folder));
1205  goto main_curses; // TEST41: neomutt -z -f missing
1206  case 1:
1207  mutt_error(_("Mailbox is empty"));
1208  goto main_curses; // TEST42: neomutt -z -f /dev/null
1209  }
1210  }
1211 
1212  mutt_folder_hook(mutt_b2s(&folder), NULL);
1215 
1216  repeat_error = true;
1217  struct Mailbox *m = mx_resolve(mutt_b2s(&folder));
1219  if (!Context)
1220  {
1221  if (m->account)
1223 
1224  mailbox_free(&m);
1225  mutt_error(_("Unable to open mailbox %s"), mutt_b2s(&folder));
1226  repeat_error = false;
1227  }
1228  if (Context || !explicit_folder)
1229  {
1230  struct MuttWindow *dlg = index_pager_init();
1231  dialog_push(dlg);
1232 
1233  struct EventMailbox em = { Context ? Context->mailbox : NULL };
1235 
1236  mutt_index_menu(dlg);
1237  dialog_pop();
1238  index_pager_shutdown(dlg);
1239  mutt_window_free(&dlg);
1240  ctx_free(&Context);
1241  log_queue_empty();
1242  repeat_error = false;
1243  }
1244 #ifdef USE_IMAP
1245  imap_logout_all();
1246 #endif
1247 #ifdef USE_SASL
1248  mutt_sasl_done();
1249 #endif
1250 #ifdef USE_AUTOCRYPT
1252 #endif
1253  // TEST43: neomutt (no change to mailbox)
1254  // TEST44: neomutt (change mailbox)
1255  }
1256 
1257 main_ok:
1258  rc = 0;
1259 main_curses:
1260  mutt_endwin();
1262  /* Repeat the last message to the user */
1263  if (repeat_error && ErrorBufMessage)
1264  puts(ErrorBuf);
1265 main_exit:
1267  mutt_buffer_dealloc(&folder);
1268  mutt_buffer_dealloc(&expanded_infile);
1269  mutt_buffer_dealloc(&tempfile);
1270  mutt_list_free(&queries);
1277  crypt_cleanup();
1278  mutt_opts_free();
1279  mutt_keys_free();
1281  mutt_prex_free();
1283  cs_free(&cs);
1285  log_queue_empty();
1286  mutt_log_stop();
1287  return rc;
1288 }
#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:871
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:51
int mx_path_is_empty(const char *path)
Is the mailbox empty.
Definition: mx.c:1265
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:93
The "current" mailbox.
Definition: context.h:38
uint8_t CliFlags
Flags for command line options, e.g. MUTT_CLI_IGNORE.
Definition: main.c:98
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:102
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
Container for lots of config items.
Definition: set.h:228
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
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:127
bool C_ResumeEditedDraftFiles
Config: Resume editing previously saved draft files.
Definition: main.c:95
The envelope/body of an email.
Definition: email.h:37
int mutt_log_start(void)
Enable file logging.
Definition: mutt_logging.c:282
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void crypt_cleanup(void)
Clean up backend.
Definition: cryptglue.c:138
struct Notify * notify
Notifications system.
Definition: color.h:149
A postponed Email, just the envelope info.
Definition: header.h:42
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
void mutt_window_init(void)
Create the default Windows.
Definition: mutt_window.c:339
struct Body * body
List of MIME parts.
Definition: email.h:91
void mutt_browser_cleanup(void)
Clean up working Buffers.
Definition: browser.c:123
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1135
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
#define mutt_message(...)
Definition: logging.h:83
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:51
bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: config.c:37
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:57
void mutt_window_free_all(void)
Free all the default Windows.
Definition: mutt_window.c:304
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition: terminal.c:55
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:919
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1073
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t.
Definition: logging.c:441
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
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
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition: neomutt.c:64
String manipulation buffer.
Definition: buffer.h:33
bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: config.c:58
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:338
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
Definition: logging.h:47
A division of the screen.
Definition: mutt_window.h:115
char * C_NewsServer
Config: (nntp) Url of the news server.
Definition: config.c:41
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:613
Log informational message.
Definition: logging.h:39
WHERE char ErrorBuf[256]
Copy of the last error message.
Definition: mutt_globals.h:45
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:54
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:308
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1258
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:183
uint16_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:37
log_dispatcher_t MuttLogger
The log dispatcher.
Definition: logging.c:52
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
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:45
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:43
#define CSR_RESULT(x)
Definition: set.h:52
void imap_logout_all(void)
close all open connections
Definition: imap.c:554
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:49
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:186
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:40
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:114
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition: hook.c:504
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:836
static bool get_user_info(struct ConfigSet *cs)
Find the user&#39;s name, home and shell.
Definition: main.c:297
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
struct Notify * notify
Notifications system.
Definition: mutt_window.h:131
struct Mailbox * mailbox
Definition: context.h:50
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:1237
bool mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1591
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:63
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:276
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:1750
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:1082
struct MyVarList MyVars
List of all the user&#39;s custom config variables.
Definition: myvar.c:34
#define MUTT_CLI_RO
-R Open mailbox in read-only mode
Definition: main.c:103
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
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:473
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: dialog.c:66
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: mutt_globals.h:154
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:169
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1008
static int start_curses(void)
Start the curses or slang UI.
Definition: main.c:224
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: multipart.c:100
Plain text.
Definition: color.h:77
void test_parse_set(void)
Test the config parsing.
Definition: parse_test.c:39
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:104
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:133
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: keymap.c:866
int mutt_reply_observer(struct NotifyCallback *nc)
Listen for config changes to "reply_regex" - Implements observer_t.
Definition: index.c:3979
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
bool C_ImapPassive
Config: (imap) Reuse an existing IMAP connection to check for new mail.
Definition: config.c:54
void mutt_window_set_root(int cols, int rows)
Set the dimensions of the Root Window.
Definition: mutt_window.c:624
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:717
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:131
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1698
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:44
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:138
#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:131
#define MUTT_CLI_MAILBOX
-Z Open first mailbox if is has new mail
Definition: main.c:101
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe()
Definition: nntp.c:2793
int mutt_abort_key_config_observer(struct NotifyCallback *nc)
Listen for abort_key config changes - Implements observer_t.
Definition: keymap.c:887
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
void log_queue_empty(void)
Free the contents of the queue.
Definition: logging.c:326
char * data
Pointer to data.
Definition: buffer.h:35
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
struct ConfigSet * init_config(size_t size)
Initialise the config system.
Definition: mutt_config.c:854
Not object-related, NotifyGlobal.
Definition: notify_type.h:40
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:165
WHERE bool C_Autoedit
Config: Skip the initial compose menu and edit the email.
Definition: mutt_globals.h:136
void myvar_set(const char *var, const char *val)
Set the value of a "my_" variable.
Definition: myvar.c:91
#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:223
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:93
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
bool TsSupported
Terminal Setting is supported.
Definition: terminal.c:43
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe()
Definition: pop.c:1204
Definition: color.h:129
int mutt_index_menu(struct MuttWindow *dlg)
Display a list of emails.
Definition: index.c:1142
void mutt_opts_free(void)
clean up before quitting
Definition: init.c:631
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:1382
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:55
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:50
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:37
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:41
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:99
struct Connection * conn
Definition: lib.h:102
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:180
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:323
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:1304
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:108
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:151
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:347
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:776
Current Mailbox has changed.
Definition: mailbox.h:175
#define mutt_error(...)
Definition: logging.h:84
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:269
void dialog_pop(void)
Hide a Window from the user.
Definition: dialog.c:98
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition: dump.h:32
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:106
#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:94
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:42
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1995
Url is mailto://.
Definition: url.h:44
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
void index_pager_shutdown(struct MuttWindow *dlg)
Clear up any non-Window parts.
Definition: index.c:4112
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
void mutt_commands_cleanup(void)
Clean up commands globals.
Definition: commands.c:101
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
int mutt_hist_observer(struct NotifyCallback *nc)
Listen for config changes affecting the history - Implements observer_t.
Definition: mutt_history.c:59
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
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:761
void mutt_log_prep(void)
Prepare to log.
Definition: mutt_logging.c:213
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition: index.c:4095
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:408
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:50
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:44
#define TAILQ_EMPTY(head)
Definition: queue.h:714
void mutt_buffer_pool_free(void)
Release the Buffer pool.
Definition: pool.c:87
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to an internal queue - Implements log_dispatcher_t.
Definition: logging.c:400
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:557
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
int mutt_log_observer(struct NotifyCallback *nc)
Listen for config changes affecting the log file - Implements observer_t.
Definition: mutt_logging.c:317
&#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:45
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
rfc2047 encode the content-descriptions
Definition: send.c:1449
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:100
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:64
int debug_notify_observer(struct NotifyCallback *nc)
Definition: notify.c:321
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:655
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:573
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:46
The header of an Email.
Definition: envelope.h:54
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
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:152
void print_copyright(void)
Print copyright message.
Definition: version.c:541

Variable Documentation

◆ C_ResumeEditedDraftFiles

bool C_ResumeEditedDraftFiles

Config: Resume editing previously saved draft files.

Definition at line 95 of file main.c.