NeoMutt  2025-09-05-70-gcfdde0
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
main.c File Reference

Command line processing. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <time.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 "mutt.h"
#include "attach/lib.h"
#include "browser/lib.h"
#include "cli/lib.h"
#include "color/lib.h"
#include "compmbox/lib.h"
#include "history/lib.h"
#include "imap/lib.h"
#include "index/lib.h"
#include "key/lib.h"
#include "lua/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "nntp/lib.h"
#include "notmuch/lib.h"
#include "parse/lib.h"
#include "pop/lib.h"
#include "postpone/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "sidebar/lib.h"
#include "alternates.h"
#include "commands.h"
#include "external.h"
#include "globals.h"
#include "hook.h"
#include "mutt_logging.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "nntp/adata.h"
#include "protos.h"
#include "subjectrx.h"
#include "version.h"
#include <libintl.h>
#include "autocrypt/lib.h"

Go to the source code of this file.

Macros

#define GNULIB_defined_setlocale
 

Functions

void show_cli (enum HelpMode mode, bool use_color)
 Show Instructions on how to run NeoMutt.
 
static int execute_commands (struct StringArray *sa)
 Execute a set of NeoMutt commands.
 
static char * find_cfg (const char *home, const char *xdg_cfg_home)
 Find a config file.
 
static char * getmailname (void)
 Try to retrieve the FQDN from mailname files.
 
static bool get_hostname (struct ConfigSet *cs)
 Find the Fully-Qualified Domain Name.
 
static int mutt_init (struct ConfigSet *cs, struct Buffer *dlevel, struct Buffer *dfile, bool skip_sys_rc, struct StringArray *user_files, struct StringArray *commands)
 Initialise NeoMutt.
 
static int get_elem_queries (struct StringArray *queries, struct HashElemArray *hea)
 Lookup the HashElems for a set of queries.
 
static void reset_tilde (struct ConfigSet *cs)
 Temporary measure.
 
static void localise_config (struct ConfigSet *cs)
 Localise some config.
 
static int start_curses (void)
 Start the Curses UI.
 
static void init_locale (void)
 Initialise the Locale/NLS settings.
 
static bool get_user_info (struct ConfigSet *cs)
 Find the user's name, home and shell.
 
static void log_translation (void)
 Log the translation being used.
 
static void log_gui (void)
 Log info about the GUI.
 
static int main_timeout_observer (struct NotifyCallback *nc)
 Notification that a timeout has occurred - Implements observer_t -.
 
static bool show_help (struct CliHelp *help)
 Show the Help.
 
static bool init_logging (struct CliShared *shared, struct ConfigSet *cs)
 Initialise the Logging.
 
static void init_nntp (struct Buffer *server, struct ConfigSet *cs)
 Initialise the NNTP config.
 
static bool dump_info (struct CliInfo *ci, struct ConfigSet *cs)
 Show config info.
 
int main (int argc, char *argv[], char *envp[])
 Start NeoMutt.
 

Variables

bool StartupComplete = false
 When the config has been read.
 

Detailed Description

Command line processing.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • g10 Code GmbH
  • Richard Russon
  • Pietro Cerutti
  • R Primus
  • Dennis Schön
  • Alejandro Colomar

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

◆ GNULIB_defined_setlocale

#define GNULIB_defined_setlocale

Definition at line 127 of file main.c.

Function Documentation

◆ show_cli()

void show_cli ( enum HelpMode mode,
bool use_color )

Show Instructions on how to run NeoMutt.

Parameters
modeDetails, e.g. HM_SHARED
use_colorHighlight parts of the text

Definition at line 332 of file usage.c.

333{
334 if (use_color)
335 printf("\033[38;5;255m%s\033[0m\n\n", mutt_make_version());
336 else
337 printf("%s\n\n", mutt_make_version());
338
339 switch (mode)
340 {
341 case HM_NONE:
342 {
343 show_cli_overview(use_color);
344 break;
345 }
346 case HM_SHARED:
347 {
348 show_cli_shared(use_color);
349 break;
350 }
351 case HM_HELP:
352 {
353 show_cli_help(use_color);
354 break;
355 }
356 case HM_INFO:
357 {
358 show_cli_info(use_color);
359 break;
360 }
361 case HM_SEND:
362 {
363 show_cli_send(use_color);
364 break;
365 }
366 case HM_TUI:
367 {
368 show_cli_tui(use_color);
369 break;
370 }
371 case HM_ALL:
372 {
373 printf("------------------------------------------------------------\n");
374 show_cli_shared(use_color);
375 printf("\n------------------------------------------------------------\n");
376 show_cli_help(use_color);
377 printf("\n------------------------------------------------------------\n");
378 show_cli_info(use_color);
379 printf("\n------------------------------------------------------------\n");
380 show_cli_send(use_color);
381 printf("\n------------------------------------------------------------\n");
382 show_cli_tui(use_color);
383 printf("\n------------------------------------------------------------\n");
384 break;
385 }
386 }
387}
@ HM_SEND
Help about sending email options.
Definition objects.h:38
@ HM_ALL
Help about all options.
Definition objects.h:40
@ HM_HELP
Help about help.
Definition objects.h:36
@ HM_INFO
Help about info options.
Definition objects.h:37
@ HM_TUI
Help about starting the tui options.
Definition objects.h:39
@ HM_NONE
No extra help.
Definition objects.h:34
@ HM_SHARED
Help about shared config options.
Definition objects.h:35
static void show_cli_tui(bool use_color)
Show Command Line Help for Tui.
Definition usage.c:290
static void show_cli_shared(bool use_color)
Show Command Line Help for Shared.
Definition usage.c:124
static void show_cli_info(bool use_color)
Show Command Line Help for Info.
Definition usage.c:207
static void show_cli_overview(bool use_color)
Display NeoMutt command line.
Definition usage.c:54
static void show_cli_help(bool use_color)
Show Command Line Help for Help.
Definition usage.c:180
static void show_cli_send(bool use_color)
Show Command Line Help for Send.
Definition usage.c:246
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition version.c:295
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ execute_commands()

static int execute_commands ( struct StringArray * sa)
static

Execute a set of NeoMutt commands.

Parameters
saArray of command strings
Return values
0Success, all the commands succeeded
-1Error

Definition at line 206 of file main.c.

207{
208 int rc = 0;
209 struct Buffer *err = buf_pool_get();
210
211 const char **cp = NULL;
212 ARRAY_FOREACH(cp, sa)
213 {
214 enum CommandResult rc2 = parse_rc_line(*cp, err);
215 if (rc2 == MUTT_CMD_ERROR)
216 mutt_error(_("Error in command line: %s"), buf_string(err));
217 else if (rc2 == MUTT_CMD_WARNING)
218 mutt_warning(_("Warning in command line: %s"), buf_string(err));
219
220 if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
221 {
222 buf_pool_release(&err);
223 return -1;
224 }
225 }
226 buf_pool_release(&err);
227
228 return rc;
229}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
CommandResult
Error codes for command_t parse functions.
Definition command.h:35
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:36
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:37
#define mutt_warning(...)
Definition logging2.h:91
#define mutt_error(...)
Definition logging2.h:93
#define _(a)
Definition message.h:28
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
enum CommandResult parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition rc.c:109
String manipulation buffer.
Definition buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_cfg()

static char * find_cfg ( const char * home,
const char * xdg_cfg_home )
static

Find a config file.

Parameters
homeUser's home directory
xdg_cfg_homeXDG home directory
Return values
ptrSuccess, first matching directory
NULLError, no matching directories

Definition at line 238 of file main.c.

239{
240 const char *names[] = {
241 "neomuttrc",
242 "muttrc",
243 NULL,
244 };
245
246 const char *locations[][2] = {
247 { xdg_cfg_home, "neomutt/" },
248 { xdg_cfg_home, "mutt/" },
249 { home, ".neomutt/" },
250 { home, ".mutt/" },
251 { home, "." },
252 { NULL, NULL },
253 };
254
255 struct Buffer *buf = buf_pool_get();
256 char *cfg = NULL;
257
258 for (int i = 0; locations[i][0] || locations[i][1]; i++)
259 {
260 if (!locations[i][0])
261 continue;
262
263 for (int j = 0; names[j]; j++)
264 {
265 buf_printf(buf, "%s/%s%s", locations[i][0], locations[i][1], names[j]);
266 if (access(buf_string(buf), F_OK) == 0)
267 {
268 cfg = buf_strdup(buf);
269 goto done;
270 }
271 }
272 }
273
274done:
275 buf_pool_release(&buf);
276 return cfg;
277}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getmailname()

static char * getmailname ( void )
static

Try to retrieve the FQDN from mailname files.

Return values
ptrHeap allocated string with the FQDN
NULLNo valid mailname file could be read

Definition at line 285 of file main.c.

