NeoMutt  2025-01-09-81-g753ae0
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 <stdint.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 "color/lib.h"
#include "compmbox/lib.h"
#include "history/lib.h"
#include "imap/lib.h"
#include "index/lib.h"
#include "key/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"
#include "mutt_lua.h"

Go to the source code of this file.

Macros

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

Typedefs

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

Functions

static int execute_commands (struct ListHead *p)
 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, const char *dlevel, const char *dfile, bool skip_sys_rc, struct ListHead *commands)
 Initialise NeoMutt.
 
static int get_elem_queries (struct ListHead *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 bool usage (void)
 Display NeoMutt command line.
 
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 -.
 
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.

◆ MUTT_CLI_NO_FLAGS

#define MUTT_CLI_NO_FLAGS   0

No flags are set.

Definition at line 202 of file main.c.

◆ MUTT_CLI_IGNORE

#define MUTT_CLI_IGNORE   (1 << 0)

-z Open first mailbox if it has mail

Definition at line 203 of file main.c.

◆ MUTT_CLI_MAILBOX

#define MUTT_CLI_MAILBOX   (1 << 1)

-Z Open first mailbox if is has new mail

Definition at line 204 of file main.c.

◆ MUTT_CLI_NOSYSRC

#define MUTT_CLI_NOSYSRC   (1 << 2)

-n Do not read the system-wide config file

Definition at line 205 of file main.c.

◆ MUTT_CLI_RO

#define MUTT_CLI_RO   (1 << 3)

-R Open mailbox in read-only mode

Definition at line 206 of file main.c.

◆ MUTT_CLI_SELECT

#define MUTT_CLI_SELECT   (1 << 4)

-y Start with a list of all mailboxes

Definition at line 207 of file main.c.

◆ MUTT_CLI_NEWS

#define MUTT_CLI_NEWS   (1 << 5)

-g/-G Start with a list of all newsgroups

Definition at line 208 of file main.c.

Typedef Documentation

◆ CliFlags

typedef uint8_t CliFlags

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

Definition at line 201 of file main.c.

Function Documentation

◆ execute_commands()

static int execute_commands ( struct ListHead *  p)
static

Execute a set of NeoMutt commands.

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

Definition at line 217 of file main.c.

218{
219 int rc = 0;
220 struct Buffer *err = buf_pool_get();
221
222 struct ListNode *np = NULL;
223 STAILQ_FOREACH(np, p, entries)
224 {
225 enum CommandResult rc2 = parse_rc_line(np->data, err);
226 if (rc2 == MUTT_CMD_ERROR)
227 mutt_error(_("Error in command line: %s"), buf_string(err));
228 else if (rc2 == MUTT_CMD_WARNING)
229 mutt_warning(_("Warning in command line: %s"), buf_string(err));
230
231 if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
232 {
233 buf_pool_release(&err);
234 return -1;
235 }
236 }
237 buf_pool_release(&err);
238
239 return rc;
240}
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:36
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
#define mutt_warning(...)
Definition: logging2.h:90
#define mutt_error(...)
Definition: logging2.h:92
#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
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
enum CommandResult parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: rc.c:104
String manipulation buffer.
Definition: buffer.h:36
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
+ 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 249 of file main.c.

250{
251 const char *names[] = {
252 "neomuttrc",
253 "muttrc",
254 NULL,
255 };
256
257 const char *locations[][2] = {
258 { xdg_cfg_home, "neomutt/" },
259 { xdg_cfg_home, "mutt/" },
260 { home, ".neomutt/" },
261 { home, ".mutt/" },
262 { home, "." },
263 { NULL, NULL },
264 };
265
266 for (int i = 0; locations[i][0] || locations[i][1]; i++)
267 {
268 if (!locations[i][0])
269 continue;
270
271 for (int j = 0; names[j]; j++)
272 {
273 char buf[256] = { 0 };
274
275 snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
276 if (access(buf, F_OK) == 0)
277 return mutt_str_dup(buf);
278 }
279 }
280
281 return NULL;
282}
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
+ 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 290 of file main.c.

291{
292 char *mailname = NULL;
293 static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
294
295 for (size_t i = 0; i < mutt_array_size(mn_files); i++)
296 {
297 FILE *fp = mutt_file_fopen(mn_files[i], "r");
298 if (!fp)
299 continue;
300
301 size_t len = 0;
302 mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
303 mutt_file_fclose(&fp);
304 if (mailname && *mailname)
305 break;
306
307 FREE(&mailname);
308 }
309
310 return mailname;
311}
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 FREE(x)
Definition: memory.h:55
#define mutt_array_size(x)
Definition: memory.h:38
+ 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 323 of file main.c.

324{
325 const char *short_host = NULL;
326 struct utsname utsname = { 0 };
327
328 const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
329 if (c_hostname)
330 {
331 short_host = c_hostname;
332 }
333 else
334 {
335 /* The call to uname() shouldn't fail, but if it does, the system is horribly
336 * broken, and the system's networking configuration is in an unreliable
337 * state. We should bail. */
338 if ((uname(&utsname)) == -1)
339 {
340 mutt_perror(_("unable to determine nodename via uname()"));
341 return false; // TEST09: can't test
342 }
343
344 short_host = utsname.nodename;
345 }
346
347 /* some systems report the FQDN instead of just the hostname */
348 char *dot = strchr(short_host, '.');
349 if (dot)
350 ShortHostname = mutt_strn_dup(short_host, dot - short_host);
351 else
352 ShortHostname = mutt_str_dup(short_host);
353
354 // All the code paths from here alloc memory for the fqdn
355 char *fqdn = mutt_str_dup(c_hostname);
356 if (!fqdn)
357 {
358 mutt_debug(LL_DEBUG1, "Setting $hostname\n");
359 /* now get FQDN. Use configured domain first, DNS next, then uname */
360#ifdef DOMAIN
361 /* we have a compile-time domain name, use that for `$hostname` */
362 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
363#else
364 fqdn = getmailname();
365 if (!fqdn)
366 {
367 struct Buffer *domain = buf_pool_get();
368 if (getdnsdomainname(domain) == 0)
369 {
370 mutt_str_asprintf(&fqdn, "%s.%s", NONULL(ShortHostname), buf_string(domain));
371 }
372 else
373 {
374 /* DNS failed, use the nodename. Whether or not the nodename had a '.'
375 * in it, we can use the nodename as the FQDN. On hosts where DNS is
376 * not being used, e.g. small network that relies on hosts files, a
377 * short host name is all that is required for SMTP to work correctly.
378 * It could be wrong, but we've done the best we can, at this point the
379 * onus is on the user to provide the correct hostname if the nodename
380 * won't work in their network. */
381 fqdn = mutt_str_dup(utsname.nodename);
382 }
383 buf_pool_release(&domain);
384 mutt_debug(LL_DEBUG1, "Hostname: %s\n", NONULL(fqdn));
385 }
386#endif
387 }
388
389 if (fqdn)
390 {
391 config_str_set_initial(cs, "hostname", fqdn);
392 FREE(&fqdn);
393 }
394
395 return true;
396}
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:38
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition: main.c:290
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:381
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:804
#define NONULL(x)
Definition: string2.h:37
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,
const char *  dlevel,
const char *  dfile,
bool  skip_sys_rc,
struct ListHead *  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
commandsList of config commands to execute
Return values
0Success
1Error

Definition at line 408 of file main.c.

410{
411 bool need_pause = false;
412 int rc = 1;
413 struct Buffer *err = buf_pool_get();
414 struct Buffer *buf = buf_pool_get();
415
416#ifdef NEOMUTT_DIRECT_COLORS
417 /* Test if we run in a terminal which supports direct colours.
418 *
419 * The user/terminal can indicate their capability independent of the
420 * terminfo file by setting the COLORTERM environment variable to "truecolor"
421 * or "24bit" (case sensitive).
422 *
423 * Note: This is to test is less about whether the terminal understands
424 * direct color commands but more about whether ncurses believes it can send
425 * them to the terminal, e.g. ncurses ignores COLORTERM.
426 */
427 if (COLORS == 16777216) // 2^24
428 {
429 /* Ncurses believes the Terminal supports it check the environment variable
430 * to respect the user's choice */
431 const char *env_colorterm = mutt_str_getenv("COLORTERM");
432 if (env_colorterm && (mutt_str_equal(env_colorterm, "truecolor") ||
433 mutt_str_equal(env_colorterm, "24bit")))
434 {
435 config_str_set_initial(cs, "color_directcolor", "yes");
436 }
437 }
438#endif
439
440 /* "$spool_file" precedence: config file, environment */
441 const char *p = mutt_str_getenv("MAIL");
442 if (!p)
443 p = mutt_str_getenv("MAILDIR");
444 if (!p)
445 {
446#ifdef HOMESPOOL
447 buf_concat_path(buf, NONULL(HomeDir), MAILPATH);
448#else
449 buf_concat_path(buf, MAILPATH, NONULL(Username));
450#endif
451 p = buf_string(buf);
452 }
453 config_str_set_initial(cs, "spool_file", p);
454
455 p = mutt_str_getenv("REPLYTO");
456 if (p)
457 {
458 struct Buffer *token = buf_pool_get();
459
460 buf_printf(buf, "Reply-To: %s", p);
461 buf_seek(buf, 0);
462 parse_my_hdr(token, buf, 0, err); /* adds to UserHeader */
463 buf_pool_release(&token);
464 }
465
466 p = mutt_str_getenv("EMAIL");
467 if (p)
468 config_str_set_initial(cs, "from", p);
469
470 /* "$mailcap_path" precedence: config file, environment, code */
471 struct Buffer *mc = buf_pool_get();
472 struct Slist *sl_mc = NULL;
473 const char *env_mc = mutt_str_getenv("MAILCAPS");
474 if (env_mc)
475 {
476 sl_mc = slist_parse(env_mc, D_SLIST_SEP_COLON);
477 }
478 else
479 {
480 cs_str_initial_get(cs, "mailcap_path", mc);
482 buf_reset(mc);
483 }
484 slist_to_buffer(sl_mc, mc);
485 config_str_set_initial(cs, "mailcap_path", buf_string(mc));
486 slist_free(&sl_mc);
487 buf_pool_release(&mc);
488
489 /* "$tmp_dir" precedence: config file, environment, code */
490 const char *env_tmp = mutt_str_getenv("TMPDIR");
491 if (env_tmp)
492 config_str_set_initial(cs, "tmp_dir", env_tmp);
493
494 /* "$visual", "$editor" precedence: config file, environment, code */
495 const char *env_ed = mutt_str_getenv("VISUAL");
496 if (!env_ed)
497 env_ed = mutt_str_getenv("EDITOR");
498 if (!env_ed)
499 env_ed = "vi";
500 config_str_set_initial(cs, "editor", env_ed);
501
502 const char *charset = mutt_ch_get_langinfo_charset();
503 config_str_set_initial(cs, "charset", charset);
504 mutt_ch_set_charset(charset);
505 FREE(&charset);
506
507 char name[256] = { 0 };
508 const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
509 if (!c_real_name)
510 {
511 struct passwd *pw = getpwuid(getuid());
512 if (pw)
513 {
514 c_real_name = mutt_gecos_name(name, sizeof(name), pw);
515 }
516 }
517 config_str_set_initial(cs, "real_name", c_real_name);
518
519#ifdef HAVE_GETSID
520 /* Unset suspend by default if we're the session leader */
521 if (getsid(0) == getpid())
522 config_str_set_initial(cs, "suspend", "no");
523#endif
524
525 /* RFC2368, "4. Unsafe headers"
526 * The creator of a mailto URL can't expect the resolver of a URL to
527 * understand more than the "subject" and "body" headers. Clients that
528 * resolve mailto URLs into mail messages should be able to correctly
529 * create RFC822-compliant mail messages using the "subject" and "body"
530 * headers. */
531 add_to_stailq(&MailToAllow, "body");
532 add_to_stailq(&MailToAllow, "subject");
533 /* Cc, In-Reply-To, and References help with not breaking threading on
534 * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
536 add_to_stailq(&MailToAllow, "in-reply-to");
537 add_to_stailq(&MailToAllow, "references");
538
539 if (STAILQ_EMPTY(&Muttrc))
540 {
541 const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
542
543 if (!xdg_cfg_home && HomeDir)
544 {
545 buf_printf(buf, "%s/.config", HomeDir);
546 xdg_cfg_home = buf_string(buf);
547 }
548
549 char *config = find_cfg(HomeDir, xdg_cfg_home);
550 if (config)
551 {
553 }
554 }
555 else
556 {
557 struct ListNode *np = NULL;
558 STAILQ_FOREACH(np, &Muttrc, entries)
559 {
560 buf_strcpy(buf, np->data);
561 FREE(&np->data);
562 buf_expand_path(buf);
563 np->data = buf_strdup(buf);
564 if (access(np->data, F_OK))
565 {
566 mutt_perror("%s", np->data);
567 goto done; // TEST10: neomutt -F missing
568 }
569 }
570 }
571
572 struct ListNode *np = NULL;
573 STAILQ_FOREACH(np, &Muttrc, entries)
574 {
575 if (np->data && !mutt_str_equal(np->data, "/dev/null"))
576 {
577 cs_str_string_set(cs, "alias_file", np->data, NULL);
578 break;
579 }
580 }
581
582 /* Process the global rc file if it exists and the user hasn't explicitly
583 * requested not to via "-n". */
584 if (!skip_sys_rc)
585 {
586 do
587 {
589 break;
590
591 buf_printf(buf, "%s/neomuttrc", SYSCONFDIR);
592 if (access(buf_string(buf), F_OK) == 0)
593 break;
594
595 buf_printf(buf, "%s/Muttrc", SYSCONFDIR);
596 if (access(buf_string(buf), F_OK) == 0)
597 break;
598
599 buf_printf(buf, "%s/neomuttrc", PKGDATADIR);
600 if (access(buf_string(buf), F_OK) == 0)
601 break;
602
603 buf_printf(buf, "%s/Muttrc", PKGDATADIR);
604 } while (false);
605
606 if (access(buf_string(buf), F_OK) == 0)
607 {
608 if (source_rc(buf_string(buf), err) != 0)
609 {
610 mutt_error("%s", buf_string(err));
611 need_pause = true; // TEST11: neomutt (error in /etc/neomuttrc)
612 }
613 }
614 }
615
616 /* Read the user's initialization file. */
617 STAILQ_FOREACH(np, &Muttrc, entries)
618 {
619 if (np->data)
620 {
621 if (source_rc(np->data, err) != 0)
622 {
623 mutt_error("%s", buf_string(err));
624 need_pause = true; // TEST12: neomutt (error in ~/.neomuttrc)
625 }
626 }
627 }
628
629 if (execute_commands(commands) != 0)
630 need_pause = true; // TEST13: neomutt -e broken
631
632 if (!get_hostname(cs))
633 goto done;
634
635 /* The command line overrides the config */
636 if (dlevel)
637 cs_str_reset(cs, "debug_level", NULL);
638 if (dfile)
639 cs_str_reset(cs, "debug_file", NULL);
640
641 if (mutt_log_start() < 0)
642 {
643 mutt_perror("log file");
644 goto done;
645 }
646
647 if (need_pause && !OptNoCurses)
648 {
650 if (mutt_any_key_to_continue(NULL) == 'q')
651 goto done; // TEST14: neomutt -e broken (press 'q')
652 }
653
654 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
655 if (mutt_file_mkdir(c_tmp_dir, S_IRWXU) < 0)
656 {
657 mutt_error(_("Can't create %s: %s"), c_tmp_dir, strerror(errno));
658 goto done;
659 }
660
661 rc = 0;
662
663done:
664 buf_pool_release(&err);
665 buf_pool_release(&buf);
666 return rc;
667}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
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
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
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
char * HomeDir
User's home directory.
Definition: globals.c:37
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:617
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:692
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 OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:69
struct ListHead Muttrc
List of config files to read.
Definition: globals.c:51
char * Username
User's login name.
Definition: globals.c:40
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:441
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: main.c:249
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: main.c:217
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition: main.c:323
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:346
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:661
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:727
int mutt_log_start(void)
Enable file logging.
Definition: mutt_logging.c:248
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition: muttlib.c:332
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1052
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition: muttlib.c:896
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:315
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:46
#define STAILQ_EMPTY(head)
Definition: queue.h:382
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 ListHead *  queries,
struct HashElemArray *  hea 
)
static

