NeoMutt  2025-01-09-117-gace867
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: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
#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:109
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: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: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: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,
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(NeoMutt->home_dir), MAILPATH);
448#else
449 buf_concat_path(buf, MAILPATH, NONULL(NeoMutt->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 && NeoMutt->home_dir)
544 {
545 buf_printf(buf, "%s/.config", NeoMutt->home_dir);
546 xdg_cfg_home = buf_string(buf);
547 }
548
549 char *config = find_cfg(NeoMutt->home_dir, 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
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 OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:66
struct ListHead Muttrc
List of config files to read.
Definition: globals.c:48
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'my_hdr' command - Implements Command::parse() -.
Definition: commands.c:849
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Save a log line to the terminal - Implements log_dispatcher_t -.
Definition: logging.c:421
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: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: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
char * username
User's login name.
Definition: neomutt.h:54
char * home_dir
User's home directory.
Definition: neomutt.h:53
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:557
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 struct Buffer *value = buf_pool_get();
733 struct HashElemArray hea = get_elem_list(NeoMutt->sub->cs, GEL_ALL_CONFIG);
734 struct HashElem **hep = NULL;
735
736 ARRAY_FOREACH(hep, &hea)
737 {
738 struct HashElem *he = *hep;
739 if (!(he->type & D_L10N_STRING))
740 continue;
741
742 buf_reset(value);
743 cs_he_initial_get(cs, he, value);
744
745 // Lookup the translation
746 const char *l10n = gettext(buf_string(value));
747 config_he_set_initial(cs, he, l10n);
748 }
749
750 ARRAY_FREE(&hea);
751 buf_pool_release(&value);
752}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:214
#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:80
@ 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:

◆ usage()

static bool usage ( void  )
static

Display NeoMutt command line.

Return values
trueText displayed

Definition at line 759 of file main.c.

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

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

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

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

938{
939 const char *header = ""; // Do not merge these two lines
940 header = _(header); // otherwise the .po files will end up badly ordered
941 const char *label = "Language:"; // the start of the lookup/needle
942 const char *lang = mutt_istr_find(header, label);
943 int len = 64;
944 if (lang)
945 {
946 lang += strlen(label); // skip label
947 SKIPWS(lang);
948 char *nl = strchr(lang, '\n');
949 if (nl)
950 len = (nl - lang);
951 }
952 else
953 {
954 lang = "NONE";
955 }
956
957 mutt_debug(LL_DEBUG1, "Translation: %.*s\n", len, lang);
958}
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 963 of file main.c.

964{
965 const char *term = mutt_str_getenv("TERM");
966 const char *color_term = mutt_str_getenv("COLORTERM");
967 bool true_color = false;
968#ifdef NEOMUTT_DIRECT_COLORS
969 true_color = true;
970#endif
971
972 mutt_debug(LL_DEBUG1, "GUI:\n");
973 mutt_debug(LL_DEBUG1, " Curses: %s\n", curses_version());
974 mutt_debug(LL_DEBUG1, " COLORS=%d\n", COLORS);
975 mutt_debug(LL_DEBUG1, " COLOR_PAIRS=%d\n", COLOR_PAIRS);
976 mutt_debug(LL_DEBUG1, " TERM=%s\n", NONULL(term));
977 mutt_debug(LL_DEBUG1, " COLORTERM=%s\n", NONULL(color_term));
978 mutt_debug(LL_DEBUG1, " True color support: %s\n", true_color ? "YES" : "NO");
979 mutt_debug(LL_DEBUG1, " Screen: %dx%d\n", RootWindow->state.cols,
981}
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 1023 of file main.c.

1024{
1025 char *subject = NULL;
1026 char *include_file = NULL;
1027 char *draft_file = NULL;
1028 char *new_type = NULL;
1029 char *dlevel = NULL;
1030 char *dfile = NULL;
1031 const char *cli_nntp = NULL;
1032 struct Email *e = NULL;
1033 struct ListHead attach = STAILQ_HEAD_INITIALIZER(attach);
1034 struct ListHead commands = STAILQ_HEAD_INITIALIZER(commands);
1035 struct ListHead queries = STAILQ_HEAD_INITIALIZER(queries);
1036 struct ListHead alias_queries = STAILQ_HEAD_INITIALIZER(alias_queries);
1037 struct ListHead cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
1038 struct ListHead bcc_list = STAILQ_HEAD_INITIALIZER(bcc_list);
1039 SendFlags sendflags = SEND_NO_FLAGS;
1041 int version = 0;
1042 int i;
1043 bool explicit_folder = false;
1044 bool dump_variables = false;
1045 bool dump_changed = false;
1046 bool one_liner = false;
1047 bool hide_sensitive = false;
1048 bool edit_infile = false;
1049 int double_dash = argc, nargc = 1;
1050 int rc = 1;
1051 bool repeat_error = false;
1052 struct Buffer *folder = buf_pool_get();
1053 struct Buffer *expanded_infile = buf_pool_get();
1054 struct Buffer *tempfile = buf_pool_get();
1055 struct ConfigSet *cs = NULL;
1056
1058
1059 /* sanity check against stupid administrators */
1060 if (getegid() != getgid())
1061 {
1062 mutt_error("%s: I don't want to run with privileges!", (argc != 0) ? argv[0] : "neomutt");
1063 goto main_exit; // TEST01: neomutt (as root, chgrp mail neomutt; chmod +s neomutt)
1064 }
1065
1066 init_locale();
1067
1068 cs = cs_new(500);
1069 if (!cs)
1070 goto main_curses;
1071
1072 NeoMutt = neomutt_new(cs);
1073
1074 NeoMutt->env = envlist_init(envp);
1077
1078 init_config(cs);
1079
1080 for (optind = 1; optind < double_dash;)
1081 {
1082 /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
1083 * encounters a non-option. That could be a file to attach
1084 * (all non-options between -a and --) or it could be an address
1085 * (which gets collapsed to the front of argv). */
1086 for (; optind < argc; optind++)
1087 {
1088 if ((argv[optind][0] == '-') && (argv[optind][1] != '\0'))
1089 {
1090 if ((argv[optind][1] == '-') && (argv[optind][2] == '\0'))
1091 double_dash = optind; /* quit outer loop after getopt */
1092 break; /* drop through to getopt */
1093 }
1094
1095 /* non-option, either an attachment or address */
1096 if (!STAILQ_EMPTY(&attach))
1097 mutt_list_insert_tail(&attach, mutt_str_dup(argv[optind]));
1098 else
1099 argv[nargc++] = argv[optind];
1100 }
1101
1102 i = getopt(argc, argv, "+A:a:b:F:f:Cc:Dd:l:Ee:g:GH:i:hm:nOpQ:RSs:TvyzZ");
1103 if (i != EOF)
1104 {
1105 switch (i)
1106 {
1107 case 'A':
1108 mutt_list_insert_tail(&alias_queries, mutt_str_dup(optarg));
1109 break;
1110 case 'a':
1111 mutt_list_insert_tail(&attach, mutt_str_dup(optarg));
1112 break;
1113 case 'b':
1114 mutt_list_insert_tail(&bcc_list, mutt_str_dup(optarg));
1115 break;
1116 case 'C':
1117 sendflags |= SEND_CLI_CRYPTO;
1118 break;
1119 case 'c':
1120 mutt_list_insert_tail(&cc_list, mutt_str_dup(optarg));
1121 break;
1122 case 'D':
1123 if (dump_variables)
1124 dump_changed = true;
1125 else
1126 dump_variables = true;
1127 break;
1128 case 'd':
1129 dlevel = optarg;
1130 break;
1131 case 'E':
1132 edit_infile = true;
1133 break;
1134 case 'e':
1135 mutt_list_insert_tail(&commands, mutt_str_dup(optarg));
1136 break;
1137 case 'F':
1139 break;
1140 case 'f':
1141 buf_strcpy(folder, optarg);
1142 explicit_folder = true;
1143 break;
1144 case 'g': /* Specify a news server */
1145 cli_nntp = optarg;
1147
1148 case 'G': /* List of newsgroups */
1149 flags |= MUTT_CLI_SELECT | MUTT_CLI_NEWS;
1150 break;
1151 case 'H':
1152 draft_file = optarg;
1153 break;
1154 case 'i':
1155 include_file = optarg;
1156 break;
1157 case 'l':
1158 dfile = optarg;
1159 break;
1160 case 'm':
1161 new_type = optarg;
1162 break;
1163 case 'n':
1164 flags |= MUTT_CLI_NOSYSRC;
1165 break;
1166 case 'O':
1167 one_liner = true;
1168 break;
1169 case 'p':
1170 sendflags |= SEND_POSTPONED;
1171 break;
1172 case 'Q':
1173 mutt_list_insert_tail(&queries, mutt_str_dup(optarg));
1174 break;
1175 case 'R':
1176 flags |= MUTT_CLI_RO; /* read-only mode */
1177 break;
1178 case 'S':
1179 hide_sensitive = true;
1180 break;
1181 case 's':
1182 subject = optarg;
1183 break;
1184 case 'v':
1185 version++;
1186 break;
1187 case 'y': /* My special hack mode */
1188 flags |= MUTT_CLI_SELECT;
1189 break;
1190 case 'Z':
1192 break;
1193 case 'z':
1194 flags |= MUTT_CLI_IGNORE;
1195 break;
1196 default:
1197 OptNoCurses = true;
1198 if (usage())
1199 goto main_ok; // TEST03: neomutt -9
1200 else
1201 goto main_curses;
1202 }
1203 }
1204 }
1205
1206 /* collapse remaining argv */
1207 while (optind < argc)
1208 argv[nargc++] = argv[optind++];
1209 optind = 1;
1210 argc = nargc;
1211
1212 if (version > 0)
1213 {
1215 bool done;
1216 if (version == 1)
1217 done = print_version(stdout);
1218 else
1219 done = print_copyright();
1220 OptNoCurses = true;
1221 if (done)
1222 goto main_ok; // TEST04: neomutt -v
1223 else
1224 goto main_curses;
1225 }
1226
1227 // Change the current umask, and save the original one
1228 NeoMutt->user_default_umask = umask(077);
1229 subjrx_init();
1230 attach_init();
1232
1233#ifdef USE_DEBUG_NOTIFY
1235#endif
1236
1237 if (!get_user_info(cs))
1238 goto main_exit;
1239
1240 reset_tilde(cs);
1241#ifdef ENABLE_NLS
1242 localise_config(cs);
1243#endif
1244
1245 if (dfile)
1246 config_str_set_initial(cs, "debug_file", dfile);
1247
1248 if (dlevel)
1249 {
1250 short num = 0;
1251 if (!mutt_str_atos_full(dlevel, &num) || (num < LL_MESSAGE) || (num >= LL_MAX))
1252 {
1253 mutt_error(_("Error: value '%s' is invalid for -d"), dlevel);
1254 goto main_exit; // TEST07: neomutt -d xyz
1255 }
1256
1257 config_str_set_initial(cs, "debug_level", dlevel);
1258 }
1259
1260 mutt_log_prep();
1263 mutt_debug(LL_DEBUG1, "user's umask %03o\n", NeoMutt->user_default_umask);
1264 mutt_debug(LL_DEBUG3, "umask set to 077\n");
1265
1266 if (!STAILQ_EMPTY(&cc_list) || !STAILQ_EMPTY(&bcc_list))
1267 {
1268 e = email_new();
1269 e->env = mutt_env_new();
1270
1271 struct ListNode *np = NULL;
1272 STAILQ_FOREACH(np, &bcc_list, entries)
1273 {
1274 mutt_addrlist_parse(&e->env->bcc, np->data);
1275 }
1276
1277 STAILQ_FOREACH(np, &cc_list, entries)
1278 {
1279 mutt_addrlist_parse(&e->env->cc, np->data);
1280 }
1281
1282 mutt_list_free(&bcc_list);
1283 mutt_list_free(&cc_list);
1284 }
1285
1286 /* Check for a batch send. */
1287 if (!isatty(STDIN_FILENO) || !STAILQ_EMPTY(&queries) ||
1288 !STAILQ_EMPTY(&alias_queries) || dump_variables)
1289 {
1290 OptNoCurses = true;
1291 sendflags |= SEND_BATCH;
1294 }
1295
1296 /* Check to make sure stdout is available in curses mode. */
1297 if (!OptNoCurses && !isatty(STDOUT_FILENO))
1298 goto main_curses;
1299
1300 /* This must come before mutt_init() because curses needs to be started
1301 * before calling the init_pair() function to set the color scheme. */
1302 if (!OptNoCurses)
1303 {
1304 int crc = start_curses();
1305 if (crc != 0)
1306 goto main_curses; // TEST08: can't test -- fake term?
1307 }
1308
1309 /* Always create the mutt_windows because batch mode has some shared code
1310 * paths that end up referencing them. */
1311 rootwin_new();
1312
1313 if (!OptNoCurses)
1314 {
1315 /* check whether terminal status is supported (must follow curses init) */
1318 log_gui();
1319 }
1320
1322 alias_init();
1323 commands_init();
1324 hooks_init();
1326 imap_init();
1327#ifdef USE_LUA
1328 mutt_lua_init();
1329#endif
1331
1332 menu_init();
1333 sb_init();
1334#ifdef USE_NOTMUCH
1335 nm_init();
1336#endif
1337
1338 /* set defaults and read init files */
1339 int rc2 = mutt_init(cs, dlevel, dfile, flags & MUTT_CLI_NOSYSRC, &commands);
1340 if (rc2 != 0)
1341 goto main_curses;
1342
1345
1346#ifdef USE_NOTMUCH
1347 const bool c_virtual_spool_file = cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
1348 if (c_virtual_spool_file)
1349 {
1350 /* Find the first virtual folder and open it */
1351 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
1353 struct MailboxNode *mp = STAILQ_FIRST(&ml);
1354 if (mp)
1355 cs_str_string_set(cs, "spool_file", mailbox_path(mp->mailbox), NULL);
1357 }
1358#endif
1359
1361
1362 /* "$news_server" precedence: command line, config file, environment, system file */
1363 if (!cli_nntp)
1364 cli_nntp = cs_subset_string(NeoMutt->sub, "news_server");
1365
1366 if (!cli_nntp)
1367 cli_nntp = mutt_str_getenv("NNTPSERVER");
1368
1369 if (!cli_nntp)
1370 {
1371 char buf[1024] = { 0 };
1372 cli_nntp = mutt_file_read_keyword(SYSCONFDIR "/nntpserver", buf, sizeof(buf));
1373 }
1374
1375 if (cli_nntp)
1376 config_str_set_initial(cs, "news_server", cli_nntp);
1377
1378 /* Initialize crypto backends. */
1379 crypt_init();
1380
1381 if (new_type && !config_str_set_initial(cs, "mbox_type", new_type))
1382 goto main_curses;
1383
1384 if (dump_variables || !STAILQ_EMPTY(&queries))
1385 {
1386 const bool tty = isatty(STDOUT_FILENO);
1387
1389 if (tty)
1390 cdflags |= CS_DUMP_LINK_DOCS;
1391 if (hide_sensitive)
1392 cdflags |= CS_DUMP_HIDE_SENSITIVE;
1393 if (one_liner)
1394 cdflags |= CS_DUMP_SHOW_DOCS;
1395
1396 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
1397 if (dump_variables)
1398 {
1399 enum GetElemListFlags gel_flags = dump_changed ? GEL_CHANGED_CONFIG : GEL_ALL_CONFIG;
1400 hea = get_elem_list(cs, gel_flags);
1401 rc = 0;
1402 }
1403 else
1404 {
1405 rc = get_elem_queries(&queries, &hea);
1406 }
1407
1408 dump_config(cs, &hea, cdflags, stdout);
1409 ARRAY_FREE(&hea);
1410 goto main_curses;
1411 }
1412
1413 if (!STAILQ_EMPTY(&alias_queries))
1414 {
1415 rc = 0;
1416 for (; optind < argc; optind++)
1417 mutt_list_insert_tail(&alias_queries, mutt_str_dup(argv[optind]));
1418 struct ListNode *np = NULL;
1419 STAILQ_FOREACH(np, &alias_queries, entries)
1420 {
1421 struct AddressList *al = alias_lookup(np->data);
1422 if (al)
1423 {
1424 /* output in machine-readable form */
1425 mutt_addrlist_to_intl(al, NULL);
1426 struct Buffer *buf = buf_pool_get();
1427 mutt_addrlist_write(al, buf, false);
1428 printf("%s\n", buf_string(buf));
1429 buf_pool_release(&buf);
1430 }
1431 else
1432 {
1433 rc = 1;
1434 printf("%s\n", NONULL(np->data)); // TEST19: neomutt -A unknown
1435 }
1436 }
1437 mutt_list_free(&alias_queries);
1438 goto main_curses; // TEST20: neomutt -A alias
1439 }
1440
1441 if (!OptNoCurses)
1442 {
1444 clear();
1448 }
1449
1450#ifdef USE_AUTOCRYPT
1451 /* Initialize autocrypt after curses messages are working,
1452 * because of the initial account setup screens. */
1453 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
1454 if (c_autocrypt)
1455 mutt_autocrypt_init(!(sendflags & SEND_BATCH));
1456#endif
1457
1458 /* Create the `$folder` directory if it doesn't exist. */
1459 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1460 if (!OptNoCurses && c_folder)
1461 {
1462 struct stat st = { 0 };
1463 struct Buffer *fpath = buf_pool_get();
1464
1465 buf_strcpy(fpath, c_folder);
1466 buf_expand_path(fpath);
1467 bool skip = false;
1468 /* we're not connected yet - skip mail folder creation */
1469 skip |= (imap_path_probe(buf_string(fpath), NULL) == MUTT_IMAP);
1470 skip |= (pop_path_probe(buf_string(fpath), NULL) == MUTT_POP);
1471 skip |= (nntp_path_probe(buf_string(fpath), NULL) == MUTT_NNTP);
1472 if (!skip && (stat(buf_string(fpath), &st) == -1) && (errno == ENOENT))
1473 {
1474 char msg2[256] = { 0 };
1475 snprintf(msg2, sizeof(msg2), _("%s does not exist. Create it?"), c_folder);
1476 if (query_yesorno(msg2, MUTT_YES) == MUTT_YES)
1477 {
1478 if ((mkdir(buf_string(fpath), 0700) == -1) && (errno != EEXIST))
1479 mutt_error(_("Can't create %s: %s"), c_folder, strerror(errno)); // TEST21: neomutt -n -F /dev/null (and ~/Mail doesn't exist)
1480 }
1481 }
1482 buf_pool_release(&fpath);
1483 }
1484
1485 StartupComplete = true;
1486
1491
1492 if (sendflags & SEND_POSTPONED)
1493 {
1494 if (!OptNoCurses)
1495 mutt_flushinp();
1496 if (mutt_send_message(SEND_POSTPONED, NULL, NULL, NULL, NULL, NeoMutt->sub) == 0)
1497 rc = 0;
1498 // TEST23: neomutt -p (postponed message, cancel)
1499 // TEST24: neomutt -p (no postponed message)
1501 repeat_error = true;
1502 goto main_curses;
1503 }
1504 else if (subject || e || draft_file || include_file ||
1505 !STAILQ_EMPTY(&attach) || (optind < argc))
1506 {
1507 FILE *fp_in = NULL;
1508 FILE *fp_out = NULL;
1509 char *infile = NULL;
1510 char *bodytext = NULL;
1511 const char *bodyfile = NULL;
1512 int rv = 0;
1513
1514 if (!OptNoCurses)
1515 mutt_flushinp();
1516
1517 if (!e)
1518 e = email_new();
1519 if (!e->env)
1520 e->env = mutt_env_new();
1521
1522 for (i = optind; i < argc; i++)
1523 {
1524 if (url_check_scheme(argv[i]) == U_MAILTO)
1525 {
1526 if (!mutt_parse_mailto(e->env, &bodytext, argv[i]))
1527 {
1528 mutt_error(_("Failed to parse mailto: link"));
1529 email_free(&e);
1530 goto main_curses; // TEST25: neomutt mailto:?
1531 }
1532 }
1533 else
1534 {
1535 mutt_addrlist_parse(&e->env->to, argv[i]);
1536 }
1537 }
1538
1539 const bool c_auto_edit = cs_subset_bool(NeoMutt->sub, "auto_edit");
1540 if (!draft_file && c_auto_edit && TAILQ_EMPTY(&e->env->to) &&
1541 TAILQ_EMPTY(&e->env->cc))
1542 {
1543 mutt_error(_("No recipients specified"));
1544 email_free(&e);
1545 goto main_curses; // TEST26: neomutt -s test (with auto_edit=yes)
1546 }
1547
1548 if (subject)
1549 {
1550 /* prevent header injection */
1552 mutt_env_set_subject(e->env, subject);
1553 }
1554
1555 if (draft_file)
1556 {
1557 infile = draft_file;
1558 include_file = NULL;
1559 }
1560 else if (include_file)
1561 {
1562 infile = include_file;
1563 }
1564 else
1565 {
1566 edit_infile = false;
1567 }
1568
1569 if (infile || bodytext)
1570 {
1571 /* Prepare fp_in and expanded_infile. */
1572 if (infile)
1573 {
1574 if (mutt_str_equal("-", infile))
1575 {
1576 if (edit_infile)
1577 {
1578 mutt_error(_("Can't use -E flag with stdin"));
1579 email_free(&e);
1580 goto main_curses; // TEST27: neomutt -E -H -
1581 }
1582 fp_in = stdin;
1583 }
1584 else
1585 {
1586 buf_strcpy(expanded_infile, infile);
1587 buf_expand_path(expanded_infile);
1588 fp_in = mutt_file_fopen(buf_string(expanded_infile), "r");
1589 if (!fp_in)
1590 {
1591 mutt_perror("%s", buf_string(expanded_infile));
1592 email_free(&e);
1593 goto main_curses; // TEST28: neomutt -E -H missing
1594 }
1595 }
1596 }
1597
1598 if (edit_infile)
1599 {
1600 /* If editing the infile, keep it around afterwards so
1601 * it doesn't get unlinked, and we can rebuild the draft_file */
1602 sendflags |= SEND_NO_FREE_HEADER;
1603 }
1604 else
1605 {
1606 /* Copy input to a tempfile, and re-point fp_in to the tempfile.
1607 * Note: stdin is always copied to a tempfile, ensuring draft_file
1608 * can stat and get the correct st_size below. */
1609 buf_mktemp(tempfile);
1610
1611 fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1612 if (!fp_out)
1613 {
1614 mutt_file_fclose(&fp_in);
1615 mutt_perror("%s", buf_string(tempfile));
1616 email_free(&e);
1617 goto main_curses; // TEST29: neomutt -H existing-file (where tmpdir=/path/to/FILE blocking tmpdir)
1618 }
1619 if (fp_in)
1620 {
1621 mutt_file_copy_stream(fp_in, fp_out);
1622 if (fp_in == stdin)
1623 sendflags |= SEND_CONSUMED_STDIN;
1624 else
1625 mutt_file_fclose(&fp_in);
1626 }
1627 else if (bodytext)
1628 {
1629 fputs(bodytext, fp_out);
1630 }
1631 mutt_file_fclose(&fp_out);
1632
1633 fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1634 if (!fp_in)
1635 {
1636 mutt_perror("%s", buf_string(tempfile));
1637 email_free(&e);
1638 goto main_curses; // TEST30: can't test
1639 }
1640 }
1641
1642 /* Parse the draft_file into the full Email/Body structure.
1643 * Set SEND_DRAFT_FILE so mutt_send_message doesn't overwrite
1644 * our e->body. */
1645 if (draft_file)
1646 {
1647 struct Envelope *opts_env = e->env;
1648 struct stat st = { 0 };
1649
1650 sendflags |= SEND_DRAFT_FILE;
1651
1652 /* Set up a tmp Email with just enough information so that
1653 * mutt_prepare_template() can parse the message in fp_in. */
1654 struct Email *e_tmp = email_new();
1655 e_tmp->offset = 0;
1656 e_tmp->body = mutt_body_new();
1657 if (fstat(fileno(fp_in), &st) != 0)
1658 {
1659 mutt_perror("%s", draft_file);
1660 email_free(&e);
1661 email_free(&e_tmp);
1662 goto main_curses; // TEST31: can't test
1663 }
1664 e_tmp->body->length = st.st_size;
1665
1666 if (mutt_prepare_template(fp_in, NULL, e, e_tmp, false) < 0)
1667 {
1668 mutt_error(_("Can't parse message template: %s"), draft_file);
1669 email_free(&e);
1670 email_free(&e_tmp);
1671 goto main_curses;
1672 }
1673
1674 /* Scan for neomutt header to set `$resume_draft_files` */
1675 struct ListNode *np = NULL, *tmp = NULL;
1676 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1677 STAILQ_FOREACH_SAFE(np, &e->env->userhdrs, entries, tmp)
1678 {
1679 if (mutt_istr_startswith(np->data, "X-Mutt-Resume-Draft:"))
1680 {
1681 if (c_resume_edited_draft_files)
1682 cs_str_native_set(cs, "resume_draft_files", true, NULL);
1683
1684 STAILQ_REMOVE(&e->env->userhdrs, np, ListNode, entries);
1685 FREE(&np->data);
1686 FREE(&np);
1687 }
1688 }
1689
1690 mutt_addrlist_copy(&e->env->to, &opts_env->to, false);
1691 mutt_addrlist_copy(&e->env->cc, &opts_env->cc, false);
1692 mutt_addrlist_copy(&e->env->bcc, &opts_env->bcc, false);
1693 if (opts_env->subject)
1694 mutt_env_set_subject(e->env, opts_env->subject);
1695
1696 mutt_env_free(&opts_env);
1697 email_free(&e_tmp);
1698 }
1699 else if (edit_infile)
1700 {
1701 /* Editing the include_file: pass it directly in.
1702 * Note that SEND_NO_FREE_HEADER is set above so it isn't unlinked. */
1703 bodyfile = buf_string(expanded_infile);
1704 }
1705 else
1706 {
1707 // For bodytext and unedited include_file: use the tempfile.
1708 bodyfile = buf_string(tempfile);
1709 }
1710
1711 mutt_file_fclose(&fp_in);
1712 }
1713
1714 FREE(&bodytext);
1715
1716 if (!STAILQ_EMPTY(&attach))
1717 {
1718 struct Body *b = e->body;
1719
1720 while (b && b->next)
1721 b = b->next;
1722
1723 struct ListNode *np = NULL;
1724 STAILQ_FOREACH(np, &attach, entries)
1725 {
1726 if (b)
1727 {
1729 b = b->next;
1730 }
1731 else
1732 {
1734 e->body = b;
1735 }
1736 if (!b)
1737 {
1738 mutt_error(_("%s: unable to attach file"), np->data);
1739 mutt_list_free(&attach);
1740 email_free(&e);
1741 goto main_curses; // TEST32: neomutt john@example.com -a missing
1742 }
1743 }
1744 mutt_list_free(&attach);
1745 }
1746
1747 rv = mutt_send_message(sendflags, e, bodyfile, NULL, NULL, NeoMutt->sub);
1748 /* We WANT the "Mail sent." and any possible, later error */
1750 if (ErrorBufMessage)
1751 mutt_message("%s", ErrorBuf);
1752
1753 if (edit_infile)
1754 {
1755 if (draft_file)
1756 {
1757 if (truncate(buf_string(expanded_infile), 0) == -1)
1758 {
1759 mutt_perror("%s", buf_string(expanded_infile));
1760 email_free(&e);
1761 goto main_curses; // TEST33: neomutt -H read-only -s test john@example.com -E
1762 }
1763 fp_out = mutt_file_fopen(buf_string(expanded_infile), "a");
1764 if (!fp_out)
1765 {
1766 mutt_perror("%s", buf_string(expanded_infile));
1767 email_free(&e);
1768 goto main_curses; // TEST34: can't test
1769 }
1770
1771 /* If the message was sent or postponed, these will already
1772 * have been done. */
1773 if (rv < 0)
1774 {
1775 if (e->body->next)
1776 e->body = mutt_make_multipart(e->body);
1778 mutt_prepare_envelope(e->env, false, NeoMutt->sub);
1779 mutt_env_to_intl(e->env, NULL, NULL);
1780 }
1781
1782 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1784 c_crypt_protected_headers_read &&
1786 NeoMutt->sub);
1787 const bool c_resume_edited_draft_files = cs_subset_bool(NeoMutt->sub, "resume_edited_draft_files");
1788 if (c_resume_edited_draft_files)
1789 fprintf(fp_out, "X-Mutt-Resume-Draft: 1\n");
1790 fputc('\n', fp_out);
1791 if ((mutt_write_mime_body(e->body, fp_out, NeoMutt->sub) == -1))
1792 {
1793 mutt_file_fclose(&fp_out);
1794 email_free(&e);
1795 goto main_curses; // TEST35: can't test
1796 }
1797 mutt_file_fclose(&fp_out);
1798 }
1799
1800 email_free(&e);
1801 }
1802
1803 /* !edit_infile && draft_file will leave the tempfile around */
1804 if (!buf_is_empty(tempfile))
1805 unlink(buf_string(tempfile));
1806
1808
1809 if (rv != 0)
1810 goto main_curses; // TEST36: neomutt -H existing -s test john@example.com -E (cancel sending)
1811 }
1812 else if (sendflags & SEND_BATCH)
1813 {
1814 /* This guards against invoking `neomutt < /dev/null` and accidentally
1815 * sending an email due to a my_hdr or other setting. */
1816 mutt_error(_("No recipients specified"));
1817 goto main_curses;
1818 }
1819 else
1820 {
1821 if (flags & MUTT_CLI_MAILBOX)
1822 {
1823 const bool c_imap_passive = cs_subset_bool(NeoMutt->sub, "imap_passive");
1824 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", false, NULL);
1826 if (mutt_mailbox_check(NULL, csflags) == 0)
1827 {
1828 mutt_message(_("No mailbox with new mail"));
1829 repeat_error = true;
1830 goto main_curses; // TEST37: neomutt -Z (no new mail)
1831 }
1832 buf_reset(folder);
1833 mutt_mailbox_next(NULL, folder);
1834 cs_subset_str_native_set(NeoMutt->sub, "imap_passive", c_imap_passive, NULL);
1835 }
1836 else if (flags & MUTT_CLI_SELECT)
1837 {
1838 if (flags & MUTT_CLI_NEWS)
1839 {
1840 const char *const c_news_server = cs_subset_string(NeoMutt->sub, "news_server");
1841 OptNews = true;
1842 CurrentNewsSrv = nntp_select_server(NULL, c_news_server, false);
1843 if (!CurrentNewsSrv)
1844 goto main_curses; // TEST38: neomutt -G (unset news_server)
1845 }
1846 else if (TAILQ_EMPTY(&NeoMutt->accounts))
1847 {
1848 mutt_error(_("No incoming mailboxes defined"));
1849 goto main_curses; // TEST39: neomutt -n -F /dev/null -y
1850 }
1851 buf_reset(folder);
1852 dlg_browser(folder, MUTT_SEL_FOLDER | MUTT_SEL_MAILBOX, NULL, NULL, NULL);
1853 if (buf_is_empty(folder))
1854 {
1855 goto main_ok; // TEST40: neomutt -y (quit selection)
1856 }
1857 }
1858
1859 if (buf_is_empty(folder))
1860 {
1861 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1862 if (c_spool_file)
1863 {
1864 // Check if `$spool_file` corresponds a mailboxes' description.
1865 struct Mailbox *m_desc = mailbox_find_name(c_spool_file);
1866 if (m_desc)
1867 buf_strcpy(folder, m_desc->realpath);
1868 else
1869 buf_strcpy(folder, c_spool_file);
1870 }
1871 else if (c_folder)
1872 {
1873 buf_strcpy(folder, c_folder);
1874 }
1875 /* else no folder */
1876 }
1877
1878 if (OptNews)
1879 {
1880 OptNews = false;
1881 buf_alloc(folder, PATH_MAX);
1882 nntp_expand_path(folder->data, folder->dsize, &CurrentNewsSrv->conn->account);
1883 }
1884 else
1885 {
1886 buf_expand_path(folder);
1887 }
1888
1891
1892 if (flags & MUTT_CLI_IGNORE)
1893 {
1894 /* check to see if there are any messages in the folder */
1895 switch (mx_path_is_empty(folder))
1896 {
1897 case -1:
1898 mutt_perror("%s", buf_string(folder));
1899 goto main_curses; // TEST41: neomutt -z -f missing
1900 case 1:
1901 mutt_error(_("Mailbox is empty"));
1902 goto main_curses; // TEST42: neomutt -z -f /dev/null
1903 }
1904 }
1905
1906 struct Mailbox *m_cur = mailbox_find(buf_string(folder));
1907 // Take a copy of the name just in case the hook alters m_cur
1908 const char *name = m_cur ? mutt_str_dup(m_cur->name) : NULL;
1910 FREE(&name);
1912 mutt_debug(LL_NOTIFY, "NT_GLOBAL_STARTUP\n");
1914
1916 window_redraw(NULL);
1917
1918 repeat_error = true;
1919 struct Mailbox *m = mx_resolve(buf_string(folder));
1920 const bool c_read_only = cs_subset_bool(NeoMutt->sub, "read_only");
1921 if (!mx_mbox_open(m, ((flags & MUTT_CLI_RO) || c_read_only) ? MUTT_READONLY : MUTT_OPEN_NO_FLAGS))
1922 {
1923 if (m->account)
1925
1926 mailbox_free(&m);
1927 mutt_error(_("Unable to open mailbox %s"), buf_string(folder));
1928 repeat_error = false;
1929 }
1930 if (m || !explicit_folder)
1931 {
1932 struct MuttWindow *dlg = index_pager_init();
1933 dialog_push(dlg);
1934
1936 m = dlg_index(dlg, m);
1938 mailbox_free(&m);
1939
1940 dialog_pop();
1941 mutt_window_free(&dlg);
1943 repeat_error = false;
1944 }
1946#ifdef USE_SASL_CYRUS
1948#endif
1949#ifdef USE_SASL_GNU
1951#endif
1952#ifdef USE_AUTOCRYPT
1954#endif
1955 // TEST43: neomutt (no change to mailbox)
1956 // TEST44: neomutt (change mailbox)
1957 }
1958
1959main_ok:
1960 rc = 0;
1961main_curses:
1962 mutt_endwin();
1964 /* Repeat the last message to the user */
1965 if (repeat_error && ErrorBufMessage)
1966 puts(ErrorBuf);
1967main_exit:
1968 if (NeoMutt && NeoMutt->sub)
1969 {
1974 }
1975 mutt_list_free(&commands);
1977 buf_pool_release(&folder);
1978 buf_pool_release(&expanded_infile);
1979 buf_pool_release(&tempfile);
1980 mutt_list_free(&queries);
1984 if (NeoMutt)
1988 menu_cleanup();
1989 crypt_cleanup();
1991
1993
1994 alias_cleanup();
1995 sb_cleanup();
1996
2002
2005
2006 /* Lists of strings */
2016
2018
2020 FREE(&LastFolder);
2022
2024
2026
2029
2031 if (NeoMutt)
2033
2041 cs_free(&cs);
2043 mutt_log_stop();
2044 return rc;
2045}
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:719
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:711
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_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 source_stack_cleanup(void)
Free memory from the stack used for the source command.
Definition: commands.c:1671
bool commands_init(void)
Initialize commands array and register default commands.
Definition: commands.c:1748
void mutt_comp_init(void)
Setup Compressed Mailbox 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:788
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_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: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:1437
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: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:50
struct ListHead HeaderOrderList
List of header fields in the order they should be displayed.
Definition: globals.c:46
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:95
void mutt_grouplist_cleanup(void)
Free GroupList singleton resource.
Definition: group.c:107
void dlg_browser(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file -.
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:1100
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 -.
Definition: mutt_logging.c:88
#define mutt_message(...)
Definition: logging2.h:92
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:2348
int main_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: init.c:250
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:986
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:965
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:632
void hooks_init(void)
Setup feature commands.
Definition: hook.c:1053
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:54
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:36
void imap_logout_all(void)
Close all open connections.
Definition: imap.c:557
void imap_init(void)
Setup feature commands.
Definition: imap.c:96
void mutt_keys_cleanup(void)
Free the key maps.
Definition: init.c:215
void mutt_init_abort_key(void)
Parse the abort_key config string.
Definition: init.c:228
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:46
@ LL_MESSAGE
Log informational message.
Definition: logging2.h:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:49
@ LL_MAX
Definition: logging2.h:51
#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:868
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:937
#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:963
static void reset_tilde(struct ConfigSet *cs)
Temporary measure.
Definition: main.c:707
static bool usage(void)
Display NeoMutt command line.
Definition: main.c:759
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:836
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:896
#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: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: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:468
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:1710
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
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:173
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:196
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:67
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:109
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:1489
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2034
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:47
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:51
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:52
uint32_t SendFlags
Flags for mutt_send_message(), e.g. SEND_REPLY.
Definition: send.h:40
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:46
#define SEND_CONSUMED_STDIN
stdin has been read; don't read it twice
Definition: send.h:57
#define SEND_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:204
void sb_cleanup(void)
Clean up the Sidebar.
Definition: sidebar.c:220
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:248
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 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:55
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:48
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
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
GetElemListFlags
Flags for get_elem_list()
Definition: subset.h:80
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition: subset.h:82
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.