NeoMutt  2020-06-26-89-g172cd3
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 "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 "ncrypt/lib.h"
#include "send/lib.h"
#include <libintl.h>
#include "sidebar/lib.h"
#include "imap/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
#define mutt_array_size(x)
Definition: memory.h:33
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:348
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:206
char * data
Pointer to data.
Definition: buffer.h:35
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:486
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:418
The item stored in a Hash Table.
Definition: hash.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_exit()

void mutt_exit ( int  code)

Leave NeoMutt NOW.

Parameters
codeValue to return to the calling environment

Definition at line 137 of file main.c.

138 {
139  mutt_endwin();
140  exit(code);
141 }
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:569
+ Here is the caller graph for this function:

◆ usage()

static void usage ( void  )
static

Display NeoMutt command line.

Definition at line 147 of file main.c.

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

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

264 {
265  setlocale(LC_ALL, "");
266 
267 #ifdef ENABLE_NLS
268  const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
269  if (domdir)
270  bindtextdomain(PACKAGE, domdir);
271  else
272  bindtextdomain(PACKAGE, MUTTLOCALEDIR);
273  textdomain(PACKAGE);
274 #endif
275 #ifndef LOCALES_HACK
276  /* Do we have a locale definition? */
277  if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
278  {
279  OptLocales = true;
280  }
281 #endif
282 }
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:996
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 291 of file main.c.