Lookup the HashElems for a set of queries.

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

Definition at line 676 of file main.c.

677{
678 int rc = 0;
679 struct ListNode *np = NULL;
680 STAILQ_FOREACH(np, queries, entries)
681 {
682 struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
683 if (!he)
684 {
685 mutt_warning(_("Unknown option %s"), np->data);
686 rc = 1;
687 continue;
688 }
689
690 if (he->type & D_INTERNAL_DEPRECATED)
691 {
692 mutt_warning(_("Option %s is deprecated"), np->data);
693 rc = 1;
694 continue;
695 }
696
697 ARRAY_ADD(hea, he);
698 }
699
700 return rc; // TEST16: neomutt -Q charset
701}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:156
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:189
#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 707 of file main.c.

708{
709 static const char *names[] = { "folder", "mbox", "postponed", "record" };
710
711 struct Buffer *value = buf_pool_get();
712 for (size_t i = 0; i < mutt_array_size(names); i++)
713 {
714 struct HashElem *he = cs_get_elem(cs, names[i]);
715 if (!he)
716 continue;
717 buf_reset(value);
718 cs_he_initial_get(cs, he, value);
719 buf_expand_path_regex(value, false);
720 config_he_set_initial(cs, he, value->data);
721 }
722 buf_pool_release(&value);
723}
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:581
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:122
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 730 of file main.c.

