NeoMutt  2025-12-11-58-g09398d
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 114 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 193 of file main.c.

194{
195 int rc = 0;
196 struct Buffer *err = buf_pool_get();
197 struct Buffer *line = buf_pool_get();
198
199 const char **cp = NULL;
200 ARRAY_FOREACH(cp, sa)
201 {
202 buf_strcpy(line, *cp);
203 enum CommandResult rc2 = parse_rc_line(line, err);
204 if (rc2 == MUTT_CMD_ERROR)
205 mutt_error(_("Error in command line: %s"), buf_string(err));
206 else if (rc2 == MUTT_CMD_WARNING)
207 mutt_warning(_("Warning in command line: %s"), buf_string(err));
208
209 if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
210 {
211 buf_pool_release(&err);
212 return -1;
213 }
214 }
215
216 buf_pool_release(&line);
217 buf_pool_release(&err);
218
219 return rc;
220}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
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(struct Buffer *line, struct Buffer *err)
Parse a line of user config.
Definition rc.c:45
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 229 of file main.c.

230{
231 const char *names[] = {
232 "neomuttrc",
233 "muttrc",
234 NULL,
235 };
236
237 const char *locations[][2] = {
238 { xdg_cfg_home, "neomutt/" },
239 { xdg_cfg_home, "mutt/" },
240 { home, ".neomutt/" },
241 { home, ".mutt/" },
242 { home, "." },
243 { NULL, NULL },
244 };
245
246 struct Buffer *buf = buf_pool_get();
247 char *cfg = NULL;
248
249 for (int i = 0; locations[i][0] || locations[i][1]; i++)
250 {
251 if (!locations[i][0])
252 continue;
253
254 for (int j = 0; names[j]; j++)
255 {
256 buf_printf(buf, "%s/%s%s", locations[i][0], locations[i][1], names[j]);
257 if (access(buf_string(buf), F_OK) == 0)
258 {
259 cfg = buf_strdup(buf);
260 goto done;
261 }
262 }
263 }
264
265done:
266 buf_pool_release(&buf);
267 return cfg;
268}
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 276 of file main.c.

277{
278 char *mailname = NULL;
279 static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
280
281 for (size_t i = 0; i < countof(mn_files); i++)
282 {
283 FILE *fp = mutt_file_fopen(mn_files[i], "r");
284 if (!fp)
285 continue;
286
287 size_t len = 0;
288 mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
289 mutt_file_fclose(&fp);
290 if (mailname && *mailname)
291 break;
292
293 FREE(&mailname);
294 }
295
296 return mailname;
297}
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 309 of file main.c.

310{
311 const char *short_host = NULL;
312 struct utsname utsname = { 0 };
313
314 const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
315 if (c_hostname)
316 {
317 short_host = c_hostname;
318 }
319 else
320 {
321 /* The call to uname() shouldn't fail, but if it does, the system is horribly
322 * broken, and the system's networking configuration is in an unreliable
323 * state. We should bail. */
324 if ((uname(&utsname)) == -1)
325 {
326 mutt_perror(_("unable to determine nodename via uname()"));
327 return false; // TEST09: can't test
328 }
329
330 short_host = utsname.nodename;
331 }
332
333 /* some systems report the FQDN instead of just the hostname */
334 char *dot = strchr(short_host, '.');
335 if (dot)
336 ShortHostname = mutt_strn_dup(short_host, dot - short_host);
337 else
338 ShortHostname = mutt_str_dup(short_host);
339
340 // All the code paths from here alloc memory for the fqdn
341 char *fqdn = mutt_str_dup(c_hostname);
342 if (!fqdn)
343 {
344 mutt_debug(LL_DEBUG1, "Setting $hostname\n");
345 /* now get FQDN. Use configured domain first, DNS next, then uname */
346#ifdef DOMAIN
347 /* we have a compile-time domain name, use that for `$hostname` */
348 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
349#else
350 fqdn = getmailname();
351 if (!fqdn)
352 {
353 struct Buffer *domain = buf_pool_get();
354 if (getdnsdomainname(domain) == 0)
355 {
356 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), buf_string(domain));
357 }
358 else
359 {
360 /* DNS failed, use the nodename. Whether or not the nodename had a '.'
361 * in it, we can use the nodename as the FQDN. On hosts where DNS is
362 * not being used, e.g. small network that relies on hosts files, a
363 * short host name is all that is required for SMTP to work correctly.
364 * It could be wrong, but we've done the best we can, at this point the
365 * onus is on the user to provide the correct hostname if the nodename
366 * won't work in their network. */
367 fqdn = mutt_str_dup(utsname.nodename);
368 }
369 buf_pool_release(&domain);
370 mutt_debug(LL_DEBUG1, "Hostname: %s\n", NONULL(fqdn));
371 }
372#endif
373 }
374
375 if (fqdn)
376 {
377 config_str_set_initial(cs, "hostname", fqdn);
378 FREE(&fqdn);
379 }
380
381 return true;
382}
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:276
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:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
+ 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 395 of file main.c.