286{
287 char *mailname = NULL;
288 static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
289
290 for (size_t i = 0; i < countof(mn_files); i++)
291 {
292 FILE *fp = mutt_file_fopen(mn_files[i], "r");
293 if (!fp)
294 continue;
295
296 size_t len = 0;
297 mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
298 mutt_file_fclose(&fp);
299 if (mailname && *mailname)
300 break;
301
302 FREE(&mailname);
303 }
304
305 return mailname;
306}
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition file.c:685
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
#define countof(x)
Definition memory.h:44
#define FREE(x)
Definition memory.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_hostname()

static bool get_hostname ( struct ConfigSet * cs)
static

Find the Fully-Qualified Domain Name.

Parameters
csConfig Set
Return values
trueSuccess
falseError, failed to find any name

Use several methods to try to find the Fully-Qualified domain name of this host. If the user has already configured a hostname, this function will use it.

Definition at line 318 of file main.c.

319{
320 const char *short_host = NULL;
321 struct utsname utsname = { 0 };
322
323 const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
324 if (c_hostname)
325 {
326 short_host = c_hostname;
327 }
328 else
329 {
330 /* The call to uname() shouldn't fail, but if it does, the system is horribly
331 * broken, and the system's networking configuration is in an unreliable
332 * state. We should bail. */
333 if ((uname(&utsname)) == -1)
334 {
335 mutt_perror(_("unable to determine nodename via uname()"));
336 return false; // TEST09: can't test
337 }
338
339 short_host = utsname.nodename;
340 }
341
342 /* some systems report the FQDN instead of just the hostname */
343 char *dot = strchr(short_host, '.');
344 if (dot)
345 ShortHostname = mutt_strn_dup(short_host, dot - short_host);
346 else
347 ShortHostname = mutt_str_dup(short_host);
348
349 // All the code paths from here alloc memory for the fqdn
350 char *fqdn = mutt_str_dup(c_hostname);
351 if (!fqdn)
352 {
353 mutt_debug(LL_DEBUG1, "Setting $hostname\n");
354 /* now get FQDN. Use configured domain first, DNS next, then uname */
355#ifdef DOMAIN
356 /* we have a compile-time domain name, use that for `$hostname` */
357 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
358#else
359 fqdn = getmailname();
360 if (!fqdn)
361 {
362 struct Buffer *domain = buf_pool_get();
363 if (getdnsdomainname(domain) == 0)
364 {
365 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), buf_string(domain));
366 }
367 else
368 {
369 /* DNS failed, use the nodename. Whether or not the nodename had a '.'
370 * in it, we can use the nodename as the FQDN. On hosts where DNS is
371 * not being used, e.g. small network that relies on hosts files, a
372 * short host name is all that is required for SMTP to work correctly.
373 * It could be wrong, but we've done the best we can, at this point the
374 * onus is on the user to provide the correct hostname if the nodename
375 * won't work in their network. */
376 fqdn = mutt_str_dup(utsname.nodename);
377 }
378 buf_pool_release(&domain);
379 mutt_debug(LL_DEBUG1, "Hostname: %s\n", NONULL(fqdn));
380 }
381#endif
382 }
383
384 if (fqdn)
385 {
386 config_str_set_initial(cs, "hostname", fqdn);
387 FREE(&fqdn);
388 }
389
390 return true;
391}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool config_str_set_initial(struct ConfigSet *cs, const char *name, const char *value)
Set the initial value of a Config Option.
Definition helpers.c:332
int getdnsdomainname(struct Buffer *result)
Lookup the host's name using DNS.
Definition getdomain.c:124
char * ShortHostname
Short version of the hostname.
Definition globals.c:37
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
#define mutt_perror(...)
Definition logging2.h:94
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:44
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition main.c:285
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:382
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:803
#define NONULL(x)
Definition string2.h:43
Container for Accounts, Notifications.
Definition neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_init()

static int mutt_init ( struct ConfigSet * cs,
struct Buffer * dlevel,
struct Buffer * dfile,
bool skip_sys_rc,
struct StringArray * user_files,
struct StringArray * commands )
static

Initialise NeoMutt.

Parameters
csConfig Set
dlevelCommand line debug level
dfileCommand line debug file
skip_sys_rcIf true, don't read the system config file
user_filesArray of user config files
commandsArray of config commands to execute
Return values
0Success
1Error

Definition at line 404 of file main.c.