731{
732 static const char *names[] = {
733 "attribution_intro",
734 "compose_format",
735 "forward_attribution_intro",
736 "forward_attribution_trailer",
737 "reply_regex",
738 "status_format",
739 "ts_icon_format",
740 "ts_status_format",
741 };
742
743 struct Buffer *value = buf_pool_get();
744 for (size_t i = 0; i < mutt_array_size(names); i++)
745 {
746 struct HashElem *he = cs_get_elem(cs, names[i]);
747 if (!he)
748 continue;
749 buf_reset(value);
750 cs_he_initial_get(cs, he, value);
751
752 // Lookup the translation
753 const char *l10n = gettext(buf_string(value));
754 config_he_set_initial(cs, he, l10n);
755 }
756 buf_pool_release(&value);
757}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ usage()

static bool usage ( void  )
static

Display NeoMutt command line.

Return values
trueText displayed

Definition at line 764 of file main.c.

765{
766 puts(mutt_make_version());
767
768 // clang-format off
769 /* L10N: Try to limit to 80 columns */
770 puts(_("usage:"));
771 puts(_(" neomutt [-CEn] [-e <command>] [-F <config>] [-H <draft>] [-i <include>]\n"
772 " [-b <address>] [-c <address>] [-s <subject>] [-a <file> [...] --]\n"
773 " <address> [...]"));
774 puts(_(" neomutt [-Cn] [-e <command>] [-F <config>] [-b <address>] [-c <address>]\n"
775 " [-s <subject>] [-a <file> [...] --] <address> [...] < message"));
776 puts(_(" neomutt [-nRy] [-e <command>] [-F <config>] [-f <mailbox>] [-m <type>]"));
777 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -A <alias>"));
778 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -B"));
779 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -D [-S] [-O]"));
780 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -d <level> -l <file>"));
781 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -G"));
782 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -g <server>"));
783 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -p"));
784 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Q <variable> [-O]"));
785 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -Z"));
786 puts(_(" neomutt [-n] [-e <command>] [-F <config>] -z [-f <mailbox>]"));
787 puts(_(" neomutt -v[v]\n"));
788
789 /* L10N: Try to limit to 80 columns. If more space is needed add an indented line */
790 puts(_("options:"));
791 puts(_(" -- Special argument forces NeoMutt to stop option parsing and treat\n"
792 " remaining arguments as addresses even if they start with a dash"));
793 puts(_(" -A <alias> Print an expanded version of the given alias to stdout and exit"));
794 puts(_(" -a <file> Attach one or more files to a message (must be the last option)\n"
795 " Add any addresses after the '--' argument"));
796 puts(_(" -B Run in batch mode (do not start the ncurses UI)"));
797 puts(_(" -b <address> Specify a blind carbon copy (Bcc) recipient"));
798 puts(_(" -c <address> Specify a carbon copy (Cc) recipient"));
799 puts(_(" -C Enable Command-line Crypto (signing/encryption)"));
800 puts(_(" -D Dump all config variables as 'name=value' pairs to stdout"));
801 puts(_(" -D -O Like -D, but show one-liner documentation"));
802 puts(_(" -D -S Like -D, but hide the value of sensitive variables"));
803 puts(_(" -d <level> Log debugging output to a file (default is \"~/.neomuttdebug0\")\n"
804 " The level can range from 1-5 and affects verbosity"));
805 puts(_(" -E Edit draft (-H) or include (-i) file during message composition"));
806 puts(_(" -e <command> Specify a command to be run after reading the config files"));
807 puts(_(" -F <config> Specify an alternative initialization file to read"));
808 puts(_(" -f <mailbox> Specify a mailbox (as defined with 'mailboxes' command) to load"));
809 puts(_(" -G Start NeoMutt with a listing of subscribed newsgroups"));
810 puts(_(" -g <server> Like -G, but start at specified news server"));
811 puts(_(" -H <draft> Specify a draft file with header and body for message composing"));
812 puts(_(" -h Print this help message and exit"));
813 puts(_(" -i <include> Specify an include file to be embedded in the body of a message"));
814 puts(_(" -l <file> Specify a file for debugging output (default \"~/.neomuttdebug0\")"));
815 puts(_(" -m <type> Specify a default mailbox format type for newly created folders\n"
816 " The type is either MH, MMDF, Maildir or mbox (case-insensitive)"));
817 puts(_(" -n Do not read the system-wide configuration file"));
818 puts(_(" -p Resume a prior postponed message, if any"));
819 puts(_(" -Q <variable> Query a configuration variable and print its value to stdout\n"
820 " (after the config has been read and any commands executed)\n"
821 " Add -O for one-liner documentation"));
822 puts(_(" -R Open mailbox in read-only mode"));
823 puts(_(" -s <subject> Specify a subject (must be enclosed in quotes if it has spaces)"));
824 puts(_(" -v Print the NeoMutt version and compile-time definitions and exit"));
825 puts(_(" -vv Print the NeoMutt license and copyright information and exit"));
826 puts(_(" -y Start NeoMutt with a listing of all defined mailboxes"));
827 puts(_(" -Z Open the first mailbox with new message or exit immediately with\n"
828 " exit code 1 if none is found in all defined mailboxes"));
829 puts(_(" -z Open the first or specified (-f) mailbox if it holds any message\n"
830 " or exit immediately with exit code 1 otherwise"));
831 // clang-format on
832
833 fflush(stdout);
834 return !ferror(stdout);
835}
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:857
+ 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 842 of file main.c.

