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

Command line processing. More...

#include "config.h"
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "index/lib.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include "alternates.h"
#include "attachments.h"
#include "browser.h"
#include "commands.h"
#include "context.h"
#include "hook.h"
#include "init.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_globals.h"
#include "mutt_history.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "myvar.h"
#include "options.h"
#include "protos.h"
#include "subjectrx.h"
#include "version.h"
#include <libintl.h>
#include "imap/lib.h"
#include "pop/lib.h"
#include "nntp/lib.h"
#include "nntp/adata.h"
#include "nntp/mdata.h"
#include "autocrypt/lib.h"

Go to the source code of this file.

Macros

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

Typedefs

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

Functions

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

Detailed Description

Command line processing.

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

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

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

Definition in file main.c.

Macro Definition Documentation

◆ MAIN_C

#define MAIN_C   1

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

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

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

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 107 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

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

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 102 of file main.c.

Function Documentation

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 118 of file main.c.

119 {
120  static const char *names[] = { "folder", "mbox", "postponed", "record" };
121 
122  struct Buffer value = mutt_buffer_make(256);
123  for (size_t i = 0; i < mutt_array_size(names); i++)
124  {
125  struct HashElem *he = cs_get_elem(cs, names[i]);
126  if (!he)
127  continue;
128  mutt_buffer_reset(&value);
129  cs_he_initial_get(cs, he, &value);
130  mutt_buffer_expand_path_regex(&value, false);
131  cs_he_initial_set(cs, he, value.data, NULL);
132  cs_he_reset(cs, he, NULL);
133  }
134  mutt_buffer_dealloc(&value);
135 }
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:133
int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:346
#define mutt_array_size(x)
Definition: memory.h:33
int cs_he_initial_set(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:416
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition: set.c:484
char * data
Pointer to data.
Definition: buffer.h:35
The item stored in a Hash Table.
Definition: hash.h:43
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_exit()

void mutt_exit ( int  code)

Leave NeoMutt NOW.

Parameters
codeValue to return to the calling environment

Definition at line 141 of file main.c.

142 {
143  mutt_endwin();
144 #ifdef HAVE_LIBUNWIND
145  if (code != 0)
146  show_backtrace();
147 #endif
148  exit(code);
149 }
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
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 155 of file main.c.

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

◆ start_curses()

static int start_curses ( void  )
static

Start the curses or slang UI.

Return values
0Success
1Failure

Definition at line 228 of file main.c.

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

274 {
275  setlocale(LC_ALL, "");
276 
277 #ifdef ENABLE_NLS
278  const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
279  if (domdir)
280  bindtextdomain(PACKAGE, domdir);
281  else
282  bindtextdomain(PACKAGE, MUTTLOCALEDIR);
283  textdomain(PACKAGE);
284 #endif
285 #ifndef LOCALES_HACK
286  /* Do we have a locale definition? */
287  if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
288  {
289  OptLocales = true;
290  }
291 #endif
292 }
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:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_user_info()

static bool get_user_info ( struct ConfigSet cs)
static

Find the user's name, home and shell.

Parameters
csConfig Set
Return values
trueSuccess

Find the login name, real name, home directory and shell.

Definition at line 301 of file main.c.

302 {
303  const char *shell = mutt_str_getenv("SHELL");
304  if (shell)
305  cs_str_initial_set(cs, "shell", shell, NULL);
306 
307  /* Get some information about the user */
308  struct passwd *pw = getpwuid(getuid());
309  if (pw)
310  {
311  if (!Username)
312  Username = mutt_str_dup(pw->pw_name);
313  if (!HomeDir)
314  HomeDir = mutt_str_dup(pw->pw_dir);
315  if (!shell)
316  cs_str_initial_set(cs, "shell", pw->pw_shell, NULL);
317  }
318 
319  if (!Username)
320  {
321  mutt_error(_("unable to determine username"));
322  return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
323  }
324 
325  if (!HomeDir)
326  {
327  mutt_error(_("unable to determine home directory"));
328  return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
329  }
330 
331  cs_str_reset(cs, "shell", NULL);
332  return true;
333 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:458
#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:393
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_translation()

static void log_translation ( void  )
static

Log the translation being used.

Read the header info from the translation file.

Note
Call bindtextdomain() first

Definition at line 342 of file main.c.

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

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