398{
399 bool need_pause = false;
400 int rc = 1;
401 struct Buffer *err = buf_pool_get();
402 struct Buffer *buf = buf_pool_get();
403 const char **cp = NULL;
404
405#ifdef NEOMUTT_DIRECT_COLORS
406 /* Test if we run in a terminal which supports direct colours.
407 *
408 * The user/terminal can indicate their capability independent of the
409 * terminfo file by setting the COLORTERM environment variable to "truecolor"
410 * or "24bit" (case sensitive).
411 *
412 * Note: This is to test is less about whether the terminal understands
413 * direct color commands but more about whether ncurses believes it can send
414 * them to the terminal, e.g. ncurses ignores COLORTERM.
415 */
416 if (COLORS == 16777216) // 2^24
417 {
418 /* Ncurses believes the Terminal supports it check the environment variable
419 * to respect the user's choice */
420 const char *env_colorterm = mutt_str_getenv("COLORTERM");
421 if (env_colorterm && (mutt_str_equal(env_colorterm, "truecolor") ||
422 mutt_str_equal(env_colorterm, "24bit")))
423 {
424 config_str_set_initial(cs, "color_directcolor", "yes");
425 }
426 }
427#endif
428
429 /* "$spool_file" precedence: config file, environment */
430 const char *p = mutt_str_getenv("MAIL");
431 if (!p)
432 p = mutt_str_getenv("MAILDIR");
433 if (!p)
434 {
435#ifdef HOMESPOOL
436 buf_concat_path(buf, NONULL(NeoMutt->home_dir), MAILPATH);
437#else
438 buf_concat_path(buf, MAILPATH, NONULL(NeoMutt->username));
439#endif
440 p = buf_string(buf);
441 }
442 config_str_set_initial(cs, "spool_file", p);
443
444 p = mutt_str_getenv("REPLYTO");
445 if (p)
446 {
447 buf_printf(buf, "Reply-To: %s", p);
448 buf_seek(buf, 0);
449
450 // Create a temporary Command struct for parse_my_hdr
451 const struct Command my_hdr_cmd = { .name = "my_hdr", .data = 0 };
452 parse_my_hdr(&my_hdr_cmd, buf, err); /* adds to UserHeader */
453 }
454
455 p = mutt_str_getenv("EMAIL");
456 if (p)
457 config_str_set_initial(cs, "from", p);
458
459 /* "$mailcap_path" precedence: config file, environment, code */
460 struct Buffer *mc = buf_pool_get();
461 struct Slist *sl_mc = NULL;
462 const char *env_mc = mutt_str_getenv("MAILCAPS");
463 if (env_mc)
464 {
465 sl_mc = slist_parse(env_mc, D_SLIST_SEP_COLON);
466 }
467 else
468 {
469 cs_str_initial_get(cs, "mailcap_path", mc);
471 buf_reset(mc);
472 }
473 slist_to_buffer(sl_mc, mc);
474 config_str_set_initial(cs, "mailcap_path", buf_string(mc));
475 slist_free(&sl_mc);
476 buf_pool_release(&mc);
477
478 /* "$tmp_dir" precedence: config file, environment, code */
479 const char *env_tmp = mutt_str_getenv("TMPDIR");
480 if (env_tmp)
481 config_str_set_initial(cs, "tmp_dir", env_tmp);
482
483 /* "$visual", "$editor" precedence: config file, environment, code */
484 const char *env_ed = mutt_str_getenv("VISUAL");
485 if (!env_ed)
486 env_ed = mutt_str_getenv("EDITOR");
487 if (!env_ed)
488 env_ed = "vi";
489 config_str_set_initial(cs, "editor", env_ed);
490
491 const char *charset = mutt_ch_get_langinfo_charset();
492 config_str_set_initial(cs, "charset", charset);
493 mutt_ch_set_charset(charset);
494 FREE(&charset);
495
496 char name[256] = { 0 };
497 const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
498 if (!c_real_name)
499 {
500 struct passwd *pw = getpwuid(getuid());
501 if (pw)
502 {
503 c_real_name = mutt_gecos_name(name, sizeof(name), pw);
504 }
505 }
506 config_str_set_initial(cs, "real_name", c_real_name);
507
508#ifdef HAVE_GETSID
509 /* Unset suspend by default if we're the session leader */
510 if (getsid(0) == getpid())
511 config_str_set_initial(cs, "suspend", "no");
512#endif
513
514 /* RFC2368, "4. Unsafe headers"
515 * The creator of a mailto URL can't expect the resolver of a URL to
516 * understand more than the "subject" and "body" headers. Clients that
517 * resolve mailto URLs into mail messages should be able to correctly
518 * create RFC822-compliant mail messages using the "subject" and "body"
519 * headers. */
520 add_to_stailq(&MailToAllow, "body");
521 add_to_stailq(&MailToAllow, "subject");
522 /* Cc, In-Reply-To, and References help with not breaking threading on
523 * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
525 add_to_stailq(&MailToAllow, "in-reply-to");
526 add_to_stailq(&MailToAllow, "references");
527
528 if (ARRAY_EMPTY(user_files))
529 {
530 const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
531
532 if (!xdg_cfg_home && NeoMutt->home_dir)
533 {
534 buf_printf(buf, "%s/.config", NeoMutt->home_dir);
535 xdg_cfg_home = buf_string(buf);
536 }
537
538 char *config = find_cfg(NeoMutt->home_dir, xdg_cfg_home);
539 if (config)
540 {
541 ARRAY_ADD(user_files, config);
542 }
543 }
544 else
545 {
546 ARRAY_FOREACH(cp, user_files)
547 {
548 buf_strcpy(buf, *cp);
549 FREE(cp);
550 buf_expand_path(buf);
551 ARRAY_SET(user_files, ARRAY_FOREACH_IDX_cp, buf_strdup(buf));
552 if (access(buf_string(buf), F_OK))
553 {
554 mutt_perror("%s", buf_string(buf));
555 goto done; // TEST10: neomutt -F missing
556 }
557 }
558 }
559
560 ARRAY_FOREACH(cp, user_files)
561 {
562 if (*cp && !mutt_str_equal(*cp, "/dev/null"))
563 {
564 cs_str_string_set(cs, "alias_file", *cp, NULL);
565 break;
566 }
567 }
568
569 /* Process the global rc file if it exists and the user hasn't explicitly
570 * requested not to via "-n". */
571 if (!skip_sys_rc)
572 {
573 do
574 {
576 break;
577
578 buf_printf(buf, "%s/neomuttrc", SYSCONFDIR);
579 if (access(buf_string(buf), F_OK) == 0)
580 break;
581
582 buf_printf(buf, "%s/Muttrc", SYSCONFDIR);
583 if (access(buf_string(buf), F_OK) == 0)
584 break;
585
586 buf_printf(buf, "%s/neomuttrc", PKGDATADIR);
587 if (access(buf_string(buf), F_OK) == 0)
588 break;
589
590 buf_printf(buf, "%s/Muttrc", PKGDATADIR);
591 } while (false);
592
593 if (access(buf_string(buf), F_OK) == 0)
594 {
595 if (source_rc(buf_string(buf), err) != 0)
596 {
597 mutt_error("%s", buf_string(err));
598 need_pause = true; // TEST11: neomutt (error in /etc/neomuttrc)
599 }
600 }
601 }
602
603 /* Read the user's initialization file. */
604 ARRAY_FOREACH(cp, user_files)
605 {
606 if (*cp)
607 {
608 if (source_rc(*cp, err) != 0)
609 {
610 mutt_error("%s", buf_string(err));
611 need_pause = true; // TEST12: neomutt (error in ~/.neomuttrc)
612 }
613 }
614 }
615
616 if (execute_commands(commands) != 0)
617 need_pause = true; // TEST13: neomutt -e broken
618
619 if (!get_hostname(cs))
620 goto done;
621
622 /* The command line overrides the config */
623 if (!buf_is_empty(dlevel))
624 cs_str_reset(cs, "debug_level", NULL);
625 if (!buf_is_empty(dfile))
626 cs_str_reset(cs, "debug_file", NULL);
627
628 if (mutt_log_start() < 0)
629 {
630 mutt_perror("log file");
631 goto done;
632 }
633
634 if (need_pause && OptGui)
635 {
637 if (mutt_any_key_to_continue(NULL) == 'q')
638 goto done; // TEST14: neomutt -e broken (press 'q')
639 }
640
641 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
642 if (mutt_file_mkdir(c_tmp_dir, S_IRWXU) < 0)
643 {
644 mutt_error(_("Can't create %s: %s"), c_tmp_dir, strerror(errno));
645 goto done;
646 }
647
648 rc = 0;
649
650done:
651 buf_pool_release(&err);
652 buf_pool_release(&buf);
653 return rc;
654}
#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_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:223
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(const struct Command *cmd, struct Buffer *line, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
Definition commands.c:916
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:229
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition main.c:309
static int execute_commands(struct StringArray *sa)
Execute a set of NeoMutt commands.
Definition main.c:193
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:55
char * home_dir
User's home directory.
Definition neomutt.h:54
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 663 of file main.c.

664{
665 int rc = 0;
666 const char **cp = NULL;
667 ARRAY_FOREACH(cp, queries)
668 {
669 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, *cp);
670 if (!he)
671 {
672 mutt_warning(_("Unknown option %s"), *cp);
673 rc = 1;
674 continue;
675 }
676
677 if (he->type & D_INTERNAL_DEPRECATED)
678 {
679 mutt_warning(_("Option %s is deprecated"), *cp);
680 rc = 1;
681 continue;
682 }
683
684 ARRAY_ADD(hea, he);
685 }
686
687 return rc; // TEST16: neomutt -Q charset
688}
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 694 of file main.c.