843{
844 km_init(); /* must come before mutt_init */
845
846 /* should come before initscr() so that ncurses 4.2 doesn't try to install
847 * its own SIGWINCH handler */
849
850 if (!initscr())
851 {
852 mutt_error(_("Error initializing terminal"));
853 return 1;
854 }
855
856 colors_init();
857 keypad(stdscr, true);
858 cbreak();
859 noecho();
860 nonl();
861 typeahead(-1); /* simulate smooth scrolling */
862 meta(stdscr, true);
864 /* Now that curses is set up, we drop back to normal screen mode.
865 * This simplifies displaying error messages to the user.
866 * The first call to refresh() will swap us back to curses screen mode. */
867 endwin();
868 return 0;
869}
void colors_init(void)
Initialize colours.
Definition: color.c:49
void km_init(void)
Initialise all the menu keybindings.
Definition: init.c:177
void init_extended_keys(void)
Initialise map of ncurses extended keys.
Definition: init.c:134
void mutt_signal_init(void)
Initialise the signal handling.
Definition: mutt_signal.c:135
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 874 of file main.c.

875{
876 setlocale(LC_ALL, "");
877
878#ifdef ENABLE_NLS
879 const char *domdir = mutt_str_getenv("TEXTDOMAINDIR");
880 if (domdir)
881 bindtextdomain(PACKAGE, domdir);
882 else
883 bindtextdomain(PACKAGE, MUTTLOCALEDIR);
884 textdomain(PACKAGE);
885#endif
886#ifndef LOCALES_HACK
887 /* Do we have a locale definition? */
888 if (mutt_str_getenv("LC_ALL") || mutt_str_getenv("LANG") || mutt_str_getenv("LC_CTYPE"))
889 {
890 OptLocales = true;
891 }
892#endif
893}
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 902 of file main.c.

903{
904 const char *shell = mutt_str_getenv("SHELL");
905
906 /* Get some information about the user */
907 struct passwd *pw = getpwuid(getuid());
908 if (pw)
909 {
910 if (!Username)
911 Username = mutt_str_dup(pw->pw_name);
912 if (!HomeDir)
913 HomeDir = mutt_str_dup(pw->pw_dir);
914 if (!shell)
915 shell = pw->pw_shell;
916 }
917
918 if (!Username)
919 {
920 mutt_error(_("unable to determine username"));
921 return false; // TEST05: neomutt (unset $USER, delete user from /etc/passwd)
922 }
923
924 if (!HomeDir)
925 {
926 mutt_error(_("unable to determine home directory"));
927 return false; // TEST06: neomutt (unset $HOME, delete user from /etc/passwd)
928 }
929
930 if (shell)
931 config_str_set_initial(cs, "shell", shell);
932
933 return true;
934}
+ 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 943 of file main.c.

944{
945 const char *header = ""; // Do not merge these two lines
946 header = _(header); // otherwise the .po files will end up badly ordered
947 const char *label = "Language:"; // the start of the lookup/needle
948 const char *lang = mutt_istr_find(header, label);
949 int len = 64;
950 if (lang)
951 {
952 lang += strlen(label); // skip label
953 SKIPWS(lang);
954 char *nl = strchr(lang, '\n');
955 if (nl)
956 len = (nl - lang);
957 }
958 else
959 {
960 lang = "NONE";
961 }
962
963 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
964}
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:522
#define SKIPWS(ch)
Definition: string2.h:45
+ 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 969 of file main.c.

970{
971 const char *term = mutt_str_getenv("TERM");
972 const char *color_term = mutt_str_getenv("COLORTERM");
973 bool true_color = false;
974#ifdef NEOMUTT_DIRECT_COLORS
975 true_color = true;
976#endif
977
978 mutt_debug(LL_DEBUG1, "GUI:\n");
979 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
980 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
981 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
982 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
983 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
984 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
985 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
987}
struct MuttWindow * RootWindow
Parent of all Windows.
Definition: rootwin.c:106
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:62
+ 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 1033 of file main.c.