407{
408 bool need_pause = false;
409 int rc = 1;
410 struct Buffer *err = buf_pool_get();
411 struct Buffer *buf = buf_pool_get();
412 const char **cp = NULL;
413
414#ifdef NEOMUTT_DIRECT_COLORS
415 /* Test if we run in a terminal which supports direct colours.
416 *
417 * The user/terminal can indicate their capability independent of the
418 * terminfo file by setting the COLORTERM environment variable to "truecolor"
419 * or "24bit" (case sensitive).
420 *
421 * Note: This is to test is less about whether the terminal understands
422 * direct color commands but more about whether ncurses believes it can send
423 * them to the terminal, e.g. ncurses ignores COLORTERM.
424 */
425 if (COLORS == 16777216) // 2^24
426 {
427 /* Ncurses believes the Terminal supports it check the environment variable
428 * to respect the user's choice */
429 const char *env_colorterm = mutt_str_getenv("COLORTERM");
430 if (env_colorterm && (mutt_str_equal(env_colorterm, "truecolor") ||
431 mutt_str_equal(env_colorterm, "24bit")))
432 {
433 config_str_set_initial(cs, "color_directcolor", "yes");
434 }
435 }
436#endif
437
438 /* "$spool_file" precedence: config file, environment */
439 const char *p = mutt_str_getenv("MAIL");
440 if (!p)
441 p = mutt_str_getenv("MAILDIR");
442 if (!p)
443 {
444#ifdef HOMESPOOL
445 buf_concat_path(buf, NONULL(NeoMutt->home_dir), MAILPATH);
446#else
447 buf_concat_path(buf, MAILPATH, NONULL(NeoMutt->username));
448#endif
449 p = buf_string(buf);
450 }
451 config_str_set_initial(cs, "spool_file", p);
452
453 p = mutt_str_getenv("REPLYTO");
454 if (p)
455 {
456 struct Buffer *token = buf_pool_get();
457
458 buf_printf(buf, "Reply-To: %s", p);
459 buf_seek(buf, 0);
460 parse_my_hdr(token, buf, 0, err); /* adds to UserHeader */
461 buf_pool_release(&token);
462 }
463
464 p = mutt_str_getenv("EMAIL");
465 if (p)
466 config_str_set_initial(cs, "from", p);
467
468 /* "$mailcap_path" precedence: config file, environment, code */
469 struct Buffer *mc = buf_pool_get();
470 struct Slist *sl_mc = NULL;
471 const char *env_mc = mutt_str_getenv("MAILCAPS");
472 if (env_mc)
473 {
474 sl_mc = slist_parse(env_mc, D_SLIST_SEP_COLON);
475 }
476 else
477 {
478 cs_str_initial_get(cs, "mailcap_path", mc);
480 buf_reset(mc);
481 }
482 slist_to_buffer(sl_mc, mc);
483 config_str_set_initial(cs, "mailcap_path", buf_string(mc));
484 slist_free(&sl_mc);
485 buf_pool_release(&mc);
486
487 /* "$tmp_dir" precedence: config file, environment, code */
488 const char *env_tmp = mutt_str_getenv("TMPDIR");
489 if (env_tmp)
490 config_str_set_initial(cs, "tmp_dir", env_tmp);
491
492 /* "$visual", "$editor" precedence: config file, environment, code */
493 const char *env_ed = mutt_str_getenv("VISUAL");
494 if (!env_ed)
495 env_ed = mutt_str_getenv("EDITOR");
496 if (!env_ed)
497 env_ed = "vi";
498 config_str_set_initial(cs, "editor", env_ed);
499
500 const char *charset = mutt_ch_get_langinfo_charset();
501 config_str_set_initial(cs, "charset", charset);
502 mutt_ch_set_charset(charset);
503 FREE(&charset);
504
505 char name[256] = { 0 };
506 const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
507 if (!c_real_name)
508 {
509 struct passwd *pw = getpwuid(getuid());
510 if (pw)
511 {
512 c_real_name = mutt_gecos_name(name, sizeof(name), pw);
513 }
514 }
515 config_str_set_initial(cs, "real_name", c_real_name);
516
517#ifdef HAVE_GETSID
518 /* Unset suspend by default if we're the session leader */
519 if (getsid(0) == getpid())
520 config_str_set_initial(cs, "suspend", "no");
521#endif
522
523 /* RFC2368, "4. Unsafe headers"
524 * The creator of a mailto URL can't expect the resolver of a URL to
525 * understand more than the "subject" and "body" headers. Clients that
526 * resolve mailto URLs into mail messages should be able to correctly
527 * create RFC822-compliant mail messages using the "subject" and "body"
528 * headers. */
529 add_to_stailq(&MailToAllow, "body");
530 add_to_stailq(&MailToAllow, "subject");
531 /* Cc, In-Reply-To, and References help with not breaking threading on
532 * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
534 add_to_stailq(&MailToAllow, "in-reply-to");
535 add_to_stailq(&MailToAllow, "references");
536
537 if (ARRAY_EMPTY(user_files))
538 {
539 const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
540
541 if (!xdg_cfg_home && NeoMutt->home_dir)
542 {
543 buf_printf(buf, "%s/.config", NeoMutt->home_dir);
544 xdg_cfg_home = buf_string(buf);
545 }
546
547 char *config = find_cfg(NeoMutt->home_dir, xdg_cfg_home);
548 if (config)
549 {
550 ARRAY_ADD(user_files, config);
551 }
552 }
553 else
554 {
555 ARRAY_FOREACH(cp, user_files)
556 {
557 buf_strcpy(buf, *cp);
558 FREE(cp);
559 buf_expand_path(buf);
560 ARRAY_SET(user_files, ARRAY_FOREACH_IDX_cp, buf_strdup(buf));
561 if (access(buf_string(buf), F_OK))
562 {
563 mutt_perror("%s", buf_string(buf));
564 goto done; // TEST10: neomutt -F missing
565 }
566 }
567 }
568
569 ARRAY_FOREACH(cp, user_files)
570 {
571 if (*cp && !mutt_str_equal(*cp, "/dev/null"))
572 {
573 cs_str_string_set(cs, "alias_file", *cp, NULL);
574 break;
575 }
576 }
577
578 /* Process the global rc file if it exists and the user hasn't explicitly
579 * requested not to via "-n". */
580 if (!skip_sys_rc)
581 {
582 do
583 {
585 break;
586
587 buf_printf(buf, "%s/neomuttrc", SYSCONFDIR);
588 if (access(buf_string(buf), F_OK) == 0)
589 break;
590
591 buf_printf(buf, "%s/Muttrc", SYSCONFDIR);
592 if (access(buf_string(buf), F_OK) == 0)
593 break;
594
595 buf_printf(buf, "%s/neomuttrc", PKGDATADIR);
596 if (access(buf_string(buf), F_OK) == 0)
597 break;
598
599 buf_printf(buf, "%s/Muttrc", PKGDATADIR);
600 } while (false);
601
602 if (access(buf_string(buf), F_OK) == 0)
603 {
604 if (source_rc(buf_string(buf), err) != 0)
605 {
606 mutt_error("%s", buf_string(err));
607 need_pause = true; // TEST11: neomutt (error in /etc/neomuttrc)
608 }
609 }
610 }
611
612 /* Read the user's initialization file. */
613 ARRAY_FOREACH(cp, user_files)
614 {
615 if (*cp)
616 {
617 if (source_rc(*cp, err) != 0)
618 {
619 mutt_error("%s", buf_string(err));
620 need_pause = true; // TEST12: neomutt (error in ~/.neomuttrc)
621 }
622 }
623 }
624
625 if (execute_commands(commands) != 0)
626 need_pause = true; // TEST13: neomutt -e broken
627
628 if (!get_hostname(cs))
629 goto done;
630
631 /* The command line overrides the config */
632 if (!buf_is_empty(dlevel))
633 cs_str_reset(cs, "debug_level", NULL);
634 if (!buf_is_empty(dfile))
635 cs_str_reset(cs, "debug_file", NULL);
636
637 if (mutt_log_start() < 0)
638 {
639 mutt_perror("log file");
640 goto done;
641 }
642
643 if (need_pause && OptGui)
644 {
646 if (mutt_any_key_to_continue(NULL) == 'q')
647 goto done; // TEST14: neomutt -e broken (press 'q')
648 }
649
650 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
651 if (mutt_file_mkdir(c_tmp_dir, S_IRWXU) < 0)
652 {
653 mutt_error(_("Can't create %s: %s"), c_tmp_dir, strerror(errno));
654 goto done;
655 }
656
657 rc = 0;
658
659done:
660 buf_pool_release(&err);
661 buf_pool_release(&buf);
662 return rc;
663}
#define ARRAY_SET(head, idx, elem)
Set an element in the array.
Definition array.h:123
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:156
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition buffer.c:622
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:509
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
Definition commands.c:219
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
int cs_str_initial_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
Get the initial, or parent, value of a config item.
Definition set.c:593
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:446
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:668
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
struct ListHead MailToAllow
List of regexes to identify non-spam emails.
Definition globals.c:42
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition file.c:851
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:59
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
Definition commands.c:849
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition logging.c:421
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition main.c:238
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition main.c:318
static int execute_commands(struct StringArray *sa)
Execute a set of NeoMutt commands.
Definition main.c:206
char * mutt_ch_get_langinfo_charset(void)
Get the user's choice of character set.
Definition charset.c:486
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition charset.c:1075
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition logging.c:347
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition slist.c:177
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition slist.c:124
int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
Export an Slist to a Buffer.
Definition slist.c:269
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition string.c:726
int mutt_log_start(void)
Enable file logging.
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition muttlib.c:331
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition muttlib.c:1038
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition muttlib.c:882
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition muttlib.c:314
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition protos.h:46
char * username
User's login name.
Definition neomutt.h:53
char * home_dir
User's home directory.
Definition neomutt.h:52
String list.
Definition slist.h:37
#define D_SLIST_SEP_COLON
Slist items are colon-separated.
Definition types.h:111
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_elem_queries()

static int get_elem_queries ( struct StringArray * queries,
struct HashElemArray * hea )
static

Lookup the HashElems for a set of queries.

Parameters
[in]queriesArray of query strings
[out]heaArray for Config HashElems
Return values
0Success, all queries exist
1Error

Definition at line 672 of file main.c.

673{
674 int rc = 0;
675 const char **cp = NULL;
676 ARRAY_FOREACH(cp, queries)
677 {
678 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, *cp);
679 if (!he)
680 {
681 mutt_warning(_("Unknown option %s"), *cp);
682 rc = 1;
683 continue;
684 }
685
686 if (he->type & D_INTERNAL_DEPRECATED)
687 {
688 mutt_warning(_("Option %s is deprecated"), *cp);
689 rc = 1;
690 continue;
691 }
692
693 ARRAY_ADD(hea, he);
694 }
695
696 return rc; // TEST16: neomutt -Q charset
697}
The item stored in a Hash Table.
Definition hash.h:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition hash.h:45
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition subset.c:193
#define D_INTERNAL_DEPRECATED
Config item shouldn't be used any more.
Definition types.h:87
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reset_tilde()

static void reset_tilde ( struct ConfigSet * cs)
static

Temporary measure.

Parameters
csConfig Set

Definition at line 703 of file main.c.

704{
705 static const char *names[] = { "folder", "mbox", "postponed", "record" };
706
707 struct Buffer *value = buf_pool_get();
708 for (size_t i = 0; i < countof(names); i++)
709 {
710 struct HashElem *he = cs_get_elem(cs, names[i]);
711 if (!he)
712 continue;
713 buf_reset(value);
714 cs_he_initial_get(cs, he, value);
715 buf_expand_path_regex(value, false);
716 config_he_set_initial(cs, he, value->data);
717 }
718 buf_pool_release(&value);
719}
bool config_he_set_initial(struct ConfigSet *cs, struct HashElem *he, const char *value)
Set the initial value of a Config Option.
Definition helpers.c:312
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition set.c:175
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:557
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition muttlib.c:121
char * data
Pointer to data.
Definition buffer.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ localise_config()

static void localise_config ( struct ConfigSet * cs)
static

Localise some config.

Parameters
csConfig Set

Definition at line 726 of file main.c.

727{
728 struct Buffer *value = buf_pool_get();
729 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
730 struct HashElem **hep = NULL;
731
732 ARRAY_FOREACH(hep, &hea)
733 {
734 struct HashElem *he = *hep;
735 if (!(he->type & D_L10N_STRING))
736 continue;
737
738 buf_reset(value);
739 cs_he_initial_get(cs, he, value);
740
741 // Lookup the translation
742 const char *l10n = gettext(buf_string(value));
743 config_he_set_initial(cs, he, l10n);
744 }
745
746 ARRAY_FREE(&hea);
747 buf_pool_release(&value);
748}
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:204
struct ConfigSet * cs
Parent ConfigSet.
Definition subset.h:50
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition subset.c:81
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition subset.h:81
#define D_L10N_STRING
String can be localised.
Definition types.h:81
+ 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 UI.

Return values
0Success
1Failure

Definition at line 756 of file main.c.

757{
758 /* should come before initscr() so that ncurses 4.2 doesn't try to install
759 * its own SIGWINCH handler */
761
762 if (!initscr())
763 {
764 mutt_error(_("Error initializing terminal"));
765 return 1;
766 }
767
768 colors_init();
769 keypad(stdscr, true);
770 cbreak();
771 noecho();
772 nonl();
773 typeahead(-1); /* simulate smooth scrolling */
774 meta(stdscr, true);
776 /* Now that curses is set up, we drop back to normal screen mode.
777 * This simplifies displaying error messages to the user.
778 * The first call to refresh() will swap us back to curses screen mode. */
779 endwin();
780 return 0;
781}
void colors_init(void)
Initialize colours.
Definition color.c:49
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition extended.c:113
void mutt_signal_init(void)
Initialise the signal handling.
int endwin(void)
+ 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 786 of file main.c.