695{
696 static const char *names[] = { "folder", "mbox", "postponed", "record" };
697
698 struct Buffer *value = buf_pool_get();
699 for (size_t i = 0; i < countof(names); i++)
700 {
701 struct HashElem *he = cs_get_elem(cs, names[i]);
702 if (!he)
703 continue;
704 buf_reset(value);
705 cs_he_initial_get(cs, he, value);
706 buf_expand_path_regex(value, false);
707 config_he_set_initial(cs, he, value->data);
708 }
709 buf_pool_release(&value);
710}
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 717 of file main.c.

718{
719 struct Buffer *value = buf_pool_get();
720 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
721 struct HashElem **hep = NULL;
722
723 ARRAY_FOREACH(hep, &hea)
724 {
725 struct HashElem *he = *hep;
726 if (!(he->type & D_L10N_STRING))
727 continue;
728
729 buf_reset(value);
730 cs_he_initial_get(cs, he, value);
731
732 // Lookup the translation
733 const char *l10n = gettext(buf_string(value));
734 config_he_set_initial(cs, he, l10n);
735 }
736
737 ARRAY_FREE(&hea);
738 buf_pool_release(&value);
739}
#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 747 of file main.c.

748{
749 /* should come before initscr() so that ncurses 4.2 doesn't try to install
750 * its own SIGWINCH handler */
752
753 if (!initscr())
754 {
755 mutt_error(_("Error initializing terminal"));
756 return 1;
757 }
758
759 colors_init();
760 keypad(stdscr, true);
761 cbreak();
762 noecho();
763 nonl();
764 typeahead(-1); /* simulate smooth scrolling */
765 meta(stdscr, true);
767 /* Now that curses is set up, we drop back to normal screen mode.
768 * This simplifies displaying error messages to the user.
769 * The first call to refresh() will swap us back to curses screen mode. */
770 endwin();
771 return 0;
772}
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 777 of file main.c.