1036{
1037 char *subject = NULL;
1038 char *include_file = NULL;
1039 char *draft_file = NULL;
1040 char *new_type = NULL;
1041 char *dlevel = NULL;
1042 char *dfile = NULL;
1043 const char *cli_nntp = NULL;
1044 struct Email *e = NULL;
1045 struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
1046 struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
1047 struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
1048 struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
1049 struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
1050 struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
1051 SendFlags sendflags = SEND_NO_FLAGS;
1053 int version = 0;
1054 int i;
1055 bool explicit_folder = false;
1056 bool dump_variables = false;
1057 bool one_liner = false;
1058 bool hide_sensitive = false;
1059 bool batch_mode = false;
1060 bool edit_infile = false;
1061 int double_dash = argc, nargc = 1;
1062 int rc = 1;
1063 bool repeat_error = false;
1064 struct Buffer *folder = buf_pool_get();
1065 struct Buffer *expanded_infile = buf_pool_get();
1066 struct Buffer *tempfile = buf_pool_get();
1067 struct ConfigSet *cs = NULL;
1068
1070
1071 /* sanity check against stupid administrators */
1072 if (getegid() != getgid())
1073 {
1074 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
1075 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
1076 }
1077
1078 init_locale();
1079
1080 EnvList = envlist_init(envp);
1081 for (optind = 1; optind < double_dash;)
1082 {
1083 /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
1084 * encounters a non-option. That could be a file to attach
1085 * (all non-options between -a and --) or it could be an address
1086 * (which gets collapsed to the front of argv). */
1087 for (; optind < argc; optind++)
1088 {
1089 if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
1090 {
1091 if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
1092 double_dash = optind; /* quit outer loop after getopt */
1093 break; /* drop through to getopt */
1094 }
1095
1096 /* non-option, either an attachment or address */
1097 if (!STAILQ_EMPTY(&attach))
1098 mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
1099 else
1100 argv[nargc++] = argv[optind];
1101 }
1102
1103 i = getopt(argc, argv, "+A:a:Bb:F:f:Cc:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvyzZ");
1104 if (i != EOF)
1105 {
1106 switch (i)
1107 {
1108 case 'A':
1109 mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
1110 break;
1111 case 'a':
1112 mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
1113 break;
1114 case 'B':
1115 batch_mode = true;
1116 break;
1117 case 'b':
1118 mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
1119 break;
1120 case 'C':
1121 sendflags |= SEND_CLI_CRYPTO;
1122 break;
1123 case 'c':
1124 mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
1125 break;
1126 case 'D':
1127 dump_variables = true;
1128 break;
1129 case 'd':
1130 dlevel = optarg;
1131 break;
1132 case 'E':
1133 edit_infile = true;
1134 break;
1135 case 'e':
1136 mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
1137 break;
1138 case 'F':
1140 break;
1141 case 'f':
1142 buf_strcpy(folder, optarg);
1143 explicit_folder = true;
1144 break;
1145 case 'g': /* Specify a news server */
1146 cli_nntp = optarg;
1148
1149 case 'G': /* List of newsgroups */
1150 flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
1151 break;
1152 case 'H':
1153 draft_file = optarg;
1154 break;
1155 case 'i':
1156 include_file = optarg;
1157 break;
1158 case 'l':
1159 dfile = optarg;
1160 break;
1161 case 'm':
1162 new_type = optarg;
1163 break;
1164 case 'n':
1165 flags |= MUTT_CLI_NOSYSRC;
1166 break;
1167 case 'O':
1168 one_liner = true;
1169 break;
1170 case 'p':
1171 sendflags |= SEND_POSTPONED;
1172 break;
1173 case 'Q':
1174 mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
1175 break;
1176 case 'R':
1177 flags |= MUTT_CLI_RO; /* read-only mode */
1178 break;
1179 case 'S':
1180 hide_sensitive = true;
1181 break;
1182 case 's':
1183 subject = optarg;
1184 break;
1185 case 'v':
1186 version++;
1187 break;
1188 case 'y': /* My special hack mode */
1189 flags |= MUTT_CLI_SELECT;
1190 break;
1191 case 'Z':
1193 break;
1194 case 'z':
1195 flags |= MUTT_CLI_IGNORE;
1196 break;
1197 default:
1198 OptNoCurses = true;
1199 if (usage())
1200 goto main_ok; // TEST03: neomutt -9
1201 else
1202 goto main_curses;
1203 }
1204 }
1205 }
1206
1207 /* collapse remaining argv */
1208 while (optind < argc)
1209 argv[nargc++] = argv[optind++];
1210 optind = 1;
1211 argc = nargc;
1212
1213 if (version > 0)
1214 {
1216 bool done;
1217 if (version == 1)
1218 done = print_version(stdout);
1219 else
1220 done = print_copyright();
1221 OptNoCurses = true;
1222 if (done)
1223 goto main_ok; // TEST04: neomutt -v
1224 else
1225 goto main_curses;
1226 }
1227
1230
1231 cs = cs_new(500);
1232 if (!cs)
1233 goto main_curses;
1234
1235 NeoMutt = neomutt_new(cs);
1236 init_config(cs);
1237
1238 // Change the current umask, and save the original one
1239 NeoMutt->user_default_umask = umask(077);
1240 subjrx_init();
1241 attach_init();
1243
1244#ifdef USE_DEBUG_NOTIFY
1246#endif
1247
1248 if (!get_user_info(cs))
1249 goto main_exit;
1250
1251 reset_tilde(cs);
1252#ifdef ENABLE_NLS
1253 localise_config(cs);
1254#endif
1255
1256 if (dfile)
1257 config_str_set_initial(cs, "debug_file", dfile);
1258
1259 if (dlevel)
1260 {
1261 short num = 0;
1262 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
1263 {
1264 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
1265 goto main_exit; // TEST07: neomutt -d xyz
1266 }
1267
1268 config_str_set_initial(cs, "debug_level", dlevel);
1269 }
1270
1271 mutt_log_prep();
1274 mutt_debug(LL_DEBUG1, "user's umask %03o\n", NeoMutt->user_default_umask);
1275 mutt_debug(LL_DEBUG3, "umask set to 077\n");
1276
1277 if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
1278 {
1279 e = email_new();
1280 e->env = mutt_env_new();
1281
1282 struct ListNode *np = NULL;
1283 STAILQ_FOREACH(np, &bcc_list, entries)
1284 {
1285 mutt_addrlist_parse(&e->env->bcc, np->data);
1286 }
1287
1288 STAILQ_FOREACH(np, &cc_list, entries)
1289 {
1290 mutt_addrlist_parse(&e->env->cc, np->data);
1291 }
1292
1293 mutt_list_free(&bcc_list);
1294 mutt_list_free(&cc_list);
1295 }
1296
1297 /* Check for a batch send. */
1298 if (!isatty(0) || !STAILQ_EMPTY(&queries) || !STAILQ_EMPTY(&alias_queries) ||
1299 dump_variables || batch_mode)
1300 {
1301 OptNoCurses = true;
1302 sendflags |= SEND_BATCH;
1305 }
1306
1307 /* Check to make sure stdout is available in curses mode. */
1308 if (!OptNoCurses && !isatty(1))
1309 goto main_curses;
1310
1311 /* This must come before mutt_init() because curses needs to be started
1312 * before calling the init_pair() function to set the color scheme. */
1313 if (!OptNoCurses)
1314 {
1315 int crc = start_curses();
1316 if (crc != 0)
1317 goto main_curses; // TEST08: can't test -- fake term?
1318 }
1319
1320 /* Always create the mutt_windows because batch mode has some shared code
1321 * paths that end up referencing them. */
1322 rootwin_new();
1323
1324 if (!OptNoCurses)
1325 {
1326 /* check whether terminal status is supported (must follow curses init) */
1329 log_gui();
1330 }
1331
1333 alias_init();
1334 commands_init();
1335 hooks_init();
1337 imap_init();
1338#ifdef USE_LUA
1339 mutt_lua_init();
1340#endif
1342
1343 menu_init();
1344 sb_init();
1345#ifdef USE_NOTMUCH
1346 nm_init();
1347#endif
1348
1349 /* set defaults and read init files */
1350 int rc2 = mutt_init(cs, dlevel, dfile, flags & MUTT_CLI_NOSYSRC, &commands);
1351 if (rc2 != 0)
1352 goto main_curses;
1353
1356
1357#ifdef USE_NOTMUCH
1358 const bool c_virtual_spool_file = cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
1359 if (c_virtual_spool_file)
1360 {
1361 /* Find the first virtual folder and open it */
1362 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
1364 struct MailboxNode *mp = STAILQ_FIRST(&ml);
1365 if (mp)
1366 cs_str_string_set(cs, "spool_file", mailbox_path(mp->mailbox), NULL);
1368 }
1369#endif
1370
1372
1373 /* "$news_server" precedence: command line, config file, environment, system file */
1374 if (!cli_nntp)
1375 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
1376
1377 if (!cli_nntp)
1378 cli_nntp = mutt_str_getenv("NNTPSERVER");
1379
1380 if (!cli_nntp)
1381 {
1382 char buf[1024] = { 0 };
1383 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
1384 }
1385
1386 if (cli_nntp)
1387 config_str_set_initial(cs, "news_server", cli_nntp);
1388
1389 /* Initialize crypto backends. */
1390 crypt_init();
1391
1392 if (new_type && !config_str_set_initial(cs, "mbox_type", new_type))
1393 goto main_curses;
1394
1395 if (dump_variables || !STAILQ_EMPTY(&queries))
1396 {
1397 const bool tty = isatty(STDOUT_FILENO);
1398
1400 if (tty)
1401 cdflags |= CS_DUMP_LINK_DOCS;
1402 if (hide_sensitive)
1403 cdflags |= CS_DUMP_HIDE_SENSITIVE;
1404 if (one_liner)
1405 cdflags |= CS_DUMP_SHOW_DOCS;
1406
1407 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
1408 if (dump_variables)
1409 {
1410 hea = get_elem_list(cs, GEL_ALL_CONFIG);
1411 rc = 0;
1412 }
1413 else
1414 {
1415 rc = get_elem_queries(&queries, &hea);
1416 }
1417
1418 dump_config(cs, &hea, cdflags, stdout);
1419 ARRAY_FREE(&hea);
1420 goto main_curses;
1421 }
1422
1423 if (!STAILQ_EMPTY(&alias_queries))
1424 {
1425 rc = 0;
1426 for (; optind < argc; optind++)
1427 mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
1428 struct ListNode *np = NULL;
1429 STAILQ_FOREACH(np, &alias_queries, entries)
1430 {
1431 struct AddressList *al = alias_lookup(np->data);
1432 if (al)
1433 {
1434 /* output in machine-readable form */
1435 mutt_addrlist_to_intl(al, NULL);
1436 struct Buffer *buf = buf_pool_get();
1437 mutt_addrlist_write(al, buf, false);
1438 printf("%s\n", buf_string(buf));
1439 buf_pool_release(&buf);
1440 }
1441 else
1442 {
1443 rc = 1;
1444 printf("%s\n", NONULL(np->data)); // TEST19: neomutt -A unknown
1445 }
1446 }
1447 mutt_list_free(&alias_queries);
1448 goto main_curses; // TEST20: neomutt -A alias
1449 }
1450
1451 if (!OptNoCurses)
1452 {
1454 clear();
1458 }
1459
1460#ifdef USE_AUTOCRYPT
1461 /* Initialize autocrypt after curses messages are working,
1462 * because of the initial account setup screens. */
1463 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
1464 if (c_autocrypt)
1465 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
1466#endif
1467
1468 /* Create the `$folder` directory if it doesn't exist. */
1469 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1470 if (!OptNoCurses && c_folder)
1471 {
1472 struct stat st = { 0 };
1473 struct Buffer *fpath = buf_pool_get();
1474
1475 buf_strcpy(fpath, c_folder);
1476 buf_expand_path(fpath);
1477 bool skip = false;
1478 /* we're not connected yet - skip mail folder creation */
1479 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
1480 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
1481 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
1482 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
1483 {
1484 char msg2[256] = { 0 };
1485 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
1486 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
1487 {
1488 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
1489 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
1490 }
1491 }
1492 buf_pool_release(&fpath);
1493 }
1494
1495 if (batch_mode)
1496 {
1497 goto main_ok; // TEST22: neomutt -B
1498 }
1499 StartupComplete = true;
1500
1505
1506 if (sendflags & SEND_POSTPONED)
1507 {
1508 if (!OptNoCurses)
1509 mutt_flushinp();
1510 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1511 rc = 0;
1512 // TEST23: neomutt -p (postponed message, cancel)
1513 // TEST24: neomutt -p (no postponed message)
1515 repeat_error = true;
1516 goto main_curses;
1517 }
1518 else if (subject || e || draft_file || include_file ||
1519 !STAILQ_EMPTY(&attach) || (optind < argc))
1520 {
1521 FILE *fp_in = NULL;
1522 FILE *fp_out = NULL;
1523 char *infile = NULL;
1524 char *bodytext = NULL;
1525 const char *bodyfile = NULL;
1526 int rv = 0;
1527
1528 if (!OptNoCurses)
1529 mutt_flushinp();
1530
1531 if (!e)
1532 e = email_new();
1533 if (!e->env)
1534 e->env = mutt_env_new();
1535
1536 for (i = optind; i < argc; i++)
1537 {
1538 if (url_check_scheme(argv[i]) == U_MAILTO)
1539 {
1540 if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
1541 {
1542 mutt_error(_("Failed to parse mailto: link"));
1543 email_free(&e);
1544 goto main_curses; // TEST25: neomutt mailto:?
1545 }
1546 }
1547 else
1548 {
1549 mutt_addrlist_parse(&e->env->to, argv[i]);
1550 }
1551 }
1552
1553 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1554 if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
1555 TAILQ_EMPTY(&e->env->cc))
1556 {
1557 mutt_error(_("No recipients specified"));
1558 email_free(&e);
1559 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1560 }
1561
1562 if (subject)
1563 {
1564 /* prevent header injection */
1566 mutt_env_set_subject(e->env, subject);
1567 }
1568
1569 if (draft_file)
1570 {
1571 infile = draft_file;
1572 include_file = NULL;
1573 }
1574 else if (include_file)
1575 {
1576 infile = include_file;
1577 }
1578 else
1579 {
1580 edit_infile = false;
1581 }
1582
1583 if (infile || bodytext)
1584 {
1585 /* Prepare fp_in and expanded_infile. */
1586 if (infile)
1587 {
1588 if (mutt_str_equal("-", infile))
1589 {
1590 if (edit_infile)
1591 {
1592 mutt_error(_("Can't use -E flag with stdin"));
1593 email_free(&e);
1594 goto main_curses; // TEST27: neomutt -E -H -
1595 }
1596 fp_in = stdin;
1597 }
1598 else
1599 {
1600 buf_strcpy(expanded_infile, infile);
1601 buf_expand_path(expanded_infile);
1602 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1603 if (!fp_in)
1604 {
1605 mutt_perror("%s", buf_string(expanded_infile));
1606 email_free(&e);
1607 goto main_curses; // TEST28: neomutt -E -H missing
1608 }
1609 }
1610 }
1611
1612 if (edit_infile)
1613 {
1614 /* If editing the infile, keep it around afterwards so
1615 * it doesn't get unlinked, and we can rebuild the draft_file */
1616 sendflags |= SEND_NO_FREE_HEADER;
1617 }
1618 else
1619 {
1620 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1621 * Note: stdin is always copied to a tempfile, ensuring draft_file
1622 * can stat and get the correct st_size below. */
1623 buf_mktemp(tempfile);
1624
1625 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1626 if (!fp_out)
1627 {
1628 mutt_file_fclose(&fp_in);
1629 mutt_perror("%s", buf_string(tempfile));
1630 email_free(&e);
1631 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1632 }
1633 if (fp_in)
1634 {
1635 mutt_file_copy_stream(fp_in, fp_out);
1636 if (fp_in == stdin)
1637 sendflags |= SEND_CONSUMED_STDIN;
1638 else
1639 mutt_file_fclose(&fp_in);
1640 }
1641 else if (bodytext)
1642 {
1643 fputs(bodytext, fp_out);
1644 }
1645 mutt_file_fclose(&fp_out);
1646
1647 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1648 if (!fp_in)
1649 {
1650 mutt_perror("%s", buf_string(tempfile));
1651 email_free(&e);
1652 goto main_curses; // TEST30: can't test
1653 }
1654 }
1655
1656 /* Parse the draft_file into the full Email/Body structure.
1657 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1658 * our e->body. */
1659 if (draft_file)
1660 {
1661 struct Envelope *opts_env = e->env;
1662 struct stat st = { 0 };
1663
1664 sendflags |= SEND_DRAFT_FILE;
1665
1666 /* Set up a tmp Email with just enough information so that
1667 * mutt_prepare_template() can parse the message in fp_in. */
1668 struct Email *e_tmp = email_new();
1669 e_tmp->offset = 0;
1670 e_tmp->body = mutt_body_new();
1671 if (fstat(fileno(fp_in), &st) != 0)
1672 {
1673 mutt_perror("%s", draft_file);
1674 email_free(&e);
1675 email_free(&e_tmp);
1676 goto main_curses; // TEST31: can't test
1677 }
1678 e_tmp->body->length = st.st_size;
1679
1680 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1681 {
1682 mutt_error(_("Can't parse message template: %s"), draft_file);
1683 email_free(&e);
1684 email_free(&e_tmp);
1685 goto main_curses;
1686 }
1687
1688 /* Scan for neomutt header to set `$resume_draft_files` */
1689 struct ListNode *np = NULL, *tmp = NULL;
1690 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1691 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1692 {
1693 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1694 {
1695 if (c_resume_edited_draft_files)
1696 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1697
1698 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1699 FREE(&np->data);
1700 FREE(&np);
1701 }
1702 }
1703
1704 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1705 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1706 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1707 if (opts_env->subject)
1708 mutt_env_set_subject(e->env, opts_env->subject);
1709
1710 mutt_env_free(&opts_env);
1711 email_free(&e_tmp);
1712 }
1713 /* Editing the include_file: pass it directly in.
1714 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1715 else if (edit_infile)
1716 bodyfile = buf_string(expanded_infile);
1717 // For bodytext and unedited include_file: use the tempfile.
1718 else
1719 bodyfile = buf_string(tempfile);
1720
1721 mutt_file_fclose(&fp_in);
1722 }
1723
1724 FREE(&bodytext);
1725
1726 if (!STAILQ_EMPTY(&attach))
1727 {
1728 struct Body *b = e->body;
1729
1730 while (b && b->next)
1731 b = b->next;
1732
1733 struct ListNode *np = NULL;
1734 STAILQ_FOREACH(np, &attach, entries)
1735 {
1736 if (b)
1737 {
1739 b = b->next;
1740 }
1741 else
1742 {
1744 e->body = b;
1745 }
1746 if (!b)
1747 {
1748 mutt_error(_("%s: unable to attach file"), np->data);
1749 mutt_list_free(&attach);
1750 email_free(&e);
1751 goto main_curses; // TEST32: neomutt john@example.com -a missing
1752 }
1753 }
1754 mutt_list_free(&attach);
1755 }
1756
1757 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1758 /* We WANT the "Mail sent." and any possible, later error */
1760 if (ErrorBufMessage)
1761 mutt_message("%s", ErrorBuf);
1762
1763 if (edit_infile)
1764 {
1765 if (draft_file)
1766 {
1767 if (truncate(buf_string(expanded_infile), 0) == -1)
1768 {
1769 mutt_perror("%s", buf_string(expanded_infile));
1770 email_free(&e);
1771 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1772 }
1773 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1774 if (!fp_out)
1775 {
1776 mutt_perror("%s", buf_string(expanded_infile));
1777 email_free(&e);
1778 goto main_curses; // TEST34: can't test
1779 }
1780
1781 /* If the message was sent or postponed, these will already
1782 * have been done. */
1783 if (rv < 0)
1784 {
1785 if (e->body->next)
1786 e->body = mutt_make_multipart(e->body);
1788 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1789 mutt_env_to_intl(e->env, NULL, NULL);
1790 }
1791
1792 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1794 c_crypt_protected_headers_read &&
1796 NeoMutt->sub);
1797 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1798 if (c_resume_edited_draft_files)
1799 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1800 fputc('\n', fp_out);
1801 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1802 {
1803 mutt_file_fclose(&fp_out);
1804 email_free(&e);
1805 goto main_curses; // TEST35: can't test
1806 }
1807 mutt_file_fclose(&fp_out);
1808 }
1809
1810 email_free(&e);
1811 }
1812
1813 /* !edit_infile && draft_file will leave the tempfile around */
1814 if (!buf_is_empty(tempfile))
1815 unlink(buf_string(tempfile));
1816
1818
1819 if (rv != 0)
1820 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1821 }
1822 else if (sendflags & SEND_BATCH)
1823 {
1824 /* This guards against invoking `neomutt < /dev/null` and accidentally
1825 * sending an email due to a my_hdr or other setting. */
1826 mutt_error(_("No recipients specified"));
1827 goto main_curses;
1828 }
1829 else
1830 {
1831 if (flags & MUTT_CLI_MAILBOX)
1832 {
1833 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1834 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1836 if (mutt_mailbox_check(NULL, csflags) == 0)
1837 {
1838 mutt_message(_("No mailbox with new mail"));
1839 repeat_error = true;
1840 goto main_curses; // TEST37: neomutt -Z (no new mail)
1841 }
1842 buf_reset(folder);
1843 mutt_mailbox_next(NULL, folder);
1844 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1845 }
1846 else if (flags & MUTT_CLI_SELECT)
1847 {
1848 if (flags & MUTT_CLI_NEWS)
1849 {
1850 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1851 OptNews = true;
1852 CurrentNewsSrv = nntp_select_server(NULL, c_news_server, false);
1853 if (!CurrentNewsSrv)
1854 goto main_curses; // TEST38: neomutt -G (unset news_server)
1855 }
1856 else if (TAILQ_EMPTY(&NeoMutt->accounts))
1857 {
1858 mutt_error(_("No incoming mailboxes defined"));
1859 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1860 }
1861 buf_reset(folder);
1862 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1863 if (buf_is_empty(folder))
1864 {
1865 goto main_ok; // TEST40: neomutt -y (quit selection)
1866 }
1867 }
1868
1869 if (buf_is_empty(folder))
1870 {
1871 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1872 if (c_spool_file)
1873 {
1874 // Check if `$spool_file` corresponds a mailboxes' description.
1875 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1876 if (m_desc)
1877 buf_strcpy(folder, m_desc->realpath);
1878 else
1879 buf_strcpy(folder, c_spool_file);
1880 }
1881 else if (c_folder)
1882 {
1883 buf_strcpy(folder, c_folder);
1884 }
1885 /* else no folder */
1886 }
1887
1888 if (OptNews)
1889 {
1890 OptNews = false;
1891 buf_alloc(folder, PATH_MAX);
1892 nntp_expand_path(folder->data, folder->dsize, &CurrentNewsSrv->conn->account);
1893 }
1894 else
1895 {
1896 buf_expand_path(folder);
1897 }
1898
1901
1902 if (flags & MUTT_CLI_IGNORE)
1903 {
1904 /* check to see if there are any messages in the folder */
1905 switch (mx_path_is_empty(folder))
1906 {
1907 case -1:
1908 mutt_perror("%s", buf_string(folder));
1909 goto main_curses; // TEST41: neomutt -z -f missing
1910 case 1:
1911 mutt_error(_("Mailbox is empty"));
1912 goto main_curses; // TEST42: neomutt -z -f /dev/null
1913 }
1914 }
1915
1916 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1917 // Take a copy of the name just in case the hook alters m_cur
1918 const char *name = m_cur ? mutt_str_dup(m_cur->name) : NULL;
1920 FREE(&name);
1922 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1924
1926 window_redraw(NULL);
1927
1928 repeat_error = true;
1929 struct Mailbox *m = mx_resolve(buf_string(folder));
1930 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1931 if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1932 {
1933 if (m->account)
1935
1936 mailbox_free(&m);
1937 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1938 repeat_error = false;
1939 }
1940 if (m || !explicit_folder)
1941 {
1942 struct MuttWindow *dlg = index_pager_init();
1943 dialog_push(dlg);
1944
1946 m = dlg_index(dlg, m);
1948 mailbox_free(&m);
1949
1950 dialog_pop();
1951 mutt_window_free(&dlg);
1953 repeat_error = false;
1954 }
1956#ifdef USE_SASL_CYRUS
1958#endif
1959#ifdef USE_SASL_GNU
1961#endif
1962#ifdef USE_AUTOCRYPT
1964#endif
1965 // TEST43: neomutt (no change to mailbox)
1966 // TEST44: neomutt (change mailbox)
1967 }
1968
1969main_ok:
1970 rc = 0;
1971main_curses:
1972 mutt_endwin();
1974 /* Repeat the last message to the user */
1975 if (repeat_error && ErrorBufMessage)
1976 puts(ErrorBuf);
1977main_exit:
1978 if (NeoMutt && NeoMutt->sub)
1979 {
1984 }
1985 mutt_list_free(&commands);
1987 buf_pool_release(&folder);
1988 buf_pool_release(&expanded_infile);
1989 buf_pool_release(&tempfile);
1990 mutt_list_free(&queries);
1997 menu_cleanup();
1998 crypt_cleanup();
2000
2002
2003 alias_cleanup();
2004 sb_cleanup();
2005
2011
2014
2015 /* Lists of strings */
2025
2027
2029 FREE(&HomeDir);
2030 FREE(&LastFolder);
2032 FREE(&Username);
2033
2035
2037
2040
2043
2051 cs_free(&cs);
2053 mutt_log_stop();
2054 return rc;
2055}
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
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_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1293
void alias_cleanup(void)
Clean up the Alias globals.
Definition: alias.c:718
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
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_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
void attach_init(void)
Set up the attachments lists.
Definition: attachments.c:106
void attach_cleanup(void)
Free the attachments lists.
Definition: attachments.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
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
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
void colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:84
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:55
void commands_init(void)
Initialize commands array and register default commands.
Definition: commands.c:1747
void source_stack_cleanup(void)
Free memory from the stack used for the source command.
Definition: commands.c:1671
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:90
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
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:812
void config_cache_cleanup(void)
Cleanup the cache of charset config variables.
Definition: config_cache.c:145
bool account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition: account.c:98
void commands_cleanup(void)
Free Commands array.
Definition: command.c:65
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:187
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:223
@ 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
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: get.c:58
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.
Definition: dlg_browser.c:159
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:1754
void mutt_filter_commandline_header_value(char *header)
Sanitise characters in a header value.
Definition: parse.c:93
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:355
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition: envelope.c:69
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
char * mutt_file_read_keyword(const char *file, char *buf, size_t buflen)
Read a keyword from a file.
Definition: file.c:1299
bool OptNews
(pseudo) used to change reader mode
Definition: globals.c:67
char * LastFolder
Previously selected mailbox.
Definition: globals.c:43
struct ListHead MimeLookupList
List of mime types that that shouldn't use the mailcap entry.
Definition: globals.c:50
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition: globals.c:47
struct ListHead AutoViewList
List of mime types to auto view.
Definition: globals.c:48
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:42
struct ListHead UserHeader
List of custom headers to add to outgoing emails.
Definition: globals.c:53
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: globals.c:49
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:75
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 -.
Definition: dlg_browser.c:853
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:398
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 -.
Definition: mutt_logging.c:88
#define mutt_message(...)
Definition: logging2.h:91
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe() -.
Definition: nntp.c:2786
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe() -.
Definition: pop.c:1156
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2344
int main_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: init.c:259
int main_hist_observer(struct NotifyCallback *nc)
Notification that a Config Variable has change - Implements observer_t -.
Definition: history.c:709
static int main_timeout_observer(struct NotifyCallback *nc)
Notification that a timeout has occurred - Implements observer_t -.
Definition: main.c:992
int main_log_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: mutt_logging.c:284
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:600
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:472
void mutt_hist_cleanup(void)
Free all the history lists.
Definition: history.c:445
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:398
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:1050
#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:553
void imap_init(void)
Setup feature commands.
Definition: imap.c:95
void mutt_keys_cleanup(void)
Free the key maps.
Definition: init.c:224
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: init.c:237
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
int(*) log_dispatcher_ MuttLogger)
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_MESSAGE
Log informational message.
Definition: logging2.h:42
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
@ LL_MAX
Definition: logging2.h:50
#define MUTT_CLI_SELECT
-y Start with a list of all mailboxes
Definition: main.c:207
static void init_locale(void)
Initialise the Locale/NLS settings.
Definition: main.c:874
static void localise_config(struct ConfigSet *cs)
Localise some config.
Definition: main.c:730
uint8_t CliFlags
Flags for command line options, e.g. MUTT_CLI_IGNORE.
Definition: main.c:201
static void log_translation(void)
Log the translation being used.
Definition: main.c:943
#define MUTT_CLI_MAILBOX
-Z Open first mailbox if is has new mail
Definition: main.c:204
static void log_gui(void)
Log info about the GUI.
Definition: main.c:969
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:707
static bool usage(void)
Display NeoMutt command line.
Definition: main.c:764
static int get_elem_queries(struct ListHead *queries, struct HashElemArray *hea)
Lookup the HashElems for a set of queries.
Definition: main.c:676
static int start_curses(void)
Start the Curses UI.
Definition: main.c:842
static int mutt_init(struct ConfigSet *cs, const char *dlevel, const char *dfile, bool skip_sys_rc, struct ListHead *commands)
Initialise NeoMutt.
Definition: main.c:408
bool StartupComplete
When the config has been read.
Definition: main.c:198
static bool get_user_info(struct ConfigSet *cs)
Find the user's name, home and shell.
Definition: main.c:902
#define MUTT_CLI_RO
-R Open mailbox in read-only mode
Definition: main.c:206
#define MUTT_CLI_NO_FLAGS
No flags are set.
Definition: main.c:202
#define MUTT_CLI_IGNORE
-z Open first mailbox if it has mail
Definition: main.c:203
#define MUTT_CLI_NEWS
-g/-G Start with a list of all newsgroups
Definition: main.c:208
#define MUTT_CLI_NOSYSRC
-n Do not read the system-wide config file
Definition: main.c:205
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
#define FALLTHROUGH
Definition: lib.h:111
void log_queue_empty(void)
Free the contents of the queue.
Definition: logging.c:324
void log_queue_set_max_size(int size)
Set a upper limit for the queue length.
Definition: logging.c:312
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:179
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:450
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:243
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:281
#define PATH_MAX
Definition: mutt.h:42
void mutt_temp_attachments_cleanup(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1305
void init_config(struct ConfigSet *cs)
Initialise the config system.
Definition: mutt_config.c:930
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.
Definition: mutt_logging.c:181
void mutt_log_prep(void)
Prepare to log.
Definition: mutt_logging.c:171
void mutt_lua_init(void)
Setup feature commands.
Definition: mutt_lua.c:465
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:169
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Definition: mutt_mailbox.c:361
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:599
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:205
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:1709
int mx_path_is_empty(struct Buffer *path)
Is the mailbox empty.
Definition: mx.c:1256
#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
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:168
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:191
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:86
@ NT_GLOBAL_STARTUP
NeoMutt is initialised.
Definition: neomutt.h:61
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:77
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:108
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:339
@ 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:327
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:441
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:388
#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:786
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:1488
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:2033
#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_CLI_CRYPTO
Enable message security in modes that by default don't enable it.
Definition: send.h:58
#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:780
void sb_init(void)
Set up the Sidebar.
Definition: sidebar.c:202
void sb_cleanup(void)
Clean up the Sidebar.
Definition: sidebar.c:218
The body of an email.
Definition: body.h:36
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
Container for lots of config items.
Definition: set.h:250
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:51
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:49
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
List of Mailboxes.
Definition: mailbox.h:166
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:167
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 Notify * notify_resize
Window resize notifications handler.
Definition: neomutt.h:44
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:47
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
struct Connection * conn
Connection to NNTP Server.
Definition: adata.h:62
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:299
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition: subset.c:80
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition: subset.h:81
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:42
bool mutt_ts_capability(void)
Check terminal capabilities.
Definition: terminal.c:72
#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:226
@ U_MAILTO
Url is mailto://.
Definition: url.h:45
bool print_copyright(void)
Print copyright message.
Definition: version.c:517
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:388

Variable Documentation

◆ StartupComplete

bool StartupComplete = false

When the config has been read.

Definition at line 198 of file main.c.