787{
788 setlocale(LC_ALL, "");
789
790#ifdef ENABLE_NLS
791 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
792 if (domdir)
793 bindtextdomain(PACKAGE, domdir);
794 else
795 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
796 textdomain(PACKAGE);
797#endif
798#ifndef LOCALES_HACK
799 /* Do we have a locale definition? */
800 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
801 {
802 OptLocales = true;
803 }
804#endif
805}
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 814 of file main.c.

815{
816 const char *shell = mutt_str_getenv("SHELL");
817
818 /* Get some information about the user */
819 struct passwd *pw = getpwuid(getuid());
820 if (pw)
821 {
822 if (!NeoMutt->username)
823 NeoMutt->username = mutt_str_dup(pw->pw_name);
824 if (!NeoMutt->home_dir)
825 NeoMutt->home_dir = mutt_str_dup(pw->pw_dir);
826 if (!shell)
827 shell = pw->pw_shell;
828 }
829
830 if (!NeoMutt->username)
831 {
832 mutt_error(_("unable to determine username"));
833 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
834 }
835
836 if (!NeoMutt->home_dir)
837 {
838 mutt_error(_("unable to determine home directory"));
839 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
840 }
841
842 if (shell)
843 config_str_set_initial(cs, "shell", shell);
844
845 return true;
846}
+ 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 855 of file main.c.

856{
857 const char *header = ""; // Do not merge these two lines
858 header = _(header); // otherwise the .po files will end up badly ordered
859 const char *label = "Language:"; // the start of the lookup/needle
860 const char *lang = mutt_istr_find(header, label);
861 int len = 64;
862 if (lang)
863 {
864 lang += strlen(label); // skip label
865 SKIPWS(lang);
866 char *nl = strchr(lang, '\n');
867 if (nl)
868 len = (nl - lang);
869 }
870 else
871 {
872 lang = "NONE";
873 }
874
875 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
876}
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:523
#define SKIPWS(ch)
Definition string2.h:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_gui()

static void log_gui ( void )
static

Log info about the GUI.

Definition at line 881 of file main.c.

882{
883 const char *term = mutt_str_getenv("TERM");
884 const char *color_term = mutt_str_getenv("COLORTERM");
885 bool true_color = false;
886#ifdef NEOMUTT_DIRECT_COLORS
887 true_color = true;
888#endif
889
890 mutt_debug(LL_DEBUG1, "GUI:\n");
891 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
892 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
893 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
894 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
895 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
896 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
897 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
898 RootWindow->state.rows);
899}
struct MuttWindow * RootWindow
Parent of all Windows.
Definition rootwin.c:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ show_help()

static bool show_help ( struct CliHelp * help)
static

Show the Help.

Parameters
helpCommand Line Options
Return values
trueSuccess, continue

Definition at line 938 of file main.c.

939{
940 if (!help->is_set)
941 return true;
942
944
945 const bool tty = isatty(STDOUT_FILENO);
946
947 if (help->help)
948 {
949 show_cli(help->mode, tty);
950 }
951 else if (help->license)
952 {
954 }
955 else
956 {
957 print_version(stdout, tty);
958 }
959
960 return false; // Stop
961}
void show_cli(enum HelpMode mode, bool use_color)
Show Instructions on how to run NeoMutt.
Definition usage.c:332
bool license
-vv Print license
Definition objects.h:68
enum HelpMode mode
Display detailed help.
Definition objects.h:70
bool help
-h Print help
Definition objects.h:66
bool is_set
This struct has been used.
Definition objects.h:65
bool print_copyright(void)
Print copyright message.
Definition version.c:702
bool print_version(FILE *fp, bool use_ansi)
Print system and compile info to a file.
Definition version.c:591
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_logging()

static bool init_logging ( struct CliShared * shared,
struct ConfigSet * cs )
static

Initialise the Logging.

Parameters
sharedShared Command line Options
csConfig Set
Return values
trueSuccess

Definition at line 969 of file main.c.

970{
971 if (!shared->is_set)
972 return true;
973
974 if (!buf_is_empty(&shared->log_file))
975 config_str_set_initial(cs, "debug_file", buf_string(&shared->log_file));
976
977 if (!buf_is_empty(&shared->log_level))
978 {
979 const char *dlevel = buf_string(&shared->log_level);
980 short num = 0;
981 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
982 {
983 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
984 return false;
985 }
986
987 config_str_set_initial(cs, "debug_level", dlevel);
988 }
989
990 return true;
991}
@ LL_MESSAGE
Log informational message.
Definition logging2.h:43
@ LL_MAX
Definition logging2.h:51
struct Buffer log_level
-d Debug log level
Definition objects.h:56
struct Buffer log_file
-l Debug log file
Definition objects.h:57
bool is_set
This struct has been used.
Definition objects.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_nntp()

static void init_nntp ( struct Buffer * server,
struct ConfigSet * cs )
static

Initialise the NNTP config.

Parameters
serverNNTP Server to use
csConfig Set

Definition at line 998 of file main.c.

999{
1000 const char *cli_nntp = NULL;
1001 if (!buf_is_empty(server))
1002 cli_nntp = buf_string(server);
1003
1004 /* "$news_server" precedence: command line, config file, environment, system file */
1005 if (cli_nntp)
1006 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
1007
1008 if (!cli_nntp)
1009 cli_nntp = mutt_str_getenv("NNTPSERVER");
1010
1011 if (!cli_nntp)
1012 {
1013 char buf[1024] = { 0 };
1014 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
1015 }
1016
1017 if (cli_nntp)
1018 config_str_set_initial(cs, "news_server", cli_nntp);
1019}
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition file.c:1299
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dump_info()

static bool dump_info ( struct CliInfo * ci,
struct ConfigSet * cs )
static

Show config info.

Parameters
ciCommand line Options
csConfig Set
Return values
trueSuccess

Definition at line 1027 of file main.c.

1028{
1029 if (!ci->is_set)
1030 return true;
1031
1032 if (ci->dump_config || !ARRAY_EMPTY(&ci->queries))
1033 {
1034 const bool tty = isatty(STDOUT_FILENO);
1035
1037 if (tty)
1038 cdflags |= CS_DUMP_LINK_DOCS;
1039 if (ci->hide_sensitive)
1040 cdflags |= CS_DUMP_HIDE_SENSITIVE;
1041 if (ci->show_help)
1042 cdflags |= CS_DUMP_SHOW_DOCS;
1043
1044 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
1045 if (ci->dump_config)
1046 {
1048 hea = get_elem_list(cs, gel_flags);
1049 }
1050 else
1051 {
1052 get_elem_queries(&ci->queries, &hea);
1053 }
1054
1055 dump_config(cs, &hea, cdflags, stdout);
1056 ARRAY_FREE(&hea);
1057 }
1058 else if (!ARRAY_EMPTY(&ci->alias_queries))
1059 {
1060 const char **cp = NULL;
1062 {
1063 struct AddressList *al = alias_lookup(*cp);
1064 if (al)
1065 {
1066 /* output in machine-readable form */
1067 mutt_addrlist_to_intl(al, NULL);
1068 struct Buffer *buf = buf_pool_get();
1069 mutt_addrlist_write(al, buf, false);
1070 printf("%s\n", buf_string(buf));
1071 buf_pool_release(&buf);
1072 }
1073 else
1074 {
1075 printf("%s\n", NONULL(*cp)); // TEST19: neomutt -A unknown
1076 }
1077 }
1078 }
1079
1080 return false; // Stop
1081}
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1293
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:276
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
bool dump_config(struct ConfigSet *cs, struct HashElemArray *hea, ConfigDumpFlags flags, FILE *fp)
Write all the config to a file.
Definition dump.c:196
#define CS_DUMP_HIDE_SENSITIVE
Obscure sensitive information like passwords.
Definition dump.h:38
uint16_t ConfigDumpFlags
Flags for dump_config(), e.g. CS_DUMP_ONLY_CHANGED.
Definition dump.h:35
#define CS_DUMP_LINK_DOCS
Link to the online docs.
Definition dump.h:47
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition dump.h:36
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition dump.h:46
static int get_elem_queries(struct StringArray *queries, struct HashElemArray *hea)
Lookup the HashElems for a set of queries.
Definition main.c:672
bool show_help
-O Show one-liner help
Definition objects.h:81
bool is_set
This struct has been used.
Definition objects.h:78
struct StringArray queries
-Q Query a config option
Definition objects.h:85
struct StringArray alias_queries
-A Lookup an alias
Definition objects.h:84
bool dump_config
-D Dump the config
Definition objects.h:79
bool dump_changed
-DD Dump the changed config
Definition objects.h:80
bool hide_sensitive
-S Hide sensitive config
Definition objects.h:82
GetElemListFlags
Flags for get_elem_list()
Definition subset.h:80
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition subset.h:82
+ Here is the call graph for this function:
+ 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 1091 of file main.c.