778{
779 setlocale(LC_ALL, "");
780
781#ifdef ENABLE_NLS
782 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
783 if (domdir)
784 bindtextdomain(PACKAGE, domdir);
785 else
786 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
787 textdomain(PACKAGE);
788#endif
789#ifndef LOCALES_HACK
790 /* Do we have a locale definition? */
791 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
792 {
793 OptLocales = true;
794 }
795#endif
796}
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 805 of file main.c.

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

847{
848 const char *header = ""; // Do not merge these two lines
849 header = _(header); // otherwise the .po files will end up badly ordered
850 const char *label = "Language:"; // the start of the lookup/needle
851 const char *lang = mutt_istr_find(header, label);
852 int len = 64;
853 if (lang)
854 {
855 lang += strlen(label); // skip label
856 SKIPWS(lang);
857 char *nl = strchr(lang, '\n');
858 if (nl)
859 len = (nl - lang);
860 }
861 else
862 {
863 lang = "NONE";
864 }
865
866 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
867}
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 872 of file main.c.

873{
874 const char *term = mutt_str_getenv("TERM");
875 const char *color_term = mutt_str_getenv("COLORTERM");
876 bool true_color = false;
877#ifdef NEOMUTT_DIRECT_COLORS
878 true_color = true;
879#endif
880
881 mutt_debug(LL_DEBUG1, "GUI:\n");
882 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
883 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
884 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
885 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
886 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
887 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
888 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
889 RootWindow->state.rows);
890}
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 929 of file main.c.

930{
931 if (!help->is_set)
932 return true;
933
935
936 const bool tty = isatty(STDOUT_FILENO);
937
938 if (help->help)
939 {
940 show_cli(help->mode, tty);
941 }
942 else if (help->license)
943 {
945 }
946 else
947 {
948 print_version(stdout, tty);
949 }
950
951 return false; // Stop
952}
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 960 of file main.c.

961{
962 if (!shared->is_set)
963 return true;
964
965 if (!buf_is_empty(&shared->log_file))
966 config_str_set_initial(cs, "debug_file", buf_string(&shared->log_file));
967
968 if (!buf_is_empty(&shared->log_level))
969 {
970 const char *dlevel = buf_string(&shared->log_level);
971 short num = 0;
972 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
973 {
974 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
975 return false;
976 }
977
978 config_str_set_initial(cs, "debug_level", dlevel);
979 }
980
981 return true;
982}
@ 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 989 of file main.c.

990{
991 const char *cli_nntp = NULL;
992 if (!buf_is_empty(server))
993 cli_nntp = buf_string(server);
994
995 /* "$news_server" precedence: command line, config file, environment, system file */
996 if (cli_nntp)
997 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
998
999 if (!cli_nntp)
1000 cli_nntp = mutt_str_getenv("NNTPSERVER");
1001
1002 if (!cli_nntp)
1003 {
1004 char buf[1024] = { 0 };
1005 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
1006 }
1007
1008 if (cli_nntp)
1009 config_str_set_initial(cs, "news_server", cli_nntp);
1010}
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 1018 of file main.c.

1019{
1020 if (!ci->is_set)
1021 return true;
1022
1023 if (ci->dump_config || !ARRAY_EMPTY(&ci->queries))
1024 {
1025 const bool tty = isatty(STDOUT_FILENO);
1026
1028 if (tty)
1029 cdflags |= CS_DUMP_LINK_DOCS;
1030 if (ci->hide_sensitive)
1031 cdflags |= CS_DUMP_HIDE_SENSITIVE;
1032 if (ci->show_help)
1033 cdflags |= CS_DUMP_SHOW_DOCS;
1034
1035 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
1036 if (ci->dump_config)
1037 {
1039 hea = get_elem_list(cs, gel_flags);
1040 }
1041 else
1042 {
1043 get_elem_queries(&ci->queries, &hea);
1044 }
1045
1046 dump_config(cs, &hea, cdflags, stdout);
1047 ARRAY_FREE(&hea);
1048 }
1049 else if (!ARRAY_EMPTY(&ci->alias_queries))
1050 {
1051 const char **cp = NULL;
1053 {
1054 struct AddressList *al = alias_lookup(*cp);
1055 if (al)
1056 {
1057 /* output in machine-readable form */
1058 mutt_addrlist_to_intl(al, NULL);
1059 struct Buffer *buf = buf_pool_get();
1060 mutt_addrlist_write(al, buf, false);
1061 printf("%s\n", buf_string(buf));
1062 buf_pool_release(&buf);
1063 }
1064 else
1065 {
1066 printf("%s\n", NONULL(*cp)); // TEST19: neomutt -A unknown
1067 }
1068 }
1069 }
1070
1071 return false; // Stop
1072}
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:663
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 1082 of file main.c.

