NeoMutt  2021-02-05
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
  • 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 33 of file main.c.

◆ GNULIB_defined_setlocale

#define GNULIB_defined_setlocale

Definition at line 34 of file main.c.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 100 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

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

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 104 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

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

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 99 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 115 of file main.c.

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

139 {
140  mutt_endwin();
141 #ifdef HAVE_LIBUNWIND
142  if (code != 0)
143  show_backtrace();
144 #endif
145  exit(code);
146 }
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 152 of file main.c.

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

226 {
227  km_init(); /* must come before mutt_init */
228 
229 #ifdef USE_SLANG_CURSES
230  SLtt_Ignore_Beep = 1; /* don't do that #*$@^! annoying visual beep! */
231  SLsmg_Display_Eight_Bit = 128; /* characters above this are printable */
232  SLtt_set_color(0, NULL, "default", "default");
233 #if (SLANG_VERSION >= 20000)
234  SLutf8_enable(-1);
235 #endif
236 #else
237  /* should come before initscr() so that ncurses 4.2 doesn't try to install
238  * its own SIGWINCH handler */
240 #endif
241  if (!initscr())
242  {
243  mutt_error(_("Error initializing terminal"));
244  return 1;
245  }
246  /* slang requires the signal handlers to be set after initializing */
249  keypad(stdscr, true);
250  cbreak();
251  noecho();
252  nonl();
253 #ifdef HAVE_TYPEAHEAD
254  typeahead(-1); /* simulate smooth scrolling */
255 #endif
256 #ifdef HAVE_META
257  meta(stdscr, true);
258 #endif
260  /* Now that curses is set up, we drop back to normal screen mode.
261  * This simplifies displaying error messages to the user.
262  * The first call to refresh() will swap us back to curses screen mode. */
263  endwin();
264  return 0;
265 }
#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:374
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 270 of file main.c.

271 {
272  setlocale(LC_ALL, "");
273 
274 #ifdef ENABLE_NLS
275  const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
276  if (domdir)
277  bindtextdomain(PACKAGE, domdir);
278  else
279  bindtextdomain(PACKAGE, MUTTLOCALEDIR);
280  textdomain(PACKAGE);
281 #endif
282 #ifndef LOCALES_HACK
283  /* Do we have a locale definition? */
284  if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
285  {
286  OptLocales = true;
287  }
288 #endif
289 }
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 298 of file main.c.

299 {
300  const char *shell = mutt_str_getenv("SHELL");
301  if (shell)
302  cs_str_initial_set(cs, "shell", shell, NULL);
303 
304  /* Get some information about the user */
305  struct passwd *pw = getpwuid(getuid());
306  if (pw)
307  {
308  if (!Username)
309  Username = mutt_str_dup(pw->pw_name);
310  if (!HomeDir)
311  HomeDir = mutt_str_dup(pw->pw_dir);
312  if (!shell)
313  cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
314  }
315 
316  if (!Username)
317  {
318  mutt_error(_("unable to determine username"));
319  return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
320  }
321 
322  if (!HomeDir)
323  {
324  mutt_error(_("unable to determine home directory"));
325  return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
326  }
327 
328  cs_str_reset(cs, "shell", NULL);
329  return true;
330 }
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 339 of file main.c.

340 {
341  const char *header = ""; // Do not merge these two lines
342  header = _(header); // otherwise the .po files will end up badly ordered
343  const char *lang = strcasestr(header, "Language:");
344  int len = 64;
345  if (lang)
346  {
347  lang += 9; // skip label
348  SKIPWS(lang);
349  char *nl = strchr(lang, '\n');
350  if (nl)
351  len = (nl - lang);
352  }
353  else
354  {
355  lang = "NONE";
356  }
357 
358  mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
359 }
#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 369 of file main.c.