1092{
1093 struct Email *e = NULL;
1094 SendFlags sendflags = SEND_NO_FLAGS;
1095 int rc = 1;
1096 bool repeat_error = false;
1097 struct Buffer *expanded_infile = buf_pool_get();
1098 struct Buffer *tempfile = buf_pool_get();
1099 struct ConfigSet *cs = NULL;
1100 struct CommandLine *cli = command_line_new();
1101
1103
1104 /* sanity check against stupid administrators */
1105 if (getegid() != getgid())
1106 {
1107 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
1108 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
1109 }
1110
1111 init_locale();
1112 OptGui = true;
1113
1114 cs = cs_new(500);
1115 if (!cs)
1116 goto main_curses;
1117
1118 NeoMutt = neomutt_new(cs);
1119
1120 NeoMutt->env = envlist_init(envp);
1123
1124 init_config(cs);
1125
1126 cli_parse(argc, argv, cli);
1127
1128 if (!show_help(&cli->help))
1129 goto main_ok;
1130
1131 // Change the current umask, and save the original one
1132 NeoMutt->user_default_umask = umask(077);
1133 subjrx_init();
1134 attach_init();
1136
1137#ifdef USE_DEBUG_NOTIFY
1139#endif
1140
1141 if (!get_user_info(cs))
1142 goto main_exit;
1143
1144 reset_tilde(cs);
1145#ifdef ENABLE_NLS
1146 localise_config(cs);
1147#endif
1148
1149 if (!init_logging(&cli->shared, cs))
1150 goto main_exit;
1151
1152 mutt_log_prep();
1155 mutt_debug(LL_DEBUG1, "user's umask %03o\n", NeoMutt->user_default_umask);
1156 mutt_debug(LL_DEBUG3, "umask set to 077\n");
1157
1158 /* Check for a batch send. */
1159 if (!isatty(STDIN_FILENO) || !ARRAY_EMPTY(&cli->info.queries) ||
1161 {
1162 OptGui = false;
1163 sendflags |= SEND_BATCH;
1166 }
1167
1168 /* Check to make sure stdout is available in curses mode. */
1169 if (OptGui && !isatty(STDOUT_FILENO))
1170 goto main_curses;
1171
1172 /* This must come before mutt_init() because curses needs to be started
1173 * before calling the init_pair() function to set the color scheme. */
1174 if (OptGui)
1175 {
1176 int crc = start_curses();
1177 if (crc != 0)
1178 goto main_curses; // TEST08: can't test -- fake term?
1179 }
1180
1181 /* Always create the mutt_windows because batch mode has some shared code
1182 * paths that end up referencing them. */
1183 rootwin_new();
1184
1185 if (OptGui)
1186 {
1187 /* check whether terminal status is supported (must follow curses init) */
1190 log_gui();
1191 }
1192
1194 alias_init();
1195 commands_init();
1196 hooks_init();
1198 imap_init();
1199 lua_init();
1201 km_init();
1202
1203 menu_init();
1204 sb_init();
1205#ifdef USE_NOTMUCH
1206 nm_init();
1207#endif
1208
1209 /* set defaults and read init files */
1210 int rc2 = mutt_init(cs, &cli->shared.log_level, &cli->shared.log_file,
1212 &cli->shared.commands);
1213 if (rc2 != 0)
1214 goto main_curses;
1215
1218
1219#ifdef USE_NOTMUCH
1220 const bool c_virtual_spool_file = cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
1221 if (c_virtual_spool_file)
1222 {
1223 /* Find the first virtual folder and open it */
1224 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_NOTMUCH);
1225 struct Mailbox **mp = ARRAY_FIRST(&ma);
1226 if (mp)
1227 cs_str_string_set(cs, "spool_file", mailbox_path(*mp), NULL);
1228 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
1229 }
1230#endif
1231
1233
1234 init_nntp(&cli->tui.nntp_server, cs);
1235
1236 /* Initialize crypto backends. */
1237 crypt_init();
1238
1239 if (!buf_is_empty(&cli->shared.mbox_type) &&
1240 !config_str_set_initial(cs, "mbox_type", buf_string(&cli->shared.mbox_type)))
1241 {
1242 goto main_curses;
1243 }
1244
1245 if (!dump_info(&cli->info, cs))
1246 goto main_ok;
1247
1248 if (OptGui)
1249 {
1251 clear();
1255 }
1256
1257#ifdef USE_AUTOCRYPT
1258 /* Initialize autocrypt after curses messages are working,
1259 * because of the initial account setup screens. */
1260 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
1261 if (c_autocrypt)
1262 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
1263#endif
1264
1265 /* Create the `$folder` directory if it doesn't exist. */
1266 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1267 if (OptGui && c_folder)
1268 {
1269 struct stat st = { 0 };
1270 struct Buffer *fpath = buf_pool_get();
1271
1272 buf_strcpy(fpath, c_folder);
1273 buf_expand_path(fpath);
1274 bool skip = false;
1275 /* we're not connected yet - skip mail folder creation */
1276 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
1277 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
1278 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
1279 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
1280 {
1281 char msg2[256] = { 0 };
1282 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
1283 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
1284 {
1285 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
1286 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
1287 }
1288 }
1289 buf_pool_release(&fpath);
1290 }
1291
1292 StartupComplete = true;
1293
1297
1298 if (cli->tui.start_postponed)
1299 {
1300 if (OptGui)
1301 mutt_flushinp();
1302 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1303 rc = 0;
1304 // TEST23: neomutt -p (postponed message, cancel)
1305 // TEST24: neomutt -p (no postponed message)
1307 repeat_error = true;
1308 goto main_curses;
1309 }
1310 else if (cli->send.is_set)
1311 {
1312 FILE *fp_in = NULL;
1313 FILE *fp_out = NULL;
1314 const char *infile = NULL;
1315 char *bodytext = NULL;
1316 const char *bodyfile = NULL;
1317 int rv = 0;
1318
1319 if (OptGui)
1320 mutt_flushinp();
1321
1322 e = email_new();
1323 e->env = mutt_env_new();
1324
1325 const char **cp = NULL;
1326 ARRAY_FOREACH(cp, &cli->send.bcc_list)
1327 {
1328 mutt_addrlist_parse(&e->env->bcc, *cp);
1329 }
1330
1331 ARRAY_FOREACH(cp, &cli->send.cc_list)
1332 {
1333 mutt_addrlist_parse(&e->env->cc, *cp);
1334 }
1335
1336 ARRAY_FOREACH(cp, &cli->send.addresses)
1337 {
1338 if (url_check_scheme(*cp) == U_MAILTO)
1339 {
1340 if (!mutt_parse_mailto(e->env, &bodytext, *cp))
1341 {
1342 mutt_error(_("Failed to parse mailto: link"));
1343 email_free(&e);
1344 goto main_curses; // TEST25: neomutt mailto:?
1345 }
1346 }
1347 else
1348 {
1349 mutt_addrlist_parse(&e->env->to, *cp);
1350 }
1351 }
1352
1353 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1354 if (buf_is_empty(&cli->send.draft_file) && c_auto_edit &&
1355 TAILQ_EMPTY(&e->env->to) && TAILQ_EMPTY(&e->env->cc))
1356 {
1357 mutt_error(_("No recipients specified"));
1358 email_free(&e);
1359 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1360 }
1361
1362 if (!buf_is_empty(&cli->send.subject))
1363 {
1364 /* prevent header injection */
1367 }
1368
1369 if (!buf_is_empty(&cli->send.draft_file))
1370 {
1371 infile = buf_string(&cli->send.draft_file);
1372 }
1373 else if (!buf_is_empty(&cli->send.include_file))
1374 {
1375 infile = buf_string(&cli->send.include_file);
1376 }
1377 else
1378 {
1379 cli->send.edit_infile = false;
1380 }
1381
1382 if (infile || bodytext)
1383 {
1384 /* Prepare fp_in and expanded_infile. */
1385 if (infile)
1386 {
1387 if (mutt_str_equal("-", infile))
1388 {
1389 if (cli->send.edit_infile)
1390 {
1391 mutt_error(_("Can't use -E flag with stdin"));
1392 email_free(&e);
1393 goto main_curses; // TEST27: neomutt -E -H -
1394 }
1395 fp_in = stdin;
1396 }
1397 else
1398 {
1399 buf_strcpy(expanded_infile, infile);
1400 buf_expand_path(expanded_infile);
1401 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1402 if (!fp_in)
1403 {
1404 mutt_perror("%s", buf_string(expanded_infile));
1405 email_free(&e);
1406 goto main_curses; // TEST28: neomutt -E -H missing
1407 }
1408 }
1409 }
1410
1411 if (cli->send.edit_infile)
1412 {
1413 /* If editing the infile, keep it around afterwards so
1414 * it doesn't get unlinked, and we can rebuild the draft_file */
1415 sendflags |= SEND_NO_FREE_HEADER;
1416 }
1417 else
1418 {
1419 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1420 * Note: stdin is always copied to a tempfile, ensuring draft_file
1421 * can stat and get the correct st_size below. */
1422 buf_mktemp(tempfile);
1423
1424 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1425 if (!fp_out)
1426 {
1427 mutt_file_fclose(&fp_in);
1428 mutt_perror("%s", buf_string(tempfile));
1429 email_free(&e);
1430 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1431 }
1432 if (fp_in)
1433 {
1434 mutt_file_copy_stream(fp_in, fp_out);
1435 if (fp_in == stdin)
1436 sendflags |= SEND_CONSUMED_STDIN;
1437 else
1438 mutt_file_fclose(&fp_in);
1439 }
1440 else if (bodytext)
1441 {
1442 fputs(bodytext, fp_out);
1443 }
1444 mutt_file_fclose(&fp_out);
1445
1446 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1447 if (!fp_in)
1448 {
1449 mutt_perror("%s", buf_string(tempfile));
1450 email_free(&e);
1451 goto main_curses; // TEST30: can't test
1452 }
1453 }
1454
1455 /* Parse the draft_file into the full Email/Body structure.
1456 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1457 * our e->body. */
1458 if (!buf_is_empty(&cli->send.draft_file))
1459 {
1460 struct Envelope *opts_env = e->env;
1461 struct stat st = { 0 };
1462
1463 sendflags |= SEND_DRAFT_FILE;
1464
1465 /* Set up a tmp Email with just enough information so that
1466 * mutt_prepare_template() can parse the message in fp_in. */
1467 struct Email *e_tmp = email_new();
1468 e_tmp->offset = 0;
1469 e_tmp->body = mutt_body_new();
1470 if (fstat(fileno(fp_in), &st) != 0)
1471 {
1472 mutt_perror("%s", buf_string(&cli->send.draft_file));
1473 email_free(&e);
1474 email_free(&e_tmp);
1475 goto main_curses; // TEST31: can't test
1476 }
1477 e_tmp->body->length = st.st_size;
1478
1479 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1480 {
1481 mutt_error(_("Can't parse message template: %s"),
1482 buf_string(&cli->send.draft_file));
1483 email_free(&e);
1484 email_free(&e_tmp);
1485 goto main_curses;
1486 }
1487
1488 /* Scan for neomutt header to set `$resume_draft_files` */
1489 struct ListNode *tmp = NULL;
1490 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1491 struct ListNode *np = NULL;
1492 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1493 {
1494 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1495 {
1496 if (c_resume_edited_draft_files)
1497 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1498
1499 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1500 FREE(&np->data);
1501 FREE(&np);
1502 }
1503 }
1504
1505 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1506 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1507 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1508 if (opts_env->subject)
1509 mutt_env_set_subject(e->env, opts_env->subject);
1510
1511 mutt_env_free(&opts_env);
1512 email_free(&e_tmp);
1513 }
1514 else if (cli->send.edit_infile)
1515 {
1516 /* Editing the include_file: pass it directly in.
1517 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1518 bodyfile = buf_string(expanded_infile);
1519 }
1520 else
1521 {
1522 // For bodytext and unedited include_file: use the tempfile.
1523 bodyfile = buf_string(tempfile);
1524 }
1525
1526 mutt_file_fclose(&fp_in);
1527 }
1528
1529 FREE(&bodytext);
1530
1531 if (!ARRAY_EMPTY(&cli->send.attach))
1532 {
1533 struct Body *b = e->body;
1534
1535 while (b && b->next)
1536 b = b->next;
1537
1538 ARRAY_FOREACH(cp, &cli->send.attach)
1539 {
1540 if (b)
1541 {
1543 b = b->next;
1544 }
1545 else
1546 {
1548 e->body = b;
1549 }
1550 if (!b)
1551 {
1552 mutt_error(_("%s: unable to attach file"), *cp);
1553 email_free(&e);
1554 goto main_curses; // TEST32: neomutt john@example.com -a missing
1555 }
1556 }
1557 }
1558
1559 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1560 /* We WANT the "Mail sent." and any possible, later error */
1562 if (ErrorBufMessage)
1563 mutt_message("%s", ErrorBuf);
1564
1565 if (cli->send.edit_infile)
1566 {
1567 if (!buf_is_empty(&cli->send.draft_file))
1568 {
1569 if (truncate(buf_string(expanded_infile), 0) == -1)
1570 {
1571 mutt_perror("%s", buf_string(expanded_infile));
1572 email_free(&e);
1573 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1574 }
1575 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1576 if (!fp_out)
1577 {
1578 mutt_perror("%s", buf_string(expanded_infile));
1579 email_free(&e);
1580 goto main_curses; // TEST34: can't test
1581 }
1582
1583 /* If the message was sent or postponed, these will already
1584 * have been done. */
1585 if (rv < 0)
1586 {
1587 if (e->body->next)
1588 e->body = mutt_make_multipart(e->body);
1590 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1591 mutt_env_to_intl(e->env, NULL, NULL);
1592 }
1593
1594 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1596 c_crypt_protected_headers_read &&
1598 NeoMutt->sub);
1599 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1600 if (c_resume_edited_draft_files)
1601 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1602 fputc('\n', fp_out);
1603 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1604 {
1605 mutt_file_fclose(&fp_out);
1606 email_free(&e);
1607 goto main_curses; // TEST35: can't test
1608 }
1609 mutt_file_fclose(&fp_out);
1610 }
1611
1612 email_free(&e);
1613 }
1614
1615 /* !edit_infile && draft_file will leave the tempfile around */
1616 if (!buf_is_empty(tempfile))
1617 unlink(buf_string(tempfile));
1618
1620
1621 if (rv != 0)
1622 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1623 }
1624 else if (sendflags & SEND_BATCH)
1625 {
1626 /* This guards against invoking `neomutt < /dev/null` and accidentally
1627 * sending an email due to a my_hdr or other setting. */
1628 mutt_error(_("No recipients specified"));
1629 goto main_curses;
1630 }
1631 else
1632 {
1633 struct Buffer *folder = &cli->tui.folder;
1634 bool explicit_folder = !buf_is_empty(folder);
1635
1636 if (cli->tui.start_new_mail)
1637 {
1638 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1639 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1641 if (mutt_mailbox_check(NULL, csflags) == 0)
1642 {
1643 mutt_message(_("No mailbox with new mail"));
1644 repeat_error = true;
1645 goto main_curses; // TEST37: neomutt -Z (no new mail)
1646 }
1647 buf_reset(folder);
1648 mutt_mailbox_next(NULL, folder);
1649 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1650 }
1651 else if (cli->tui.start_nntp || cli->tui.start_browser)
1652 {
1653 if (cli->tui.start_nntp)
1654 {
1655 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1656 OptNews = true;
1657 CurrentNewsSrv = nntp_select_server(NULL, c_news_server, false);
1658 if (!CurrentNewsSrv)
1659 goto main_curses; // TEST38: neomutt -G (unset news_server)
1660 }
1661 else if (ARRAY_EMPTY(&NeoMutt->accounts))
1662 {
1663 mutt_error(_("No incoming mailboxes defined"));
1664 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1665 }
1666 buf_reset(folder);
1667 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1668 if (buf_is_empty(folder))
1669 {
1670 goto main_ok; // TEST40: neomutt -y (quit selection)
1671 }
1672 }
1673
1674 if (buf_is_empty(folder))
1675 {
1676 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1677 if (c_spool_file)
1678 {
1679 // Check if `$spool_file` corresponds a mailboxes' description.
1680 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1681 if (m_desc)
1682 buf_strcpy(folder, m_desc->realpath);
1683 else
1684 buf_strcpy(folder, c_spool_file);
1685 }
1686 else if (c_folder)
1687 {
1688 buf_strcpy(folder, c_folder);
1689 }
1690 /* else no folder */
1691 }
1692
1693 if (OptNews)
1694 {
1695 OptNews = false;
1696 buf_alloc(folder, PATH_MAX);
1697 nntp_expand_path(folder->data, folder->dsize, &CurrentNewsSrv->conn->account);
1698 }
1699 else
1700 {
1701 buf_expand_path(folder);
1702 }
1703
1706
1707 if (cli->tui.start_any_mail || cli->tui.start_new_mail)
1708 {
1709 /* check to see if there are any messages in the folder */
1710 switch (mx_path_is_empty(folder))
1711 {
1712 case -1:
1713 mutt_perror("%s", buf_string(folder));
1714 goto main_curses; // TEST41: neomutt -z -f missing
1715 case 1:
1716 mutt_error(_("Mailbox is empty"));
1717 goto main_curses; // TEST42: neomutt -z -f /dev/null
1718 }
1719 }
1720
1721 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1722 // Take a copy of the name just in case the hook alters m_cur
1723 const char *name = m_cur ? mutt_str_dup(m_cur->name) : NULL;
1725 FREE(&name);
1727 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1729
1731 window_redraw(NULL);
1732
1733 repeat_error = true;
1734 struct Mailbox *m = mx_resolve(buf_string(folder));
1735 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1736 if (!mx_mbox_open(m, (cli->tui.read_only || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1737 {
1738 if (m->account)
1740
1741 mailbox_free(&m);
1742 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1743 repeat_error = false;
1744 }
1745 if (m || !explicit_folder)
1746 {
1747 struct MuttWindow *dlg = index_pager_init();
1748 dialog_push(dlg);
1749
1751 m = dlg_index(dlg, m);
1753 mailbox_free(&m);
1754
1755 dialog_pop();
1756 mutt_window_free(&dlg);
1758 repeat_error = false;
1759 }
1761#ifdef USE_SASL_CYRUS
1763#endif
1764#ifdef USE_SASL_GNU
1766#endif
1767#ifdef USE_AUTOCRYPT
1769#endif
1770 // TEST43: neomutt (no change to mailbox)
1771 // TEST44: neomutt (change mailbox)
1772 }
1773
1774main_ok:
1775 rc = 0;
1776main_curses:
1777 mutt_endwin();
1779 /* Repeat the last message to the user */
1780 if (repeat_error && ErrorBufMessage)
1781 puts(ErrorBuf);
1782main_exit:
1783 if (NeoMutt && NeoMutt->sub)
1784 {
1788 }
1790 buf_pool_release(&expanded_infile);
1791 buf_pool_release(&tempfile);
1795 if (NeoMutt)
1799 menu_cleanup();
1800 crypt_cleanup();
1802 command_line_free(&cli);
1803
1805
1806 alias_cleanup();
1807 sb_cleanup();
1808
1814
1817
1818 /* Lists of strings */
1827
1829
1831 FREE(&LastFolder);
1833
1835
1837
1840
1842 if (NeoMutt)
1844
1845 lua_cleanup();
1853 cs_free(&cs);
1855 mutt_log_stop();
1856 return rc;
1857}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:765
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:480
void alias_cleanup(void)
Clean up the Alias globals.
Definition alias.c:718
void alias_init(void)
Set up the Alias globals.
Definition alias.c:710
void alternates_cleanup(void)
Free the alternates lists.
Definition alternates.c:49
void alternates_init(void)
Set up the alternates lists.
Definition alternates.c:60
#define ARRAY_FIRST(head)
Convenience method to get the first element.
Definition array.h:135
void attach_init(void)
Set up the attachments lists.
Definition commands.c:106
void attach_cleanup(void)
Free the attachments lists.
Definition commands.c:92
void mutt_autocrypt_cleanup(void)
Shutdown Autocrypt.
Definition autocrypt.c:129
int mutt_autocrypt_init(bool can_create)
Initialise Autocrypt.
Definition autocrypt.c:99
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition lib.h:58
#define MUTT_SEL_FOLDER
Select a local directory.
Definition lib.h:60
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
bool cli_parse(int argc, char *const *argv, struct CommandLine *cli)
Parse the Command Line.
Definition parse.c:93
void colors_cleanup(void)
Cleanup all the colours.
Definition color.c:84
@ MT_COLOR_NORMAL
Plain text.
Definition color.h:54
void source_stack_cleanup(void)
Free memory from the stack used for the source command.
Definition commands.c:1670
bool commands_init(void)
Initialize commands array and register default commands.
Definition commands.c:1741
void mutt_comp_init(void)
Setup Compressed Mailbox commands.
Definition compress.c:90
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
void cs_free(struct ConfigSet **ptr)
Free a Config Set.
Definition set.c:141
struct ConfigSet * cs_new(size_t size)
Create a new Config Set.
Definition set.c:127
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:788
bool StartupComplete
When the config has been read.
Definition address.c:13
void config_cache_cleanup(void)
Cleanup the cache of charset config variables.
void account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition account.c:94
void commands_clear(struct CommandArray *ca)
Clear an Array of Commands.
Definition command.c:70
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:89
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition mailbox.c:186
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:150
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:214
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:51
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition crypt.c:1100
void crypto_module_cleanup(void)
Clean up the crypto modules.
Definition crypt_mod.c:84
void crypt_cleanup(void)
Clean up backend.
Definition cryptglue.c:141
void crypt_init(void)
Initialise the crypto backends.
Definition cryptglue.c:93
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:152
int debug_all_observer(struct NotifyCallback *nc)
Definition notify.c:196
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition dialog.c:109
void dialog_pop(void)
Hide a Window from the user.
Definition dialog.c:142
void mutt_browser_cleanup(void)
Clean up working Buffers.
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition dlg_index.c:1436
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
struct ReplaceList SpamList
List of regexes to match subscribed mailing lists.
Definition globals.c:46
struct RegexList SubscribedLists
List of header patterns to unignore (see)
Definition globals.c:48
struct RegexList UnSubscribedLists
Definition globals.c:54
struct RegexList UnMailLists
List of regexes to exclude false matches in SubscribedLists.
Definition globals.c:52
struct RegexList MailLists
List of permitted fields in a mailto: url.
Definition globals.c:40
struct ListHead Ignore
List of regexes to match mailing lists.
Definition globals.c:38
struct RegexList NoSpamList
List of regexes and patterns to match spam emails.
Definition globals.c:44
struct ListHead UnIgnore
List of regexes to exclude false matches in MailLists.
Definition globals.c:50
bool mutt_parse_mailto(struct Envelope *env, char **body, const char *src)
Parse a mailto:// url.
Definition parse.c:1753
void mutt_filter_commandline_header_value(char *header)
Sanitise characters in a header value.
Definition parse.c:92
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope's Address fields to Punycode format.
Definition envelope.c:354
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition envelope.c:68
void envlist_free(char ***envp)
Free the private copy of the environment.
Definition envlist.c:42
char ** envlist_init(char **envp)
Create a copy of the environment.
Definition envlist.c:58
void external_cleanup(void)
Clean up commands globals.
Definition external.c:80
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:225
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition get.c:58
bool OptNews
(pseudo) used to change reader mode
Definition globals.c:64
char * LastFolder
Previously selected mailbox.
Definition globals.c:40
struct ListHead MimeLookupList
List of mime types that that shouldn't use the mailcap entry.
Definition globals.c:47
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition globals.c:44
struct ListHead AutoViewList
List of mime types to auto view.
Definition globals.c:45
char ErrorBuf[1024]
Copy of the last error message.
Definition globals.c:35
bool ErrorBufMessage
true if the last message was an error
Definition globals.c:34
char * CurrentFolder
Currently selected mailbox.
Definition globals.c:39
struct ListHead UserHeader
List of custom headers to add to outgoing emails.
Definition globals.c:49
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition globals.c:46
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition group.c:95
void mutt_grouplist_cleanup(void)
Free GroupList singleton resource.
Definition group.c:107
void dlg_browser(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file -.
struct Mailbox * dlg_index(struct MuttWindow *dlg, struct Mailbox *m_init)
Display a list of emails -.
Definition dlg_index.c:1099
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Save a log line to an internal queue - Implements log_dispatcher_t -.
Definition logging.c:378
int log_disp_curses(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Display a log line in the message line - Implements log_dispatcher_t -.
#define mutt_message(...)
Definition logging2.h:92
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox?
Definition nntp.c:2785
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox?
Definition pop.c:1156
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2351
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has change - Implements observer_t -.
Definition history.c:701
static int main_timeout_observer(struct NotifyCallback *nc)
Notification that a timeout has occurred - Implements observer_t -.
Definition main.c:904
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
void mutt_gsasl_cleanup(void)
Shutdown GNU SASL library.
Definition gsasl.c:149
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *b, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject, struct ConfigSubset *sub)
Write out one RFC822 header line.
Definition header.c:577
@ MUTT_WRITE_HEADER_POSTPONE
A postponed Email, just the envelope info.
Definition header.h:42
void mutt_hist_read_file(void)
Read the History from a file.
Definition history.c:592
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition history.c:464
void mutt_hist_cleanup(void)
Free all the history lists.
Definition history.c:437
void mutt_startup_shutdown_hook(HookFlags type)
Execute any startup/shutdown hooks.
Definition hook.c:963
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition hook.c:397
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition hook.c:630
void hooks_init(void)
Setup feature commands.
Definition hook.c:1051
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition hook.h:54
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition hook.h:36
void imap_logout_all(void)
Close all open connections.
Definition imap.c:557
void imap_init(void)
Setup feature commands.
Definition imap.c:95
void km_init(void)
Initialise all the menu keybindings.
Definition init.c:85
void mutt_keys_cleanup(void)
Free the key maps.
Definition init.c:146
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition init.c:162
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
int log_dispatcher_t MuttLogger
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:49
void lua_init(void)
Setup feature commands.
Definition commands.c:128
void lua_cleanup(void)
Clean up Lua.
Definition commands.c:136
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition main.c:786
static void localise_config(struct ConfigSet *cs)
Localise some config.
Definition main.c:726
static bool init_logging(struct CliShared *shared, struct ConfigSet *cs)
Initialise the Logging.
Definition main.c:969
static void log_translation(void)
Log the translation being used.
Definition main.c:855
static void log_gui(void)
Log info about the GUI.
Definition main.c:881
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition main.c:703
static void init_nntp(struct Buffer *server, struct ConfigSet *cs)
Initialise the NNTP config.
Definition main.c:998
static bool show_help(struct CliHelp *help)
Show the Help.
Definition main.c:938
static int start_curses(void)
Start the Curses UI.
Definition main.c:756
static bool dump_info(struct CliInfo *ci, struct ConfigSet *cs)
Show config info.
Definition main.c:1027
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition main.c:814
static int mutt_init(struct ConfigSet *cs, struct Buffer *dlevel, struct Buffer *dfile, bool skip_sys_rc, struct StringArray *user_files, struct StringArray *commands)
Initialise NeoMutt.
Definition main.c:404
void menu_init(void)
Initialise all the Menus.
Definition menu.c:79
void menu_cleanup(void)
Free the saved Menu searches.
Definition menu.c:70
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition multipart.c:100
void mutt_ch_cache_cleanup(void)
Clean up the cached iconv handles and charset strings.
Definition charset.c:1175
void log_queue_empty(void)
Free the contents of the queue.
Definition logging.c:325
void log_queue_set_max_size(int size)
Set a upper limit for the queue length.
Definition logging.c:313
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition notify.c:230
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:191
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition regex.c:178
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition regex.c:449
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:244
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:282
#define PATH_MAX
Definition mutt.h:42
void mutt_temp_attachments_cleanup(void)
Delete all temporary attachments.
void init_config(struct ConfigSet *cs)
Initialise the config system.
enum MuttCursorState mutt_curses_set_cursor(enum MuttCursorState state)
Set the cursor state.
Definition mutt_curses.c:94
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
Definition mutt_curses.c:79
void mutt_resize_screen(void)
Update NeoMutt's opinion about the window size.
Definition resize.c:76
@ MUTT_CURSOR_INVISIBLE
Hide the cursor.
Definition mutt_curses.h:65
@ MUTT_CURSOR_VISIBLE
Display a normal cursor.
Definition mutt_curses.h:66
void mutt_log_stop(void)
Close the log file.
void mutt_log_prep(void)
Prepare to log.
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:288
struct Mailbox * mx_resolve(const char *path_or_name)
Get a Mailbox from either a path or name.
Definition mx.c:1722
int mx_path_is_empty(struct Buffer *path)
Is the mailbox empty.
Definition mx.c:1257
#define MUTT_READONLY
Open in read-only mode.
Definition mxapi.h:43
#define MUTT_MAILBOX_CHECK_IMMEDIATE
Don't postpone the actual checking.
Definition mxapi.h:53
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition mxapi.h:40
uint8_t CheckStatsFlags
Flags for mutt_mailbox_check.
Definition mxapi.h:49
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:184
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the main NeoMutt object.
Definition neomutt.c:49
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition neomutt.c:85
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition neomutt.h:66
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition newsrc.c:556
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition nntp.c:76
struct NntpAccountData * nntp_select_server(struct Mailbox *m, const char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition newsrc.c:945
@ NT_TIMEOUT
Timeout has occurred.
Definition notify_type.h:56
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition notify_type.h:43
@ NT_ALL
Register for all notifications.
Definition notify_type.h:35
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition notify_type.h:46
@ NT_RESIZE
Window has been resized.
Definition notify_type.h:52
void nm_init(void)
Setup feature commands.
Definition notmuch.c:109
struct CommandLine * command_line_new(void)
Create a new CommandLine.
Definition objects.c:105
void command_line_free(struct CommandLine **ptr)
Free a CommandLine.
Definition objects.c:114
void buf_pool_cleanup(void)
Release the Buffer pool.
Definition pool.c:68
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:487
void mutt_prex_cleanup(void)
Cleanup heap memory allocated by compiled regexes.
Definition prex.c:338
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:325
#define STAILQ_REMOVE(head, elm, type, field)
Definition queue.h:441
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:400
#define TAILQ_EMPTY(head)
Definition queue.h:778
void rootwin_cleanup(void)
Free all the default Windows.
Definition rootwin.c:202
void rootwin_new(void)
Create the default Windows.
Definition rootwin.c:214
void mutt_sasl_cleanup(void)
Invoke when processing is complete.
Definition sasl.c:785
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition body.c:300
void mutt_encode_descriptions(struct Body *b, bool recurse, struct ConfigSubset *sub)
RFC2047 encode the content-descriptions.
Definition send.c:1489
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition send.c:2034
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition send.h:47
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition send.h:51
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition send.h:52
uint32_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition send.h:40
#define SEND_POSTPONED
Recall a postponed email.
Definition send.h:46
#define SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
Definition send.h:57
#define SEND_NO_FLAGS
No flags are set.
Definition send.h:41
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition sendlib.c:606
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition sendlib.c:779
void sb_init(void)
Set up the Sidebar.
Definition sidebar.c:204
void sb_cleanup(void)
Clean up the Sidebar.
Definition sidebar.c:220
The body of an email.
Definition body.h:36
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition body.h:68
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
struct Body * next
next attachment in the list
Definition body.h:72
size_t dsize
Length of data.
Definition buffer.h:39
struct Buffer draft_file
-H Use this draft file
Definition objects.h:102
bool is_set
This struct has been used.
Definition objects.h:93
struct Buffer include_file
-i Use this include file
Definition objects.h:103
struct StringArray cc_list
-c Add a Cc:
Definition objects.h:99
struct StringArray attach
-a Attach a file
Definition objects.h:97
bool edit_infile
-E Edit the draft/include
Definition objects.h:95
struct StringArray bcc_list
-b Add a Bcc:
Definition objects.h:98
struct StringArray addresses
Send to these addresses.
Definition objects.h:100
struct Buffer subject
-s Use this Subject:
Definition objects.h:104
struct StringArray commands
-e Run these commands
Definition objects.h:53
bool disable_system
-n Don't read the system config file
Definition objects.h:51
struct StringArray user_files
-F Use these user config files
Definition objects.h:50
struct Buffer mbox_type
-m Set the default Mailbox type
Definition objects.h:54
bool read_only
-R Open Mailbox read-only
Definition objects.h:113
bool start_any_mail
-z Check for Any Mail
Definition objects.h:118
bool start_nntp
-G Open an NNTP Mailbox
Definition objects.h:116
struct Buffer nntp_server
-g Open this NNTP Mailbox
Definition objects.h:121
struct Buffer folder
-f Open this Mailbox
Definition objects.h:120
bool start_postponed
-p Open Postponed emails
Definition objects.h:114
bool start_new_mail
-Z Check for New Mail
Definition objects.h:117
bool start_browser
-y Open the Mailbox Browser
Definition objects.h:115
Command Line options.
Definition objects.h:128
struct CliSend send
Send Mode command line options.
Definition objects.h:132
struct CliShared shared
Shared command line options.
Definition objects.h:129
struct CliHelp help
Help Mode command line options.
Definition objects.h:130
struct CliInfo info
Info Mode command line options.
Definition objects.h:131
struct CliTui tui
Tui Mode command line options.
Definition objects.h:133
Container for lots of config items.
Definition set.h:248
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition subset.h:51
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
struct Body * body
List of MIME parts.
Definition email.h:69
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
The header of an Email.
Definition envelope.h:57
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
char *const subject
Email's subject.
Definition envelope.h:70
struct AddressList to
Email's 'To' list.
Definition envelope.h:60
struct AddressList cc
Email's 'Cc' list.
Definition envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition envelope.h:62
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
A mailbox.
Definition mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:81
char * name
A short name for the Mailbox.
Definition mailbox.h:82
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:127
struct AccountArray accounts
All Accounts.
Definition neomutt.h:47
struct CommandArray commands
NeoMutt commands.
Definition neomutt.h:50
struct Notify * notify_resize
Window resize notifications handler.
Definition neomutt.h:44
char ** env
Private copy of the environment variables.
Definition neomutt.h:54
mode_t user_default_umask
User's default file writing permissions (inferred from umask)
Definition neomutt.h:49
struct Notify * notify
Notifications handler.
Definition neomutt.h:43
void subjrx_init(void)
Create new Subject Regex List.
Definition subjectrx.c:55
void subjrx_cleanup(void)
Free the Subject Regex List.
Definition subjectrx.c:46
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:303
void driver_tags_cleanup(void)
Deinitialize structures used for tags.
Definition tags.c:245
void driver_tags_init(void)
Initialize structures used for tags.
Definition tags.c:233
bool TsSupported
Terminal Setting is supported.
Definition terminal.c:53
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition terminal.c:83
#define buf_mktemp(buf)
Definition tmp.h:33
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition url.c:225
@ U_MAILTO
Url is mailto://.
Definition url.h:45

Variable Documentation

◆ StartupComplete

bool StartupComplete = false

When the config has been read.

Definition at line 196 of file main.c.