1083{
1084 struct Email *e = NULL;
1085 SendFlags sendflags = SEND_NO_FLAGS;
1086 int rc = 1;
1087 bool repeat_error = false;
1088 struct Buffer *expanded_infile = buf_pool_get();
1089 struct Buffer *tempfile = buf_pool_get();
1090 struct ConfigSet *cs = NULL;
1091 struct CommandLine *cli = command_line_new();
1092
1094
1095 /* sanity check against stupid administrators */
1096 if (getegid() != getgid())
1097 {
1098 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
1099 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
1100 }
1101
1102 init_locale();
1103 OptGui = true;
1104
1105 cs = cs_new(500);
1106 if (!cs)
1107 goto main_curses;
1108
1109 NeoMutt = neomutt_new(cs);
1110
1111 NeoMutt->env = envlist_init(envp);
1114
1115 init_config(cs);
1116
1117 cli_parse(argc, argv, cli);
1118
1119 if (!show_help(&cli->help))
1120 goto main_ok;
1121
1122 // Change the current umask, and save the original one
1123 NeoMutt->user_default_umask = umask(077);
1124 subjrx_init();
1125 attach_init();
1127
1128#ifdef USE_DEBUG_NOTIFY
1130#endif
1131
1132 if (!get_user_info(cs))
1133 goto main_exit;
1134
1135 reset_tilde(cs);
1136#ifdef ENABLE_NLS
1137 localise_config(cs);
1138#endif
1139
1140 if (!init_logging(&cli->shared, cs))
1141 goto main_exit;
1142
1143 mutt_log_prep();
1146 mutt_debug(LL_DEBUG1, "user's umask %03o\n", NeoMutt->user_default_umask);
1147 mutt_debug(LL_DEBUG3, "umask set to 077\n");
1148
1149 /* Check for a batch send. */
1150 if (!isatty(STDIN_FILENO) || !ARRAY_EMPTY(&cli->info.queries) ||
1152 {
1153 OptGui = false;
1154 sendflags |= SEND_BATCH;
1157 }
1158
1159 /* Check to make sure stdout is available in curses mode. */
1160 if (OptGui && !isatty(STDOUT_FILENO))
1161 goto main_curses;
1162
1163 /* This must come before mutt_init() because curses needs to be started
1164 * before calling the init_pair() function to set the color scheme. */
1165 if (OptGui)
1166 {
1167 int crc = start_curses();
1168 if (crc != 0)
1169 goto main_curses; // TEST08: can't test -- fake term?
1170 }
1171
1172 /* Always create the mutt_windows because batch mode has some shared code
1173 * paths that end up referencing them. */
1174 rootwin_new();
1175
1176 if (OptGui)
1177 {
1178 /* check whether terminal status is supported (must follow curses init) */
1181 log_gui();
1182 }
1183
1184 alias_init();
1185 commands_init();
1186 hooks_init();
1188 imap_init();
1189 lua_init();
1191 km_init();
1192
1193 menu_init();
1194 sb_init();
1195#ifdef USE_NOTMUCH
1196 nm_init();
1197#endif
1198
1199 /* set defaults and read init files */
1200 int rc2 = mutt_init(cs, &cli->shared.log_level, &cli->shared.log_file,
1202 &cli->shared.commands);
1203 if (rc2 != 0)
1204 goto main_curses;
1205
1208
1209#ifdef USE_NOTMUCH
1210 const bool c_virtual_spool_file = cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
1211 if (c_virtual_spool_file)
1212 {
1213 /* Find the first virtual folder and open it */
1214 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_NOTMUCH);
1215 struct Mailbox **mp = ARRAY_FIRST(&ma);
1216 if (mp)
1217 cs_str_string_set(cs, "spool_file", mailbox_path(*mp), NULL);
1218 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
1219 }
1220#endif
1221
1223
1224 init_nntp(&cli->tui.nntp_server, cs);
1225
1226 /* Initialize crypto backends. */
1227 crypt_init();
1228
1229 if (!buf_is_empty(&cli->shared.mbox_type) &&
1230 !config_str_set_initial(cs, "mbox_type", buf_string(&cli->shared.mbox_type)))
1231 {
1232 goto main_curses;
1233 }
1234
1235 if (!dump_info(&cli->info, cs))
1236 goto main_ok;
1237
1238 if (OptGui)
1239 {
1241 clear();
1245 }
1246
1247#ifdef USE_AUTOCRYPT
1248 /* Initialize autocrypt after curses messages are working,
1249 * because of the initial account setup screens. */
1250 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
1251 if (c_autocrypt)
1252 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
1253#endif
1254
1255 /* Create the `$folder` directory if it doesn't exist. */
1256 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1257 if (OptGui && c_folder)
1258 {
1259 struct stat st = { 0 };
1260 struct Buffer *fpath = buf_pool_get();
1261
1262 buf_strcpy(fpath, c_folder);
1263 buf_expand_path(fpath);
1264 bool skip = false;
1265 /* we're not connected yet - skip mail folder creation */
1266 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
1267 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
1268 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
1269 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
1270 {
1271 char msg2[256] = { 0 };
1272 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
1273 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
1274 {
1275 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
1276 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
1277 }
1278 }
1279 buf_pool_release(&fpath);
1280 }
1281
1282 StartupComplete = true;
1283
1287
1288 if (cli->tui.start_postponed)
1289 {
1290 if (OptGui)
1291 mutt_flushinp();
1292 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1293 rc = 0;
1294 // TEST23: neomutt -p (postponed message, cancel)
1295 // TEST24: neomutt -p (no postponed message)
1297 repeat_error = true;
1298 goto main_curses;
1299 }
1300 else if (cli->send.is_set)
1301 {
1302 FILE *fp_in = NULL;
1303 FILE *fp_out = NULL;
1304 const char *infile = NULL;
1305 char *bodytext = NULL;
1306 const char *bodyfile = NULL;
1307 int rv = 0;
1308
1309 if (OptGui)
1310 mutt_flushinp();
1311
1312 e = email_new();
1313 e->env = mutt_env_new();
1314
1315 const char **cp = NULL;
1316 ARRAY_FOREACH(cp, &cli->send.bcc_list)
1317 {
1318 mutt_addrlist_parse(&e->env->bcc, *cp);
1319 }
1320
1321 ARRAY_FOREACH(cp, &cli->send.cc_list)
1322 {
1323 mutt_addrlist_parse(&e->env->cc, *cp);
1324 }
1325
1326 ARRAY_FOREACH(cp, &cli->send.addresses)
1327 {
1328 if (url_check_scheme(*cp) == U_MAILTO)
1329 {
1330 if (!mutt_parse_mailto(e->env, &bodytext, *cp))
1331 {
1332 mutt_error(_("Failed to parse mailto: link"));
1333 email_free(&e);
1334 goto main_curses; // TEST25: neomutt mailto:?
1335 }
1336 }
1337 else
1338 {
1339 mutt_addrlist_parse(&e->env->to, *cp);
1340 }
1341 }
1342
1343 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1344 if (buf_is_empty(&cli->send.draft_file) && c_auto_edit &&
1345 TAILQ_EMPTY(&e->env->to) && TAILQ_EMPTY(&e->env->cc))
1346 {
1347 mutt_error(_("No recipients specified"));
1348 email_free(&e);
1349 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1350 }
1351
1352 if (!buf_is_empty(&cli->send.subject))
1353 {
1354 /* prevent header injection */
1357 }
1358
1359 if (!buf_is_empty(&cli->send.draft_file))
1360 {
1361 infile = buf_string(&cli->send.draft_file);
1362 }
1363 else if (!buf_is_empty(&cli->send.include_file))
1364 {
1365 infile = buf_string(&cli->send.include_file);
1366 }
1367 else
1368 {
1369 cli->send.edit_infile = false;
1370 }
1371
1372 if (infile || bodytext)
1373 {
1374 /* Prepare fp_in and expanded_infile. */
1375 if (infile)
1376 {
1377 if (mutt_str_equal("-", infile))
1378 {
1379 if (cli->send.edit_infile)
1380 {
1381 mutt_error(_("Can't use -E flag with stdin"));
1382 email_free(&e);
1383 goto main_curses; // TEST27: neomutt -E -H -
1384 }
1385 fp_in = stdin;
1386 }
1387 else
1388 {
1389 buf_strcpy(expanded_infile, infile);
1390 buf_expand_path(expanded_infile);
1391 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1392 if (!fp_in)
1393 {
1394 mutt_perror("%s", buf_string(expanded_infile));
1395 email_free(&e);
1396 goto main_curses; // TEST28: neomutt -E -H missing
1397 }
1398 }
1399 }
1400
1401 if (cli->send.edit_infile)
1402 {
1403 /* If editing the infile, keep it around afterwards so
1404 * it doesn't get unlinked, and we can rebuild the draft_file */
1405 sendflags |= SEND_NO_FREE_HEADER;
1406 }
1407 else
1408 {
1409 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1410 * Note: stdin is always copied to a tempfile, ensuring draft_file
1411 * can stat and get the correct st_size below. */
1412 buf_mktemp(tempfile);
1413
1414 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1415 if (!fp_out)
1416 {
1417 mutt_file_fclose(&fp_in);
1418 mutt_perror("%s", buf_string(tempfile));
1419 email_free(&e);
1420 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1421 }
1422 if (fp_in)
1423 {
1424 mutt_file_copy_stream(fp_in, fp_out);
1425 if (fp_in == stdin)
1426 sendflags |= SEND_CONSUMED_STDIN;
1427 else
1428 mutt_file_fclose(&fp_in);
1429 }
1430 else if (bodytext)
1431 {
1432 fputs(bodytext, fp_out);
1433 }
1434 mutt_file_fclose(&fp_out);
1435
1436 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1437 if (!fp_in)
1438 {
1439 mutt_perror("%s", buf_string(tempfile));
1440 email_free(&e);
1441 goto main_curses; // TEST30: can't test
1442 }
1443 }
1444
1445 /* Parse the draft_file into the full Email/Body structure.
1446 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1447 * our e->body. */
1448 if (!buf_is_empty(&cli->send.draft_file))
1449 {
1450 struct Envelope *opts_env = e->env;
1451 struct stat st = { 0 };
1452
1453 sendflags |= SEND_DRAFT_FILE;
1454
1455 /* Set up a tmp Email with just enough information so that
1456 * mutt_prepare_template() can parse the message in fp_in. */
1457 struct Email *e_tmp = email_new();
1458 e_tmp->offset = 0;
1459 e_tmp->body = mutt_body_new();
1460 if (fstat(fileno(fp_in), &st) != 0)
1461 {
1462 mutt_perror("%s", buf_string(&cli->send.draft_file));
1463 email_free(&e);
1464 email_free(&e_tmp);
1465 goto main_curses; // TEST31: can't test
1466 }
1467 e_tmp->body->length = st.st_size;
1468
1469 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1470 {
1471 mutt_error(_("Can't parse message template: %s"),
1472 buf_string(&cli->send.draft_file));
1473 email_free(&e);
1474 email_free(&e_tmp);
1475 goto main_curses;
1476 }
1477
1478 /* Scan for neomutt header to set `$resume_draft_files` */
1479 struct ListNode *tmp = NULL;
1480 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1481 struct ListNode *np = NULL;
1482 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1483 {
1484 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1485 {
1486 if (c_resume_edited_draft_files)
1487 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1488
1489 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1490 FREE(&np->data);
1491 FREE(&np);
1492 }
1493 }
1494
1495 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1496 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1497 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1498 if (opts_env->subject)
1499 mutt_env_set_subject(e->env, opts_env->subject);
1500
1501 mutt_env_free(&opts_env);
1502 email_free(&e_tmp);
1503 }
1504 else if (cli->send.edit_infile)
1505 {
1506 /* Editing the include_file: pass it directly in.
1507 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1508 bodyfile = buf_string(expanded_infile);
1509 }
1510 else
1511 {
1512 // For bodytext and unedited include_file: use the tempfile.
1513 bodyfile = buf_string(tempfile);
1514 }
1515
1516 mutt_file_fclose(&fp_in);
1517 }
1518
1519 FREE(&bodytext);
1520
1521 if (!ARRAY_EMPTY(&cli->send.attach))
1522 {
1523 struct Body *b = e->body;
1524
1525 while (b && b->next)
1526 b = b->next;
1527
1528 ARRAY_FOREACH(cp, &cli->send.attach)
1529 {
1530 if (b)
1531 {
1533 b = b->next;
1534 }
1535 else
1536 {
1538 e->body = b;
1539 }
1540 if (!b)
1541 {
1542 mutt_error(_("%s: unable to attach file"), *cp);
1543 email_free(&e);
1544 goto main_curses; // TEST32: neomutt john@example.com -a missing
1545 }
1546 }
1547 }
1548
1549 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1550 /* We WANT the "Mail sent." and any possible, later error */
1552 if (ErrorBufMessage)
1553 mutt_message("%s", ErrorBuf);
1554
1555 if (cli->send.edit_infile)
1556 {
1557 if (!buf_is_empty(&cli->send.draft_file))
1558 {
1559 if (truncate(buf_string(expanded_infile), 0) == -1)
1560 {
1561 mutt_perror("%s", buf_string(expanded_infile));
1562 email_free(&e);
1563 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1564 }
1565 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1566 if (!fp_out)
1567 {
1568 mutt_perror("%s", buf_string(expanded_infile));
1569 email_free(&e);
1570 goto main_curses; // TEST34: can't test
1571 }
1572
1573 /* If the message was sent or postponed, these will already
1574 * have been done. */
1575 if (rv < 0)
1576 {
1577 if (e->body->next)
1578 e->body = mutt_make_multipart(e->body);
1580 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1581 mutt_env_to_intl(e->env, NULL, NULL);
1582 }
1583
1584 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1586 c_crypt_protected_headers_read &&
1588 NeoMutt->sub);
1589 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1590 if (c_resume_edited_draft_files)
1591 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1592 fputc('\n', fp_out);
1593 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1594 {
1595 mutt_file_fclose(&fp_out);
1596 email_free(&e);
1597 goto main_curses; // TEST35: can't test
1598 }
1599 mutt_file_fclose(&fp_out);
1600 }
1601
1602 email_free(&e);
1603 }
1604
1605 /* !edit_infile && draft_file will leave the tempfile around */
1606 if (!buf_is_empty(tempfile))
1607 unlink(buf_string(tempfile));
1608
1610
1611 if (rv != 0)
1612 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1613 }
1614 else if (sendflags & SEND_BATCH)
1615 {
1616 /* This guards against invoking `neomutt < /dev/null` and accidentally
1617 * sending an email due to a my_hdr or other setting. */
1618 mutt_error(_("No recipients specified"));
1619 goto main_curses;
1620 }
1621 else
1622 {
1623 struct Buffer *folder = &cli->tui.folder;
1624 bool explicit_folder = !buf_is_empty(folder);
1625
1626 if (cli->tui.start_new_mail)
1627 {
1628 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1629 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1631 if (mutt_mailbox_check(NULL, csflags) == 0)
1632 {
1633 mutt_message(_("No mailbox with new mail"));
1634 repeat_error = true;
1635 goto main_curses; // TEST37: neomutt -Z (no new mail)
1636 }
1637 buf_reset(folder);
1638 mutt_mailbox_next(NULL, folder);
1639 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1640 }
1641 else if (cli->tui.start_nntp || cli->tui.start_browser)
1642 {
1643 if (cli->tui.start_nntp)
1644 {
1645 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1646 OptNews = true;
1647 CurrentNewsSrv = nntp_select_server(NULL, c_news_server, false);
1648 if (!CurrentNewsSrv)
1649 goto main_curses; // TEST38: neomutt -G (unset news_server)
1650 }
1651 else if (ARRAY_EMPTY(&NeoMutt->accounts))
1652 {
1653 mutt_error(_("No incoming mailboxes defined"));
1654 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1655 }
1656 buf_reset(folder);
1657 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1658 if (buf_is_empty(folder))
1659 {
1660 goto main_ok; // TEST40: neomutt -y (quit selection)
1661 }
1662 }
1663
1664 if (buf_is_empty(folder))
1665 {
1666 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1667 if (c_spool_file)
1668 {
1669 // Check if `$spool_file` corresponds a mailboxes' description.
1670 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1671 if (m_desc)
1672 buf_strcpy(folder, m_desc->realpath);
1673 else
1674 buf_strcpy(folder, c_spool_file);
1675 }
1676 else if (c_folder)
1677 {
1678 buf_strcpy(folder, c_folder);
1679 }
1680 /* else no folder */
1681 }
1682
1683 if (OptNews)
1684 {
1685 OptNews = false;
1686 buf_alloc(folder, PATH_MAX);
1687 nntp_expand_path(folder->data, folder->dsize, &CurrentNewsSrv->conn->account);
1688 }
1689 else
1690 {
1691 buf_expand_path(folder);
1692 }
1693
1696
1697 if (cli->tui.start_any_mail || cli->tui.start_new_mail)
1698 {
1699 /* check to see if there are any messages in the folder */
1700 switch (mx_path_is_empty(folder))
1701 {
1702 case -1:
1703 mutt_perror("%s", buf_string(folder));
1704 goto main_curses; // TEST41: neomutt -z -f missing
1705 case 1:
1706 mutt_error(_("Mailbox is empty"));
1707 goto main_curses; // TEST42: neomutt -z -f /dev/null
1708 }
1709 }
1710
1711 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1712 // Take a copy of the name just in case the hook alters m_cur
1713 const char *name = m_cur ? mutt_str_dup(m_cur->name) : NULL;
1715 FREE(&name);
1717 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1719
1721 window_redraw(NULL);
1722
1723 repeat_error = true;
1724 struct Mailbox *m = mx_resolve(buf_string(folder));
1725 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1726 if (!mx_mbox_open(m, (cli->tui.read_only || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1727 {
1728 if (m->account)
1730
1731 mailbox_free(&m);
1732 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1733 repeat_error = false;
1734 }
1735 if (m || !explicit_folder)
1736 {
1737 struct MuttWindow *dlg = index_pager_init();
1738 dialog_push(dlg);
1739
1741 m = dlg_index(dlg, m);
1743 mailbox_free(&m);
1744
1745 dialog_pop();
1746 mutt_window_free(&dlg);
1748 repeat_error = false;
1749 }
1751#ifdef USE_SASL_CYRUS
1753#endif
1754#ifdef USE_SASL_GNU
1756#endif
1757#ifdef USE_AUTOCRYPT
1759#endif
1760 // TEST43: neomutt (no change to mailbox)
1761 // TEST44: neomutt (change mailbox)
1762 }
1763
1764main_ok:
1765 rc = 0;
1766main_curses:
1767 mutt_endwin();
1769 /* Repeat the last message to the user */
1770 if (repeat_error && ErrorBufMessage)
1771 puts(ErrorBuf);
1772main_exit:
1773 if (NeoMutt && NeoMutt->sub)
1774 {
1778 }
1780 buf_pool_release(&expanded_infile);
1781 buf_pool_release(&tempfile);
1785 if (NeoMutt)
1789 menu_cleanup();
1790 crypt_cleanup();
1792 command_line_free(&cli);
1793
1795
1796 alias_cleanup();
1797 sb_cleanup();
1798
1804
1806
1807 /* Lists of strings */
1816
1818
1820 FREE(&LastFolder);
1822
1824
1826
1829
1831 if (NeoMutt)
1833
1834 lua_cleanup();
1842 cs_free(&cs);
1844 mutt_log_stop();
1845 return rc;
1846}
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:48
void alternates_init(void)
Set up the alternates lists.
Definition alternates.c:59
#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:105
void attach_cleanup(void)
Free the attachments lists.
Definition commands.c:91
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:1936
bool commands_init(void)
Initialize commands array and register default commands.
Definition commands.c:2170
void mutt_comp_init(void)
Setup Compressed Mailbox commands.
Definition compress.c:100
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 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:2382
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:895
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:1624
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition hook.c:1029
void mutt_folder_hook(const char *path, const char *desc)
Perform a folder hook.
Definition hook.c:1291
void hooks_init(void)
Setup feature commands.
Definition hook.c:1769
#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:573
void imap_init(void)
Setup feature commands.
Definition imap.c:102
void km_init(void)
Initialise all the menu keybindings.
Definition init.c:104
void mutt_keys_cleanup(void)
Free the key maps.
Definition init.c:165
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition init.c:181
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:162
void lua_cleanup(void)
Clean up Lua.
Definition commands.c:170
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition main.c:777
static void localise_config(struct ConfigSet *cs)
Localise some config.
Definition main.c:717
static bool init_logging(struct CliShared *shared, struct ConfigSet *cs)
Initialise the Logging.
Definition main.c:960
static void log_translation(void)
Log the translation being used.
Definition main.c:846
static void log_gui(void)
Log info about the GUI.
Definition main.c:872
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition main.c:694
static void init_nntp(struct Buffer *server, struct ConfigSet *cs)
Initialise the NNTP config.
Definition main.c:989
static bool show_help(struct CliHelp *help)
Show the Help.
Definition main.c:929
static int start_curses(void)
Start the Curses UI.
Definition main.c:747
static bool dump_info(struct CliInfo *ci, struct ConfigSet *cs)
Show config info.
Definition main.c:1018
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition main.c:805
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:395
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:189
struct NeoMutt * neomutt_new(struct ConfigSet *cs)
Create the main NeoMutt object.
Definition neomutt.c:50
void neomutt_free(struct NeoMutt **ptr)
Free a NeoMutt.
Definition neomutt.c:88
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition neomutt.h:68
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:1490
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:2035
#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:607
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition sendlib.c:740
void sb_init(void)
Set up the Sidebar.
Definition sidebar.c:211
void sb_cleanup(void)
Clean up the Sidebar.
Definition sidebar.c:227
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:48
struct CommandArray commands
NeoMutt commands.
Definition neomutt.h:51
struct Notify * notify_resize
Window resize notifications handler.
Definition neomutt.h:45
char ** env
Private copy of the environment variables.
Definition neomutt.h:56
mode_t user_default_umask
User's default file writing permissions (inferred from umask)
Definition neomutt.h:50
struct Notify * notify
Notifications handler.
Definition neomutt.h:44
void subjrx_init(void)
Create new Subject Regex List.
Definition subjectrx.c:54
void subjrx_cleanup(void)
Free the Subject Regex List.
Definition subjectrx.c:45
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 183 of file main.c.