370 {
371  char *subject = NULL;
372  char *include_file = NULL;
373  char *draft_file = NULL;
374  char *new_type = NULL;
375  char *dlevel = NULL;
376  char *dfile = NULL;
377 #ifdef USE_NNTP
378  char *cli_nntp = NULL;
379 #endif
380  struct Email *e = NULL;
381  struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
382  struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
383  struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
384  struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
385  struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
386  struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
387  SendFlags sendflags = SEND_NO_FLAGS;
388  CliFlags flags = MUTT_CLI_NO_FLAGS;
389  int version = 0;
390  int i;
391  bool explicit_folder = false;
392  bool dump_variables = false;
393  bool one_liner = false;
394  bool hide_sensitive = false;
395  bool batch_mode = false;
396  bool edit_infile = false;
397 #ifdef USE_DEBUG_PARSE_TEST
398  bool test_config = false;
399 #endif
400  int double_dash = argc, nargc = 1;
401  int rc = 1;
402  bool repeat_error = false;
403  struct Buffer folder = mutt_buffer_make(0);
404  struct Buffer expanded_infile = mutt_buffer_make(0);
405  struct Buffer tempfile = mutt_buffer_make(0);
406  struct ConfigSet *cs = NULL;
407 
409 
410  /* sanity check against stupid administrators */
411  if (getegid() != getgid())
412  {
413  mutt_error("%s: I don't want to run with privileges!", argv[0]);
414  goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
415  }
416 
417  init_locale();
418 
419  umask(077);
420 
421  mutt_envlist_init(envp);
422  for (optind = 1; optind < double_dash;)
423  {
424  /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
425  * encounters a non-option. That could be a file to attach
426  * (all non-options between -a and --) or it could be an address
427  * (which gets collapsed to the front of argv). */
428  for (; optind < argc; optind++)
429  {
430  if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
431  {
432  if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
433  double_dash = optind; /* quit outer loop after getopt */
434  break; /* drop through to getopt */
435  }
436 
437  /* non-option, either an attachment or address */
438  if (!STAILQ_EMPTY(&attach))
439  mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
440  else
441  argv[nargc++] = argv[optind];
442  }
443 
444  /* USE_NNTP 'g:G' */
445  i = getopt(argc, argv, "+A:a:Bb:F:f:c:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvxyzZ");
446  if (i != EOF)
447  {
448  switch (i)
449  {
450  case 'A':
451  mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
452  break;
453  case 'a':
454  mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
455  break;
456  case 'B':
457  batch_mode = true;
458  break;
459  case 'b':
460  mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
461  break;
462  case 'c':
463  mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
464  break;
465  case 'D':
466  dump_variables = true;
467  break;
468  case 'd':
469  dlevel = optarg;
470  break;
471  case 'E':
472  edit_infile = true;
473  break;
474  case 'e':
475  mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
476  break;
477  case 'F':
478  mutt_list_insert_tail(&Muttrc, mutt_str_dup(optarg));
479  break;
480  case 'f':
481  mutt_buffer_strcpy(&folder, optarg);
482  explicit_folder = true;
483  break;
484 #ifdef USE_NNTP
485  case 'g': /* Specify a news server */
486  cli_nntp = optarg;
487  /* fallthrough */
488  case 'G': /* List of newsgroups */
489  flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
490  break;
491 #endif
492  case 'H':
493  draft_file = optarg;
494  break;
495  case 'i':
496  include_file = optarg;
497  break;
498  case 'l':
499  dfile = optarg;
500  break;
501  case 'm':
502  new_type = optarg;
503  break;
504  case 'n':
505  flags |= MUTT_CLI_NOSYSRC;
506  break;
507  case 'O':
508  one_liner = true;
509  break;
510  case 'p':
511  sendflags |= SEND_POSTPONED;
512  break;
513  case 'Q':
514  mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
515  break;
516  case 'R':
517  flags |= MUTT_CLI_RO; /* read-only mode */
518  break;
519  case 'S':
520  hide_sensitive = true;
521  break;
522  case 's':
523  subject = optarg;
524  break;
525 #ifdef USE_DEBUG_PARSE_TEST
526  case 'T':
527  test_config = true;
528  break;
529 #endif
530  case 'v':
531  version++;
532  break;
533  case 'y': /* My special hack mode */
534  flags |= MUTT_CLI_SELECT;
535  break;
536  case 'Z':
538  break;
539  case 'z':
540  flags |= MUTT_CLI_IGNORE;
541  break;
542  default:
543  usage();
544  OptNoCurses = true;
545  goto main_ok; // TEST03: neomutt -9
546  }
547  }
548  }
549 
550  /* collapse remaining argv */
551  while (optind < argc)
552  argv[nargc++] = argv[optind++];
553  optind = 1;
554  argc = nargc;
555 
556  if (version > 0)
557  {
559  if (version == 1)
560  print_version(stdout);
561  else
562  print_copyright();
563  OptNoCurses = true;
564  goto main_ok; // TEST04: neomutt -v
565  }
566 
569 
570  cs = init_config(500);
571  if (!cs)
572  goto main_curses;
573  NeoMutt = neomutt_new(cs);
574 
575 #ifdef USE_DEBUG_NOTIFY
577 #endif
578 
579  if (!get_user_info(cs))
580  goto main_exit;
581 
582 #ifdef USE_DEBUG_PARSE_TEST
583  if (test_config)
584  {
585  cs_str_initial_set(cs, "from", "rich@flatcap.org", NULL);
586  cs_str_reset(cs, "from", NULL);
587  myvar_set("my_var", "foo");
588  test_parse_set();
589  goto main_ok;
590  }
591 #endif
592 
593  reset_tilde(cs);
594 
595  if (dfile)
596  {
597  cs_str_initial_set(cs, "debug_file", dfile, NULL);
598  cs_str_reset(cs, "debug_file", NULL);
599  }
600 
601  if (dlevel)
602  {
603  short num = 0;
604  if ((mutt_str_atos(dlevel, &num) < 0) || (num < LL_MESSAGE) || (num >= LL_MAX))
605  {
606  mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
607  goto main_exit; // TEST07: neomutt -d xyz
608  }
609  cs_str_initial_set(cs, "debug_level", dlevel, NULL);
610  cs_str_reset(cs, "debug_level", NULL);
611  }
612 
613  mutt_log_prep();
614  if (dlevel)
615  mutt_log_start();
616 
618 
619  log_translation();
620 
621  if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
622  {
623  e = email_new();
624  e->env = mutt_env_new();
625 
626  struct ListNode *np = NULL;
627  STAILQ_FOREACH(np, &bcc_list, entries)
628  {
629  mutt_addrlist_parse(&e->env->bcc, np->data);
630  }
631 
632  STAILQ_FOREACH(np, &cc_list, entries)
633  {
634  mutt_addrlist_parse(&e->env->cc, np->data);
635  }
636 
637  mutt_list_free(&bcc_list);
638  mutt_list_free(&cc_list);
639  }
640 
641  /* Check for a batch send. */
642  if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
643  dump_variables || batch_mode)
644  {
645  OptNoCurses = true;
646  sendflags = SEND_BATCH;
649  }
650 
651  /* Always create the mutt_windows because batch mode has some shared code
652  * paths that end up referencing them. */
654 
655  /* This must come before mutt_init() because curses needs to be started
656  * before calling the init_pair() function to set the color scheme. */
657  if (!OptNoCurses)
658  {
659  int crc = start_curses();
660  if (crc != 0)
661  goto main_curses; // TEST08: can't test -- fake term?
662 
663  /* check whether terminal status is supported (must follow curses init) */
665  mutt_window_set_root(COLS, LINES);
666  }
667 
668  /* set defaults and read init files */
669  int rc2 = mutt_init(cs, flags & MUTT_CLI_NOSYSRC, &commands);
670  mutt_list_free(&commands);
671  if (rc2 != 0)
672  goto main_curses;
673 
675 
676  /* The command line overrides the config */
677  if (dlevel)
678  cs_str_reset(cs, "debug_level", NULL);
679  if (dfile)
680  cs_str_reset(cs, "debug_file", NULL);
681 
682  if (mutt_log_start() < 0)
683  {
684  mutt_perror("log file");
685  goto main_exit;
686  }
687 
688 #ifdef USE_NNTP
689  /* "$news_server" precedence: command line, config file, environment, system file */
690  if (cli_nntp)
691  cs_str_string_set(cs, "news_server", cli_nntp, NULL);
692  if (!C_NewsServer)
693  {
694  const char *env_nntp = mutt_str_getenv("NNTPSERVER");
695  cs_str_string_set(cs, "news_server", env_nntp, NULL);
696  }
697  if (!C_NewsServer)
698  {
699  char buf[1024];
700  char *server = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
701  cs_str_string_set(cs, "news_server", server, NULL);
702  }
703  if (C_NewsServer)
704  cs_str_initial_set(cs, "news_server", C_NewsServer, NULL);
705 #endif
706 
707  /* Initialize crypto backends. */
708  crypt_init();
709 
710  if (new_type)
711  {
712  struct Buffer err = mutt_buffer_make(0);
713  int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
714  if (CSR_RESULT(r) != CSR_SUCCESS)
715  {
716  mutt_error(err.data);
717  mutt_buffer_dealloc(&err);
718  goto main_curses;
719  }
720  cs_str_reset(cs, "mbox_type", NULL);
721  }
722 
723  if (!STAILQ_EMPTY(&queries))
724  {
725  rc = mutt_query_variables(&queries, one_liner);
726  goto main_curses;
727  }
728 
729  if (dump_variables)
730  {
732  if (hide_sensitive)
733  cdflags |= CS_DUMP_HIDE_SENSITIVE;
734  if (one_liner)
735  cdflags |= CS_DUMP_SHOW_DOCS;
736  dump_config(cs, cdflags, stdout);
737  goto main_ok; // TEST18: neomutt -D
738  }
739 
740  if (!STAILQ_EMPTY(&alias_queries))
741  {
742  rc = 0;
743  for (; optind < argc; optind++)
744  mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
745  struct ListNode *np = NULL;
746  STAILQ_FOREACH(np, &alias_queries, entries)
747  {
748  struct AddressList *al = alias_lookup(np->data);
749  if (al)
750  {
751  /* output in machine-readable form */
752  mutt_addrlist_to_intl(al, NULL);
753  mutt_addrlist_write_file(al, stdout, 0, false);
754  }
755  else
756  {
757  rc = 1;
758  printf("%s\n", np->data); // TEST19: neomutt -A unknown
759  }
760  }
761  mutt_list_free(&alias_queries);
762  goto main_curses; // TEST20: neomutt -A alias
763  }
764 
765  if (!OptNoCurses)
766  {
768  clear();
772  }
773 
774 #ifdef USE_AUTOCRYPT
775  /* Initialize autocrypt after curses messages are working,
776  * because of the initial account setup screens. */
777  if (C_Autocrypt)
778  mutt_autocrypt_init(!(sendflags & SEND_BATCH));
779 #endif
780 
781  /* Create the `$folder` directory if it doesn't exist. */
782  if (!OptNoCurses && C_Folder)
783  {
784  struct stat sb;
785  struct Buffer *fpath = mutt_buffer_pool_get();
786 
789  bool skip = false;
790 #ifdef USE_IMAP
791  /* we're not connected yet - skip mail folder creation */
792  skip |= (imap_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_IMAP);
793 #endif
794 #ifdef USE_POP
795  skip |= (pop_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_POP);
796 #endif
797 #ifdef USE_NNTP
798  skip |= (nntp_path_probe(mutt_buffer_string(fpath), NULL) == MUTT_NNTP);
799 #endif
800  if (!skip && (stat(mutt_buffer_string(fpath), &sb) == -1) && (errno == ENOENT))
801  {
802  char msg2[256];
803  snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), C_Folder);
804  if (mutt_yesorno(msg2, MUTT_YES) == MUTT_YES)
805  {
806  if ((mkdir(mutt_buffer_string(fpath), 0700) == -1) && (errno != EEXIST))
807  mutt_error(_("Can't create %s: %s"), C_Folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
808  }
809  }
810  mutt_buffer_pool_release(&fpath);
811  }
812 
813  if (batch_mode)
814  {
815  goto main_ok; // TEST22: neomutt -B
816  }
817 
823  if (Colors)
825 
826  if (sendflags & SEND_POSTPONED)
827  {
828  if (!OptNoCurses)
829  mutt_flushinp();
830  if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
831  rc = 0;
832  // TEST23: neomutt -p (postponed message, cancel)
833  // TEST24: neomutt -p (no postponed message)
834  log_queue_empty();
835  repeat_error = true;
836  goto main_curses;
837  }
838  else if (subject || e || sendflags || draft_file || include_file ||
839  !STAILQ_EMPTY(&attach) || (optind < argc))
840  {
841  FILE *fp_in = NULL;
842  FILE *fp_out = NULL;
843  char *infile = NULL;
844  char *bodytext = NULL;
845  const char *bodyfile = NULL;
846  int rv = 0;
847 
848  if (!OptNoCurses)
849  mutt_flushinp();
850 
851  if (!e)
852  e = email_new();
853  if (!e->env)
854  e->env = mutt_env_new();
855 
856  for (i = optind; i < argc; i++)
857  {
858  if (url_check_scheme(argv[i]) == U_MAILTO)
859  {
860  if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
861  {
862  mutt_error(_("Failed to parse mailto: link"));
863  email_free(&e);
864  goto main_curses; // TEST25: neomutt mailto:?
865  }
866  }
867  else
868  mutt_addrlist_parse(&e->env->to, argv[i]);
869  }
870 
871  if (!draft_file && C_Autoedit && TAILQ_EMPTY(&e->env->to) &&
872  TAILQ_EMPTY(&e->env->cc))
873  {
874  mutt_error(_("No recipients specified"));
875  email_free(&e);
876  goto main_curses; // TEST26: neomutt -s test (with autoedit=yes)
877  }
878 
879  if (subject)
880  e->env->subject = mutt_str_dup(subject);
881 
882  if (draft_file)
883  {
884  infile = draft_file;
885  include_file = NULL;
886  }
887  else if (include_file)
888  infile = include_file;
889  else
890  edit_infile = false;
891 
892  if (infile || bodytext)
893  {
894  /* Prepare fp_in and expanded_infile. */
895  if (infile)
896  {
897  if (mutt_str_equal("-", infile))
898  {
899  if (edit_infile)
900  {
901  mutt_error(_("Can't use -E flag with stdin"));
902  email_free(&e);
903  goto main_curses; // TEST27: neomutt -E -H -
904  }
905  fp_in = stdin;
906  }
907  else
908  {
909  mutt_buffer_strcpy(&expanded_infile, infile);
910  mutt_buffer_expand_path(&expanded_infile);
911  fp_in = fopen(mutt_buffer_string(&expanded_infile), "r");
912  if (!fp_in)
913  {
914  mutt_perror(mutt_buffer_string(&expanded_infile));
915  email_free(&e);
916  goto main_curses; // TEST28: neomutt -E -H missing
917  }
918  }
919  }
920 
921  /* Copy input to a tempfile, and re-point fp_in to the tempfile.
922  * Note: stdin is always copied to a tempfile, ensuring draft_file
923  * can stat and get the correct st_size below. */
924  if (!edit_infile)
925  {
926  mutt_buffer_mktemp(&tempfile);
927 
928  fp_out = mutt_file_fopen(mutt_buffer_string(&tempfile), "w");
929  if (!fp_out)
930  {
931  mutt_file_fclose(&fp_in);
932  mutt_perror(mutt_buffer_string(&tempfile));
933  email_free(&e);
934  goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
935  }
936  if (fp_in)
937  {
938  mutt_file_copy_stream(fp_in, fp_out);
939  if (fp_in != stdin)
940  mutt_file_fclose(&fp_in);
941  }
942  else if (bodytext)
943  fputs(bodytext, fp_out);
944  mutt_file_fclose(&fp_out);
945 
946  fp_in = fopen(mutt_buffer_string(&tempfile), "r");
947  if (!fp_in)
948  {
949  mutt_perror(mutt_buffer_string(&tempfile));
950  email_free(&e);
951  goto main_curses; // TEST30: can't test
952  }
953  }
954  /* If editing the infile, keep it around afterwards so
955  * it doesn't get unlinked, and we can rebuild the draft_file */
956  else
957  sendflags |= SEND_NO_FREE_HEADER;
958 
959  /* Parse the draft_file into the full Email/Body structure.
960  * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
961  * our e->body. */
962  if (draft_file)
963  {
964  struct Envelope *opts_env = e->env;
965  struct stat st;
966 
967  sendflags |= SEND_DRAFT_FILE;
968 
969  /* Set up a tmp Email with just enough information so that
970  * mutt_prepare_template() can parse the message in fp_in. */
971  struct Email *e_tmp = email_new();
972  e_tmp->offset = 0;
973  e_tmp->body = mutt_body_new();
974  if (fstat(fileno(fp_in), &st) != 0)
975  {
976  mutt_perror(draft_file);
977  email_free(&e);
978  email_free(&e_tmp);
979  goto main_curses; // TEST31: can't test
980  }
981  e_tmp->body->length = st.st_size;
982 
983  if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
984  {
985  mutt_error(_("Can't parse message template: %s"), draft_file);
986  email_free(&e);
987  email_free(&e_tmp);
988  goto main_curses;
989  }
990 
991  /* Scan for neomutt header to set `$resume_draft_files` */
992  struct ListNode *np = NULL, *tmp = NULL;
993  STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
994  {
995  if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
996  {
998  cs_str_native_set(cs, "resume_draft_files", true, NULL);
999 
1000  STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1001  FREE(&np->data);
1002  FREE(&np);
1003  }
1004  }
1005 
1006  mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1007  mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1008  mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1009  if (opts_env->subject)
1010  mutt_str_replace(&e->env->subject, opts_env->subject);
1011 
1012  mutt_env_free(&opts_env);
1013  email_free(&e_tmp);
1014  }
1015  /* Editing the include_file: pass it directly in.
1016  * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1017  else if (edit_infile)
1018  bodyfile = mutt_buffer_string(&expanded_infile);
1019  // For bodytext and unedited include_file: use the tempfile.
1020  else
1021  bodyfile = mutt_buffer_string(&tempfile);
1022 
1023  mutt_file_fclose(&fp_in);
1024  }
1025 
1026  FREE(&bodytext);
1027 
1028  if (!STAILQ_EMPTY(&attach))
1029  {
1030  struct Body *b = e->body;
1031 
1032  while (b && b->next)
1033  b = b->next;
1034 
1035  struct ListNode *np = NULL;
1036  STAILQ_FOREACH(np, &attach, entries)
1037  {
1038  if (b)
1039  {
1041  b = b->next;
1042  }
1043  else
1044  {
1046  e->body = b;
1047  }
1048  if (!b)
1049  {
1050  mutt_error(_("%s: unable to attach file"), np->data);
1051  mutt_list_free(&attach);
1052  email_free(&e);
1053  goto main_curses; // TEST32: neomutt john@example.com -a missing
1054  }
1055  }
1056  mutt_list_free(&attach);
1057  }
1058 
1059  rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1060  /* We WANT the "Mail sent." and any possible, later error */
1061  log_queue_empty();
1062  if (ErrorBufMessage)
1063  mutt_message("%s", ErrorBuf);
1064 
1065  if (edit_infile)
1066  {
1067  if (include_file)
1068  e->body->unlink = false;
1069  else if (draft_file)
1070  {
1071  if (truncate(mutt_buffer_string(&expanded_infile), 0) == -1)
1072  {
1073  mutt_perror(mutt_buffer_string(&expanded_infile));
1074  email_free(&e);
1075  goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1076  }
1077  fp_out = mutt_file_fopen(mutt_buffer_string(&expanded_infile), "a");
1078  if (!fp_out)
1079  {
1080  mutt_perror(mutt_buffer_string(&expanded_infile));
1081  email_free(&e);
1082  goto main_curses; // TEST34: can't test
1083  }
1084 
1085  /* If the message was sent or postponed, these will already
1086  * have been done. */
1087  if (rv < 0)
1088  {
1089  if (e->body->next)
1090  e->body = mutt_make_multipart(e->body);
1092  mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1093  mutt_env_to_intl(e->env, NULL, NULL);
1094  }
1095 
1097  fp_out, e->env, e->body, MUTT_WRITE_HEADER_POSTPONE, false,
1099  NeoMutt->sub);
1101  fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1102  fputc('\n', fp_out);
1103  if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1104  {
1105  mutt_file_fclose(&fp_out);
1106  email_free(&e);
1107  goto main_curses; // TEST35: can't test
1108  }
1109  mutt_file_fclose(&fp_out);
1110  }
1111 
1112  email_free(&e);
1113  }
1114 
1115  /* !edit_infile && draft_file will leave the tempfile around */
1116  if (!mutt_buffer_is_empty(&tempfile))
1117  unlink(mutt_buffer_string(&tempfile));
1118 
1120 
1121  if (rv != 0)
1122  goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1123  }
1124  else
1125  {
1126  if (flags & MUTT_CLI_MAILBOX)
1127  {
1128  struct Mailbox *m = ctx_mailbox(Context);
1129 #ifdef USE_IMAP
1130  bool passive = C_ImapPassive;
1131  C_ImapPassive = false;
1132 #endif
1133  if (mutt_mailbox_check(m, 0) == 0)
1134  {
1135  mutt_message(_("No mailbox with new mail"));
1136  goto main_curses; // TEST37: neomutt -Z (no new mail)
1137  }
1138  mutt_buffer_reset(&folder);
1139  mutt_mailbox_next(m, &folder);
1140 #ifdef USE_IMAP
1141  C_ImapPassive = passive;
1142 #endif
1143  }
1144  else if (flags & MUTT_CLI_SELECT)
1145  {
1146 #ifdef USE_NNTP
1147  if (flags & MUTT_CLI_NEWS)
1148  {
1149  OptNews = true;
1150  CurrentNewsSrv =
1152  if (!CurrentNewsSrv)
1153  goto main_curses; // TEST38: neomutt -G (unset news_server)
1154  }
1155  else
1156 #endif
1157  if (TAILQ_EMPTY(&NeoMutt->accounts))
1158  {
1159  mutt_error(_("No incoming mailboxes defined"));
1160  goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1161  }
1162  mutt_buffer_reset(&folder);
1164  if (mutt_buffer_is_empty(&folder))
1165  {
1166  goto main_ok; // TEST40: neomutt -y (quit selection)
1167  }
1168  }
1169 
1170  if (mutt_buffer_is_empty(&folder))
1171  {
1172  if (C_Spoolfile)
1173  {
1174  // Check if `$spoolfile` corresponds a mailboxes' description.
1175  struct Mailbox *m_desc = mailbox_find_name(C_Spoolfile);
1176  if (m_desc)
1177  mutt_buffer_strcpy(&folder, m_desc->realpath);
1178  else
1179  mutt_buffer_strcpy(&folder, C_Spoolfile);
1180  }
1181  else if (C_Folder)
1182  mutt_buffer_strcpy(&folder, C_Folder);
1183  /* else no folder */
1184  }
1185 
1186 #ifdef USE_NNTP
1187  if (OptNews)
1188  {
1189  OptNews = false;
1190  mutt_buffer_alloc(&folder, PATH_MAX);
1191  nntp_expand_path(folder.data, folder.dsize, &CurrentNewsSrv->conn->account);
1192  }
1193  else
1194 #endif
1195  mutt_buffer_expand_path(&folder);
1196 
1199 
1200  if (flags & MUTT_CLI_IGNORE)
1201  {
1202  /* check to see if there are any messages in the folder */
1203  switch (mx_path_is_empty(mutt_buffer_string(&folder)))
1204  {
1205  case -1:
1206  mutt_perror(mutt_buffer_string(&folder));
1207  goto main_curses; // TEST41: neomutt -z -f missing
1208  case 1:
1209  mutt_error(_("Mailbox is empty"));
1210  goto main_curses; // TEST42: neomutt -z -f /dev/null
1211  }
1212  }
1213 
1214  mutt_folder_hook(mutt_buffer_string(&folder), NULL);
1217 
1218  repeat_error = true;
1219  struct Mailbox *m = mx_resolve(mutt_buffer_string(&folder));
1221  if (!Context)
1222  {
1223  if (m->account)
1225 
1226  mailbox_free(&m);
1227  mutt_error(_("Unable to open mailbox %s"), mutt_buffer_string(&folder));
1228  repeat_error = false;
1229  }
1230  if (Context || !explicit_folder)
1231  {
1232  struct MuttWindow *dlg = index_pager_init();
1233  dialog_push(dlg);
1234 
1235  struct EventMailbox em = { Context ? Context->mailbox : NULL };
1237 
1238  mutt_index_menu(dlg);
1239  dialog_pop();
1240  index_pager_shutdown(dlg);
1241  mutt_window_free(&dlg);
1242  ctx_free(&Context);
1243  log_queue_empty();
1244  repeat_error = false;
1245  }
1246 #ifdef USE_IMAP
1247  imap_logout_all();
1248 #endif
1249 #ifdef USE_SASL
1250  mutt_sasl_done();
1251 #endif
1252 #ifdef USE_AUTOCRYPT
1254 #endif
1255  // TEST43: neomutt (no change to mailbox)
1256  // TEST44: neomutt (change mailbox)
1257  }
1258 
1259 main_ok:
1260  rc = 0;
1261 main_curses:
1262  mutt_endwin();
1264  /* Repeat the last message to the user */
1265  if (repeat_error && ErrorBufMessage)
1266  puts(ErrorBuf);
1267 main_exit:
1269  mutt_buffer_dealloc(&folder);
1270  mutt_buffer_dealloc(&expanded_infile);
1271  mutt_buffer_dealloc(&tempfile);
1272  mutt_list_free(&queries);
1279  crypt_cleanup();
1280  mutt_opts_free();
1281  mutt_keys_free();
1283  mutt_prex_free();
1285  cs_free(&cs);
1287  log_queue_empty();
1288  mutt_log_stop();
1289  return rc;
1290 }
#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:1266
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:99
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:103
#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:96
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
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
#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:124
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:428
&#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:1140
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:339
#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:309
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1266
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:557
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
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:186
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:40
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:115
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:298
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:1238
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:70
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:1751
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:1083
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:104
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:1009
static int start_curses(void)
Start the curses or slang UI.
Definition: main.c:225
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:105
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition: autocrypt.c:133
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:3985
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:1070
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:724
&#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:138
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:102
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:1201
Definition: color.h:129
int mutt_index_menu(struct MuttWindow *dlg)
Display a list of emails.
Definition: index.c:1146
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: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:100
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:152
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:270
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:107
#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:1999
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:4118
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
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:4101
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:589
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
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:1451
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:101
#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:656
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 96 of file main.c.