292 {
293  const char *shell = mutt_str_getenv("SHELL");
294  if (shell)
295  cs_str_initial_set(cs, "shell", shell, NULL);
296 
297  /* Get some information about the user */
298  struct passwd *pw = getpwuid(getuid());
299  if (pw)
300  {
301  if (!Username)
302  Username = mutt_str_dup(pw->pw_name);
303  if (!HomeDir)
304  HomeDir = mutt_str_dup(pw->pw_dir);
305  if (!shell)
306  cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
307  }
308 
309  if (!Username)
310  {
311  mutt_error(_("unable to determine username"));
312  return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
313  }
314 
315  if (!HomeDir)
316  {
317  mutt_error(_("unable to determine home directory"));
318  return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
319  }
320 
321  cs_str_reset(cs, "shell", NULL);
322  return true;
323 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:50
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:996
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:53
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:460
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:395
#define mutt_error(...)
Definition: logging.h:84
+ 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 332 of file main.c.

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

363 {
364  char *subject = NULL;
365  char *include_file = NULL;
366  char *draft_file = NULL;
367  char *new_type = NULL;
368  char *dlevel = NULL;
369  char *dfile = NULL;
370 #ifdef USE_NNTP
371  char *cli_nntp = NULL;
372 #endif
373  struct Email *e = NULL;
374  struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
375  struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
376  struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
377  struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
378  struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
379  struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
380  SendFlags sendflags = SEND_NO_FLAGS;
381  CliFlags flags = MUTT_CLI_NO_FLAGS;
382  int version = 0;
383  int i;
384  bool explicit_folder = false;
385  bool dump_variables = false;
386  bool hide_sensitive = false;
387  bool batch_mode = false;
388  bool edit_infile = false;
389 #ifdef USE_DEBUG_PARSE_TEST
390  bool test_config = false;
391 #endif
392  int double_dash = argc, nargc = 1;
393  int rc = 1;
394  bool repeat_error = false;
395  struct Buffer folder = mutt_buffer_make(0);
396  struct Buffer expanded_infile = mutt_buffer_make(0);
397  struct Buffer tempfile = mutt_buffer_make(0);
398  struct ConfigSet *cs = NULL;
399 
401 
402  /* sanity check against stupid administrators */
403  if (getegid() != getgid())
404  {
405  mutt_error("%s: I don't want to run with privileges!", argv[0]);
406  goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
407  }
408 
409  init_locale();
410 
411  umask(077);
412 
413  mutt_envlist_init(envp);
414  for (optind = 1; optind < double_dash;)
415  {
416  /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
417  * encounters a non-option. That could be a file to attach
418  * (all non-options between -a and --) or it could be an address
419  * (which gets collapsed to the front of argv). */
420  for (; optind < argc; optind++)
421  {
422  if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
423  {
424  if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
425  double_dash = optind; /* quit outer loop after getopt */
426  break; /* drop through to getopt */
427  }
428 
429  /* non-option, either an attachment or address */
430  if (!STAILQ_EMPTY(&attach))
431  mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
432  else
433  argv[nargc++] = argv[optind];
434  }
435 
436  /* USE_NNTP 'g:G' */
437  i = getopt(argc, argv, "+A:a:Bb:F:f:c:Dd:l:Ee:g:GH:i:hm:npQ:RSs:TvxyzZ");
438  if (i != EOF)
439  {
440  switch (i)
441  {
442  case 'A':
443  mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
444  break;
445  case 'a':
446  mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
447  break;
448  case 'B':
449  batch_mode = true;
450  break;
451  case 'b':
452  mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
453  break;
454  case 'c':
455  mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
456  break;
457  case 'D':
458  dump_variables = true;
459  break;
460  case 'd':
461  dlevel = optarg;
462  break;
463  case 'E':
464  edit_infile = true;
465  break;
466  case 'e':
467  mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
468  break;
469  case 'F':
470  mutt_list_insert_tail(&Muttrc, mutt_str_dup(optarg));
471  break;
472  case 'f':
473  mutt_buffer_strcpy(&folder, optarg);
474  explicit_folder = true;
475  break;
476 #ifdef USE_NNTP
477  case 'g': /* Specify a news server */
478  cli_nntp = optarg;
479  /* fallthrough */
480  case 'G': /* List of newsgroups */
481  flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
482  break;
483 #endif
484  case 'H':
485  draft_file = optarg;
486  break;
487  case 'i':
488  include_file = optarg;
489  break;
490  case 'l':
491  dfile = optarg;
492  break;
493  case 'm':
494  new_type = optarg;
495  break;
496  case 'n':
497  flags |= MUTT_CLI_NOSYSRC;
498  break;
499  case 'p':
500  sendflags |= SEND_POSTPONED;
501  break;
502  case 'Q':
503  mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
504  break;
505  case 'R':
506  flags |= MUTT_CLI_RO; /* read-only mode */
507  break;
508  case 'S':
509  hide_sensitive = true;
510  break;
511  case 's':
512  subject = optarg;
513  break;
514 #ifdef USE_DEBUG_PARSE_TEST
515  case 'T':
516  test_config = true;
517  break;
518 #endif
519  case 'v':
520  version++;
521  break;
522  case 'y': /* My special hack mode */
523  flags |= MUTT_CLI_SELECT;
524  break;
525  case 'Z':
527  break;
528  case 'z':
529  flags |= MUTT_CLI_IGNORE;
530  break;
531  default:
532  usage();
533  OptNoCurses = true;
534  goto main_ok; // TEST03: neomutt -9
535  }
536  }
537  }
538 
539  /* collapse remaining argv */
540  while (optind < argc)
541  argv[nargc++] = argv[optind++];
542  optind = 1;
543  argc = nargc;
544 
545  if (version > 0)
546  {
548  if (version == 1)
549  print_version(stdout);
550  else
551  print_copyright();
552  OptNoCurses = true;
553  goto main_ok; // TEST04: neomutt -v
554  }
555 
558 
559  cs = init_config(500);
560  if (!cs)
561  goto main_curses;
562  NeoMutt = neomutt_new(cs);
563 
564 #ifdef USE_DEBUG_NOTIFY
566 #endif
567 
568  if (!get_user_info(cs))
569  goto main_exit;
570 
571 #ifdef USE_DEBUG_PARSE_TEST
572  if (test_config)
573  {
574  cs_str_initial_set(cs, "from", "rich@flatcap.org", NULL);
575  cs_str_reset(cs, "from", NULL);
576  myvar_set("my_var", "foo");
577  test_parse_set();
578  goto main_ok;
579  }
580 #endif
581 
582  reset_tilde(cs);
583 
584  if (dfile)
585  {
586  cs_str_initial_set(cs, "debug_file", dfile, NULL);
587  cs_str_reset(cs, "debug_file", NULL);
588  }
589 
590  if (dlevel)
591  {
592  short num = 0;
593  if ((mutt_str_atos(dlevel, &num) < 0) || (num < LL_MESSAGE) || (num >= LL_MAX))
594  {
595  mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
596  goto main_exit; // TEST07: neomutt -d xyz
597  }
598  cs_str_initial_set(cs, "debug_level", dlevel, NULL);
599  cs_str_reset(cs, "debug_level", NULL);
600  }
601 
602  mutt_log_prep();
603  if (dlevel)
604  mutt_log_start();
605 
607 
608  log_translation();
609 
610  if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
611  {
612  e = email_new();
613  e->env = mutt_env_new();
614 
615  struct ListNode *np = NULL;
616  STAILQ_FOREACH(np, &bcc_list, entries)
617  {
618  mutt_addrlist_parse(&e->env->bcc, np->data);
619  }
620 
621  STAILQ_FOREACH(np, &cc_list, entries)
622  {
623  mutt_addrlist_parse(&e->env->cc, np->data);
624  }
625 
626  mutt_list_free(&bcc_list);
627  mutt_list_free(&cc_list);
628  }
629 
630  /* Check for a batch send. */
631  if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
632  dump_variables || batch_mode)
633  {
634  OptNoCurses = true;
635  sendflags = SEND_BATCH;
638  }
639 
640  /* Always create the mutt_windows because batch mode has some shared code
641  * paths that end up referencing them. */
643 
644  /* This must come before mutt_init() because curses needs to be started
645  * before calling the init_pair() function to set the color scheme. */
646  if (!OptNoCurses)
647  {
648  int crc = start_curses();
649  if (crc != 0)
650  goto main_curses; // TEST08: can't test -- fake term?
651 
652  /* check whether terminal status is supported (must follow curses init) */
654  mutt_window_set_root(COLS, LINES);
655  }
656 
657  /* set defaults and read init files */
658  int rc2 = mutt_init(cs, flags & MUTT_CLI_NOSYSRC, &commands);
659  mutt_list_free(&commands);
660  if (rc2 != 0)
661  goto main_curses;
662 
664 
665  /* The command line overrides the config */
666  if (dlevel)
667  cs_str_reset(cs, "debug_level", NULL);
668  if (dfile)
669  cs_str_reset(cs, "debug_file", NULL);
670 
671  if (mutt_log_start() < 0)
672  {
673  mutt_perror("log file");
674  goto main_exit;
675  }
676 
677 #ifdef USE_NNTP
678  /* "$news_server" precedence: command line, config file, environment, system file */
679  if (cli_nntp)
680  cs_str_string_set(cs, "news_server", cli_nntp, NULL);
681  if (!C_NewsServer)
682  {
683  const char *env_nntp = mutt_str_getenv("NNTPSERVER");
684  cs_str_string_set(cs, "news_server", env_nntp, NULL);
685  }
686  if (!C_NewsServer)
687  {
688  char buf[1024];
689  char *server = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
690  cs_str_string_set(cs, "news_server", server, NULL);
691  }
692  if (C_NewsServer)
693  cs_str_initial_set(cs, "news_server", C_NewsServer, NULL);
694 #endif
695 
696  /* Initialize crypto backends. */
697  crypt_init();
698 
699  if (new_type)
700  {
701  struct Buffer err = mutt_buffer_make(0);
702  int r = cs_str_initial_set(cs, "mbox_type", new_type, &err);
703  if (CSR_RESULT(r) != CSR_SUCCESS)
704  {
705  mutt_error(err.data);
706  mutt_buffer_dealloc(&err);
707  goto main_curses;
708  }
709  cs_str_reset(cs, "mbox_type", NULL);
710  }
711 
712  if (!STAILQ_EMPTY(&queries))
713  {
714  rc = mutt_query_variables(&queries);
715  goto main_curses;
716  }
717 
718  if (dump_variables)
719  {
720  dump_config(cs, hide_sensitive ? CS_DUMP_HIDE_SENSITIVE : CS_DUMP_NO_FLAGS, stdout);
721  goto main_ok; // TEST18: neomutt -D
722  }
723 
724  if (!STAILQ_EMPTY(&alias_queries))
725  {
726  rc = 0;
727  for (; optind < argc; optind++)
728  mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
729  struct ListNode *np = NULL;
730  STAILQ_FOREACH(np, &alias_queries, entries)
731  {
732  struct AddressList *al = alias_lookup(np->data);
733  if (al)
734  {
735  /* output in machine-readable form */
736  mutt_addrlist_to_intl(al, NULL);
737  mutt_addrlist_write_file(al, stdout, 0, false);
738  }
739  else
740  {
741  rc = 1;
742  printf("%s\n", np->data); // TEST19: neomutt -A unknown
743  }
744  }
745  mutt_list_free(&alias_queries);
746  goto main_curses; // TEST20: neomutt -A alias
747  }
748 
749  if (!OptNoCurses)
750  {
752  clear();
756  }
757 
758 #ifdef USE_AUTOCRYPT
759  /* Initialize autocrypt after curses messages are working,
760  * because of the initial account setup screens. */
761  if (C_Autocrypt)
762  mutt_autocrypt_init(!(sendflags & SEND_BATCH));
763 #endif
764 
765  /* Create the C_Folder directory if it doesn't exist. */
766  if (!OptNoCurses && C_Folder)
767  {
768  struct stat sb;
769  struct Buffer *fpath = mutt_buffer_pool_get();
770 
773  bool skip = false;
774 #ifdef USE_IMAP
775  /* we're not connected yet - skip mail folder creation */
776  skip |= (imap_path_probe(mutt_b2s(fpath), NULL) == MUTT_IMAP);
777 #endif
778 #ifdef USE_NNTP
779  skip |= (nntp_path_probe(mutt_b2s(fpath), NULL) == MUTT_NNTP);
780 #endif
781  if (!skip && (stat(mutt_b2s(fpath), &sb) == -1) && (errno == ENOENT))
782  {
783  char msg2[256];
784  snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), C_Folder);
785  if (mutt_yesorno(msg2, MUTT_YES) == MUTT_YES)
786  {
787  if ((mkdir(mutt_b2s(fpath), 0700) == -1) && (errno != EEXIST))
788  mutt_error(_("Can't create %s: %s"), C_Folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
789  }
790  }
791  mutt_buffer_pool_release(&fpath);
792  }
793 
794  if (batch_mode)
795  {
796  goto main_ok; // TEST22: neomutt -B
797  }
798 
804  if (Colors)
806 
807  if (sendflags & SEND_POSTPONED)
808  {
809  if (!OptNoCurses)
810  mutt_flushinp();
811  if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
812  rc = 0;
813  // TEST23: neomutt -p (postponed message, cancel)
814  // TEST24: neomutt -p (no postponed message)
815  log_queue_empty();
816  repeat_error = true;
817  goto main_curses;
818  }
819  else if (subject || e || sendflags || draft_file || include_file ||
820  !STAILQ_EMPTY(&attach) || (optind < argc))
821  {
822  FILE *fp_in = NULL;
823  FILE *fp_out = NULL;
824  char *infile = NULL;
825  char *bodytext = NULL;
826  const char *bodyfile = NULL;
827  int rv = 0;
828 
829  if (!OptNoCurses)
830  mutt_flushinp();
831 
832  if (!e)
833  e = email_new();
834  if (!e->env)
835  e->env = mutt_env_new();
836 
837  for (i = optind; i < argc; i++)
838  {
839  if (url_check_scheme(argv[i]) == U_MAILTO)
840  {
841  if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
842  {
843  mutt_error(_("Failed to parse mailto: link"));
844  email_free(&e);
845  goto main_curses; // TEST25: neomutt mailto:?
846  }
847  }
848  else
849  mutt_addrlist_parse(&e->env->to, argv[i]);
850  }
851 
852  if (!draft_file && C_Autoedit && TAILQ_EMPTY(&e->env->to) &&
853  TAILQ_EMPTY(&e->env->cc))
854  {
855  mutt_error(_("No recipients specified"));
856  email_free(&e);
857  goto main_curses; // TEST26: neomutt -s test (with autoedit=yes)
858  }
859 
860  if (subject)
861  e->env->subject = mutt_str_dup(subject);
862 
863  if (draft_file)
864  {
865  infile = draft_file;
866  include_file = NULL;
867  }
868  else if (include_file)
869  infile = include_file;
870  else
871  edit_infile = false;
872 
873  if (infile || bodytext)
874  {
875  /* Prepare fp_in and expanded_infile. */
876  if (infile)
877  {
878  if (mutt_str_equal("-", infile))
879  {
880  if (edit_infile)
881  {
882  mutt_error(_("Can't use -E flag with stdin"));
883  email_free(&e);
884  goto main_curses; // TEST27: neomutt -E -H -
885  }
886  fp_in = stdin;
887  }
888  else
889  {
890  mutt_buffer_strcpy(&expanded_infile, infile);
891  mutt_buffer_expand_path(&expanded_infile);
892  fp_in = fopen(mutt_b2s(&expanded_infile), "r");
893  if (!fp_in)
894  {
895  mutt_perror(mutt_b2s(&expanded_infile));
896  email_free(&e);
897  goto main_curses; // TEST28: neomutt -E -H missing
898  }
899  }
900  }
901 
902  /* Copy input to a tempfile, and re-point fp_in to the tempfile.
903  * Note: stdin is always copied to a tempfile, ensuring draft_file
904  * can stat and get the correct st_size below. */
905  if (!edit_infile)
906  {
907  mutt_buffer_mktemp(&tempfile);
908 
909  fp_out = mutt_file_fopen(mutt_b2s(&tempfile), "w");
910  if (!fp_out)
911  {
912  mutt_file_fclose(&fp_in);
913  mutt_perror(mutt_b2s(&tempfile));
914  email_free(&e);
915  goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
916  }
917  if (fp_in)
918  {
919  mutt_file_copy_stream(fp_in, fp_out);
920  if (fp_in != stdin)
921  mutt_file_fclose(&fp_in);
922  }
923  else if (bodytext)
924  fputs(bodytext, fp_out);
925  mutt_file_fclose(&fp_out);
926 
927  fp_in = fopen(mutt_b2s(&tempfile), "r");
928  if (!fp_in)
929  {
930  mutt_perror(mutt_b2s(&tempfile));
931  email_free(&e);
932  goto main_curses; // TEST30: can't test
933  }
934  }
935  /* If editing the infile, keep it around afterwards so
936  * it doesn't get unlinked, and we can rebuild the draft_file */
937  else
938  sendflags |= SEND_NO_FREE_HEADER;
939 
940  /* Parse the draft_file into the full Email/Body structure.
941  * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
942  * our e->content. */
943  if (draft_file)
944  {
945  struct Envelope *opts_env = e->env;
946  struct stat st;
947 
948  sendflags |= SEND_DRAFT_FILE;
949 
950  /* Set up a tmp Email with just enough information so that
951  * mutt_prepare_template() can parse the message in fp_in. */
952  struct Email *e_tmp = email_new();
953  e_tmp->offset = 0;
954  e_tmp->content = mutt_body_new();
955  if (fstat(fileno(fp_in), &st) != 0)
956  {
957  mutt_perror(draft_file);
958  email_free(&e);
959  email_free(&e_tmp);
960  goto main_curses; // TEST31: can't test
961  }
962  e_tmp->content->length = st.st_size;
963 
964  if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
965  {
966  mutt_error(_("Can't parse message template: %s"), draft_file);
967  email_free(&e);
968  email_free(&e_tmp);
969  goto main_curses;
970  }
971 
972  /* Scan for neomutt header to set C_ResumeDraftFiles */
973  struct ListNode *np = NULL, *tmp = NULL;
974  STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
975  {
976  if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
977  {
979  cs_str_native_set(cs, "resume_draft_files", true, NULL);
980 
981  STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
982  FREE(&np->data);
983  FREE(&np);
984  }
985  }
986 
987  mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
988  mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
989  mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
990  if (opts_env->subject)
991  mutt_str_replace(&e->env->subject, opts_env->subject);
992 
993  mutt_env_free(&opts_env);
994  email_free(&e_tmp);
995  }
996  /* Editing the include_file: pass it directly in.
997  * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
998  else if (edit_infile)
999  bodyfile = mutt_b2s(&expanded_infile);
1000  // For bodytext and unedited include_file: use the tempfile.
1001  else
1002  bodyfile = mutt_b2s(&tempfile);
1003 
1004  mutt_file_fclose(&fp_in);
1005  }
1006 
1007  FREE(&bodytext);
1008 
1009  if (!STAILQ_EMPTY(&attach))
1010  {
1011  struct Body *b = e->content;
1012 
1013  while (b && b->next)
1014  b = b->next;
1015 
1016  struct ListNode *np = NULL;
1017  STAILQ_FOREACH(np, &attach, entries)
1018  {
1019  if (b)
1020  {
1022  b = b->next;
1023  }
1024  else
1025  {
1027  e->content = b;
1028  }
1029  if (!b)
1030  {
1031  mutt_error(_("%s: unable to attach file"), np->data);
1032  mutt_list_free(&attach);
1033  email_free(&e);
1034  goto main_curses; // TEST32: neomutt john@example.com -a missing
1035  }
1036  }
1037  mutt_list_free(&attach);
1038  }
1039 
1040  rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1041  /* We WANT the "Mail sent." and any possible, later error */
1042  log_queue_empty();
1043  if (ErrorBufMessage)
1044  mutt_message("%s", ErrorBuf);
1045 
1046  if (edit_infile)
1047  {
1048  if (include_file)
1049  e->content->unlink = false;
1050  else if (draft_file)
1051  {
1052  if (truncate(mutt_b2s(&expanded_infile), 0) == -1)
1053  {
1054  mutt_perror(mutt_b2s(&expanded_infile));
1055  email_free(&e);
1056  goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1057  }
1058  fp_out = mutt_file_fopen(mutt_b2s(&expanded_infile), "a");
1059  if (!fp_out)
1060  {
1061  mutt_perror(mutt_b2s(&expanded_infile));
1062  email_free(&e);
1063  goto main_curses; // TEST34: can't test
1064  }
1065 
1066  /* If the message was sent or postponed, these will already
1067  * have been done. */
1068  if (rv < 0)
1069  {
1070  if (e->content->next)
1073  mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1074  mutt_env_to_intl(e->env, NULL, NULL);
1075  }
1076 
1078  fp_out, e->env, e->content, MUTT_WRITE_HEADER_POSTPONE, false,
1080  NeoMutt->sub);
1082  fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1083  fputc('\n', fp_out);
1084  if ((mutt_write_mime_body(e->content, fp_out, NeoMutt->sub) == -1))
1085  {
1086  mutt_file_fclose(&fp_out);
1087  email_free(&e);
1088  goto main_curses; // TEST35: can't test
1089  }
1090  mutt_file_fclose(&fp_out);
1091  }
1092 
1093  email_free(&e);
1094  }
1095 
1096  /* !edit_infile && draft_file will leave the tempfile around */
1097  if (!mutt_buffer_is_empty(&tempfile))
1098  unlink(mutt_b2s(&tempfile));
1099 
1101 
1102  if (rv != 0)
1103  goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1104  }
1105  else
1106  {
1107  if (flags & MUTT_CLI_MAILBOX)
1108  {
1109 #ifdef USE_IMAP
1110  bool passive = C_ImapPassive;
1111  C_ImapPassive = false;
1112 #endif
1113  if (mutt_mailbox_check(Context ? Context->mailbox : NULL, 0) == 0)
1114  {
1115  mutt_message(_("No mailbox with new mail"));
1116  goto main_curses; // TEST37: neomutt -Z (no new mail)
1117  }
1118  mutt_buffer_reset(&folder);
1119  mutt_mailbox_next(Context ? Context->mailbox : NULL, &folder);
1120 #ifdef USE_IMAP
1121  C_ImapPassive = passive;
1122 #endif
1123  }
1124  else if (flags & MUTT_CLI_SELECT)
1125  {
1126 #ifdef USE_NNTP
1127  if (flags & MUTT_CLI_NEWS)
1128  {
1129  OptNews = true;
1130  CurrentNewsSrv =
1132  if (!CurrentNewsSrv)
1133  goto main_curses; // TEST38: neomutt -G (unset news_server)
1134  }
1135  else
1136 #endif
1137  if (TAILQ_EMPTY(&NeoMutt->accounts))
1138  {
1139  mutt_error(_("No incoming mailboxes defined"));
1140  goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1141  }
1142  mutt_buffer_reset(&folder);
1144  if (mutt_buffer_is_empty(&folder))
1145  {
1146  goto main_ok; // TEST40: neomutt -y (quit selection)
1147  }
1148  }
1149 
1150  if (mutt_buffer_is_empty(&folder))
1151  {
1152  if (C_Spoolfile)
1153  {
1154  // Check if C_Spoolfile corresponds a mailboxes' description.
1155  struct Mailbox *m_desc = mailbox_find_name(C_Spoolfile);
1156  if (m_desc)
1157  mutt_buffer_strcpy(&folder, m_desc->realpath);
1158  else
1159  mutt_buffer_strcpy(&folder, C_Spoolfile);
1160  }
1161  else if (C_Folder)
1162  mutt_buffer_strcpy(&folder, C_Folder);
1163  /* else no folder */
1164  }
1165 
1166 #ifdef USE_NNTP
1167  if (OptNews)
1168  {
1169  OptNews = false;
1170  mutt_buffer_alloc(&folder, PATH_MAX);
1171  nntp_expand_path(folder.data, folder.dsize, &CurrentNewsSrv->conn->account);
1172  }
1173  else
1174 #endif
1175  mutt_buffer_expand_path(&folder);
1176 
1178  mutt_str_replace(&LastFolder, mutt_b2s(&folder));
1179 
1180  if (flags & MUTT_CLI_IGNORE)
1181  {
1182  /* check to see if there are any messages in the folder */
1183  switch (mx_check_empty(mutt_b2s(&folder)))
1184  {
1185  case -1:
1186  mutt_perror(mutt_b2s(&folder));
1187  goto main_curses; // TEST41: neomutt -z -f missing
1188  case 1:
1189  mutt_error(_("Mailbox is empty"));
1190  goto main_curses; // TEST42: neomutt -z -f /dev/null
1191  }
1192  }
1193 
1194  mutt_folder_hook(mutt_b2s(&folder), NULL);
1197 
1198  repeat_error = true;
1199  struct Mailbox *m = mx_resolve(mutt_b2s(&folder));
1201  if (!Context)
1202  {
1203  if (m->account)
1205 
1206  mailbox_free(&m);
1207  mutt_error(_("Unable to open mailbox %s"), mutt_b2s(&folder));
1208  repeat_error = false;
1209  }
1210  if (Context || !explicit_folder)
1211  {
1212  struct MuttWindow *dlg = index_pager_init();
1213  dialog_push(dlg);
1214 #ifdef USE_SIDEBAR
1215  struct MuttWindow *win_sidebar = mutt_window_find(dlg, WT_SIDEBAR);
1216  sb_set_open_mailbox(win_sidebar, Context ? Context->mailbox : NULL);
1217 #endif
1218  mutt_index_menu(dlg);
1219  dialog_pop();
1220  index_pager_shutdown(dlg);
1221  mutt_window_free(&dlg);
1222  ctx_free(&Context);
1223  log_queue_empty();
1224  repeat_error = false;
1225  }
1226 #ifdef USE_IMAP
1227  imap_logout_all();
1228 #endif
1229 #ifdef USE_SASL
1230  mutt_sasl_done();
1231 #endif
1232 #ifdef USE_AUTOCRYPT
1234 #endif
1235  // TEST43: neomutt (no change to mailbox)
1236  // TEST44: neomutt (change mailbox)
1237  }
1238 
1239 main_ok:
1240  rc = 0;
1241 main_curses:
1242  mutt_endwin();
1244  /* Repeat the last message to the user */
1245  if (repeat_error && ErrorBufMessage)
1246  puts(ErrorBuf);
1247 main_exit:
1249  mutt_buffer_dealloc(&folder);
1250  mutt_buffer_dealloc(&expanded_infile);
1251  mutt_buffer_dealloc(&tempfile);
1252  mutt_list_free(&queries);
1259  crypt_cleanup();
1260  mutt_opts_free();
1261  mutt_keys_free();
1263  mutt_prex_free();
1265  cs_free(&cs);
1267  log_queue_empty();
1268  mutt_log_stop();
1269  return rc;
1270 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
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:52
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition: autocrypt.c:93
The "current" mailbox.
Definition: context.h:37
struct ConfigSet * init_config(size_t size)
Initialise the config system.
Definition: init.c:1550
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:227
#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
#define CSR_RESULT(x)
Definition: set.h:52
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:2344
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:319
void mutt_browser_cleanup(void)
Clean up working Buffers.
Definition: browser.c:117
&#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:1182
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
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:597
#define mutt_message(...)
Definition: logging.h:83
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.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:55
void dialog_pop(void)
Hide a Window from the user.
Definition: mutt_window.c:750
void mutt_window_free_all(void)
Free all the default Windows.
Definition: mutt_window.c:283
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:916
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1071
struct MuttWindow * mutt_window_find(struct MuttWindow *root, enum WindowType type)
Find a Window of a given type.
Definition: mutt_window.c:692
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:450
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 dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: mutt_window.c:720
struct Body * content
List of MIME parts.
Definition: email.h:90
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:43
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
static void log_translation(void)
Log the translation being used.
Definition: main.c:332
#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:267
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:114
char * C_NewsServer
Config: (nntp) Url of the news server.
Definition: config.c:41
Log informational message.
Definition: logging.h:39
WHERE char ErrorBuf[256]
Copy of the last error message.
Definition: mutt_globals.h:46
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:55
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
incoming folders completion routine
Definition: mutt_mailbox.c:323
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1231
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:357
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:227
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:45
struct NntpAccountData * nntp_select_server(struct Mailbox *m, char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1008
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:47
void imap_logout_all(void)
close all open connections
Definition: imap.c:537
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:50
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:996
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:151
#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:53
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
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:460
int mutt_query_variables(struct ListHead *queries)
Implement the -Q command line flag.
Definition: init.c:1072
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:835
static bool get_user_info(struct ConfigSet *cs)
Find the user&#39;s name, home and shell.
Definition: main.c:291
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:377
int mx_check_empty(const char *path)
Is the mailbox empty.
Definition: mx.c:1241
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:1235
bool mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1574
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
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:1739
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:1080
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
WHERE bool C_ReadOnly
Config: Open folders in read-only mode.
Definition: mutt_globals.h:156
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
static int start_curses(void)
Start the curses or slang UI.
Definition: main.c:218
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: multipart.c:99
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
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:826
int mutt_reply_observer(struct NotifyCallback *nc)
Listen for config changes to "reply_regex" - Implements observer_t.
Definition: index.c:4006
Side panel containing Accounts or groups of data.
Definition: mutt_window.h:98
void log_queue_set_max_size(int size)
Set a upper limit for the queue length.
Definition: logging.c:323
bool C_ImapPassive
Config: (imap) Reuse an existing IMAP connection to check for new mail.
Definition: config.c:51
void mutt_window_set_root(int cols, int rows)
Set the dimensions of the Root Window.
Definition: mutt_window.c:620
int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: init.c:743
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:569
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:128
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1644
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:153
#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:2828
int mutt_abort_key_config_observer(struct NotifyCallback *nc)
Listen for abort_key config changes - Implements observer_t.
Definition: keymap.c:847
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:335
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:99
Not object-related, NotifyGlobal.
Definition: notify_type.h:39
WHERE bool C_Autoedit
Config: Skip the initial compose menu and edit the email.
Definition: mutt_globals.h:140
void myvar_set(const char *var, const char *val)
Set the value of a "my_" variable.
Definition: myvar.c:91
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:177
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
bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition: dump.c:154
Definition: color.h:129
int mutt_index_menu(struct MuttWindow *dlg)
Display a list of emails.
Definition: index.c:1173
void mutt_opts_free(void)
clean up before quitting
Definition: init.c:659
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:1375
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:153
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:56
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition: set.c:172
#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:83
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:395
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:45
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:99
struct Connection * conn
Definition: lib.h:102
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:1297
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:111
NeoMutt is initialised.
Definition: neomutt.h:50
static void usage(void)
Display NeoMutt command line.
Definition: main.c:147
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:451
void mutt_prex_free(void)
Cleanup heap memory allocated by compiled regexes.
Definition: prex.c:347
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:94
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:747
#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:263
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:55
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:106
#define FREE(x)
Definition: memory.h:40
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:1923
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:4138
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
void mutt_commands_cleanup(void)
Clean up commands globals.
Definition: commands.c:100
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:186
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
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:4121
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:49
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:45
#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:409
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:41
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:323
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the master 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:1444
#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:290
static const char clear[]
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:652
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
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, int linelen, bool display)
Wrapper for mutt_write_address()
Definition: address.c:1226
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
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:739
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:137
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.