CheckStructMember to check for dirent.d_ino
[apps/madmutt.git] / main.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
4  * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.org>
5  * Copyright (C) 2004 g10 Code GmbH
6  *
7  * Parts written/modified by:
8  * Nico Golde <nion@muttng.org>
9  * Andreas Krennmair <ak@synflood.at>
10  *
11  * This file is part of mutt-ng, see http://www.muttng.org/.
12  * It's licensed under the GNU General Public License,
13  * please see the file GPL in the top level source directory.
14  */
15
16 #define MAIN_C 1
17
18 #include <lib-lib/lib-lib.h>
19
20 #include <sys/utsname.h>
21
22 #include <lib-lua/lib-lua.h>
23 #include <lib-sys/mutt_signal.h>
24 #include <lib-mime/mime.h>
25 #include <lib-ui/curses.h>
26 #include <lib-mx/mx.h>
27
28 #include "mutt.h"
29 #include "crypt.h"
30 #include "alias.h"
31 #include "buffy.h"
32 #include "sort.h"
33 #include "keymap.h"
34 #include "mutt_idna.h"
35 #include "mutt_sasl.h"
36
37 #ifdef HAVE_GETOPT_H
38 #include <getopt.h>
39 #else
40 extern char *optarg;
41 extern int optind;
42 #endif
43
44 #ifdef HAVE_LIBIDN
45 #include <stringprep.h>
46 #endif
47
48 #ifdef USE_NNTP
49 #include <nntp/nntp.h>
50 #endif
51
52 #ifdef USE_LIBESMTP
53 #include <libesmtp.h>
54 #endif
55
56 #ifdef USE_HCACHE
57 #if defined(HAVE_QDBM)
58 #include <depot.h>
59 #elif defined(HAVE_GDBM)
60 #include <gdbm.h>
61 #endif
62 #endif
63
64 #include <gnutls/gnutls.h>
65 #include <gpgme.h>
66
67 static const char *Notice = N_("\
68 Copyright (C) 1996-2002 Michael R. Elkins and others.\n\
69 Copyright (C) 2005 The Mutt-ng Team\n\
70 Copyright (C) 2006 Pierre Habouzit undation, Inc.\n\
71 This is free software.  You may redistribute copies of it under the terms of\n\
72 the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n\
73 There is NO WARRANTY, to the extent permitted by law.\n");
74
75 void mutt_exit (int code)
76 {
77   mutt_endwin (NULL);
78   exit (code);
79 }
80
81 static void mutt_usage (void)
82 {
83   puts (mutt_make_version());
84
85   puts
86     _("usage: madmutt [ -nRyzZ ] [ -e <cmd> ] [ -F <file> ] [ -m <type> ] [ -f <file> ]\n\
87        madmutt [ -nR ] [ -e <cmd> ] [ -F <file> ] -Q <query> [ -Q <query> ] [...]\n\
88        madmutt [ -nR ] [ -e <cmd> ] [ -F <file> ] -A <alias> [ -A <alias> ] [...]\n\
89        madmutt [ -nR ] [ -e <cmd> ] [ -F <file> ] -t");
90   puts
91     _("\
92        madmutt [ -nR ] [ -e <cmd> ] [ -F <file> ] -T\n\
93        madmutt [ -nx ] [ -e <cmd> ] [ -a <file> ] [ -F <file> ] [ -H <file> ] [ -i <file> ] [ -s <subj> ] [ -b <addr> ] [ -c <addr> ] <addr> [ ... ]\n\
94        madmutt [ -n ] [ -e <cmd> ] [ -F <file> ] -p\n\
95        madmutt -v\n\
96 \n\
97 options:\n\
98   -A <alias>\texpand the given alias\n\
99   -a <file>\tattach a file to the message\n\
100   -b <address>\tspecify a blind carbon-copy (BCC) address\n\
101   -c <address>\tspecify a carbon-copy (CC) address");
102   puts _("\
103   -e <command>\tspecify a command to be executed after initialization\n\
104   -f <file>\tspecify which mailbox to read\n\
105   -F <file>\tspecify an alternate muttrngc file\n\
106   -g <server>\tspecify a newsserver (if compiled with NNTP)\n\
107   -G\t\tselect a newsgroup (if compiled with NNTP)\n\
108   -H <file>\tspecify a draft file to read header and body from\n\
109   -i <file>\tspecify a file which Madmutt should include in the body");
110   puts _("\
111   -d <level>\t specify debugging level of Madmutt\n\
112   -m <type>\tspecify a default mailbox type\n\
113   -n\t\tcauses Madmutt not to read the system Madmuttrc\n\
114   -p\t\trecall a postponed message\n\
115   -Q <variable>\tquery a configuration variable\n\
116   -R\t\topen mailbox in read-only mode\n\
117   -s <subj>\tspecify a subject (must be in quotes if it has spaces)");
118   puts _("\
119   -t\t\tprint the value of all variables to stdout\n\
120   -T\t\tprint the value of all changed variables to stdout\n\
121   -v\t\tshow version and compile-time definitions\n\
122   -y\t\tselect a mailbox specified in your `mailboxes' list\n\
123   -z\t\texit immediately if there are no messages in the mailbox\n\
124   -Z\t\topen the first folder with new message, exit immediately if none\n\
125   -h\t\tthis help message");
126
127   exit (0);
128 }
129
130 static void show_version (void)
131 {
132   struct utsname uts;
133 #ifdef USE_LIBESMTP
134   char buf[STRING];
135 #endif
136
137   puts (mutt_make_version());
138   puts (_(Notice));
139
140   uname (&uts);
141
142 #ifdef _AIX
143   printf ("System:\n  %s %s.%s", uts.sysname, uts.version, uts.release);
144 #elif defined (SCO)
145   printf ("System:\n  SCO %s", uts.release);
146 #else
147   printf ("System:\n  %s %s", uts.sysname, uts.release);
148 #endif
149
150   printf (" (%s)\nExternal Libraries:\n", uts.machine);
151
152 #ifdef NCURSES_VERSION
153   printf ("  ncurses %s\n", NCURSES_VERSION);
154 #elif defined(USE_SLANG_CURSES)
155   printf ("  slang %d\n", SLANG_VERSION);
156 #endif
157
158 #ifdef _LIBICONV_VERSION
159   printf ("  libiconv %d.%d\n", _LIBICONV_VERSION >> 8,
160           _LIBICONV_VERSION & 0xff);
161 #endif
162
163 #ifdef HAVE_LIBIDN
164   printf ("  libidn %s (compiled with %s)\n",
165           stringprep_check_version (NULL), STRINGPREP_VERSION);
166 #endif
167
168 #ifdef USE_LIBESMTP
169   smtp_version (buf, sizeof (buf), 0);
170   printf ("  libESMTP %s\n", buf);
171 #endif
172
173 #ifdef USE_HCACHE
174 #if defined(HAVE_QDBM)
175   printf ("  qdbm %s\n", dpversion);
176 #elif defined(HAVE_GDBM)
177   printf ("  gdbm %s\n", gdbm_version);
178 #endif
179 #endif
180
181   printf ("  gnutls %s\n", LIBGNUTLS_VERSION);
182   printf ("  gpgme %s\n", GPGME_VERSION);
183   puts (_("Compile Options:"));
184
185   puts (
186 #ifdef USE_SETGID
187          "+USE_SETGID  "
188 #else
189          "-USE_SETGID  "
190 #endif
191 #ifdef USE_FCNTL
192          "+USE_FCNTL  "
193 #else
194          "-USE_FCNTL  "
195 #endif
196 #ifdef USE_FLOCK
197          "+USE_FLOCK   "
198 #else
199          "-USE_FLOCK   "
200 #endif
201 #ifdef USE_HCACHE
202          "+USE_HCACHE  "
203 #else
204          "-USE_HCACHE  "
205 #endif
206     );
207   puts (
208 #ifdef USE_NNTP
209          "+USE_NNTP  "
210 #else
211          "-USE_NNTP  "
212 #endif
213 #ifdef USE_LIBESMTP
214          "+USE_LIBESMTP  "
215 #else
216          "-USE_LIBESMTP  "
217 #endif
218          "\n  "
219 #ifdef HAVE_REGCOMP
220          "+HAVE_REGCOMP  "
221 #else
222          "-HAVE_REGCOMP  "
223 #endif
224          "\n  "
225 #ifdef HAVE_TYPEAHEAD
226          "+HAVE_TYPEAHEAD  "
227 #else
228          "-HAVE_TYPEAHEAD  "
229 #endif
230 #ifdef HAVE_BKGDSET
231          "+HAVE_BKGDSET  "
232 #else
233          "-HAVE_BKGDSET  "
234 #endif
235          "\n  "
236 #ifdef HAVE_CURS_SET
237          "+HAVE_CURS_SET  "
238 #else
239          "-HAVE_CURS_SET  "
240 #endif
241 #ifdef HAVE_META
242          "+HAVE_META  "
243 #else
244          "-HAVE_META  "
245 #endif
246 #ifdef HAVE_RESIZETERM
247          "+HAVE_RESIZETERM  "
248 #else
249          "-HAVE_RESIZETERM  "
250 #endif
251     );
252
253   puts (
254          "+CRYPT_BACKEND_GPGME  "
255          "\n  "
256 #ifdef ENABLE_NLS
257          "+ENABLE_NLS  "
258 #else
259          "-ENABLE_NLS  "
260 #endif
261 #ifdef HAVE_WC_FUNCS
262          "+HAVE_WC_FUNCS  "
263 #else
264          "-HAVE_WC_FUNCS  "
265 #endif
266 #ifdef HAVE_LANGINFO_CODESET
267          "+HAVE_LANGINFO_CODESET  "
268 #else
269          "-HAVE_LANGINFO_CODESET  "
270 #endif
271 #ifdef HAVE_ICONV
272          "+HAVE_ICONV  "
273 #else
274          "-HAVE_ICONV  "
275 #endif
276 #ifdef HAVE_LIBIDN
277          "+HAVE_LIBIDN  "
278 #else
279          "-HAVE_LIBIDN  "
280 #endif
281 #ifdef HAVE_GETSID
282          "+HAVE_GETSID  "
283 #else
284          "-HAVE_GETSID  "
285 #endif
286     );
287
288   puts (_("Built-In Defaults:"));
289   printf ("  +SENDMAIL=\"%s\"\n", SENDMAIL);
290   printf ("  +MAILPATH=\"%s\"\n", MAILPATH);
291   printf ("  +PKGDATADIR=\"%s\"\n", PKGDATADIR);
292   printf ("  +PKGDOCDIR=\"%s\"\n", PKGDOCDIR);
293   printf ("  +SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
294   printf ("  +MIXMASTER=\"%s\"\n\n", MIXMASTER);
295
296   puts (_("MadMutt is based on Madmutt wich was based on Mutt before\n"));
297
298   exit (0);
299 }
300
301 static void start_curses (void)
302 {
303   km_init ();                   /* must come before mutt_init */
304
305 #ifdef USE_SLANG_CURSES
306   SLtt_Ignore_Beep = 1;         /* don't do that #*$@^! annoying visual beep! */
307   SLsmg_Display_Eight_Bit = 128;        /* characters above this are printable */
308   SLtt_set_color (0, NULL, "default", "default");
309 #else
310   /* should come before initscr() so that ncurses 4.2 doesn't try to install
311      its own SIGWINCH handler */
312   mutt_signal_initialize ();
313 #endif
314   if (initscr () == NULL) {
315     puts _("Error initializing terminal.");
316
317     exit (1);
318   }
319   mutt_signal_initialize ();
320   ci_start_color ();
321   keypad (stdscr, TRUE);
322   cbreak ();
323   noecho ();
324 #ifdef HAVE_TYPEAHEAD
325   typeahead (-1);               /* simulate smooth scrolling */
326 #endif
327 #ifdef HAVE_META
328   meta (stdscr, TRUE);
329 #endif
330 }
331
332 #define M_IGNORE  (1<<0)        /* -z */
333 #define M_BUFFY   (1<<1)        /* -Z */
334 #define M_NOSYSRC (1<<2)        /* -n */
335 #define M_RO      (1<<3)        /* -R */
336 #define M_SELECT  (1<<4)        /* -y */
337 #ifdef USE_NNTP
338 #define M_NEWS    (1<<5)        /* -g and -G */
339 #endif
340
341 __attribute__((format(printf, 1, 0)))
342 static void mutt_nocurses_error (const char *fmt, ...)
343 {
344     va_list ap;
345
346     va_start(ap, fmt);
347     vfprintf(stderr, fmt, ap);
348     va_end(ap);
349     fputc('\n', stderr);
350 }
351
352 int main (int argc, char **argv)
353 {
354   char folder[_POSIX_PATH_MAX] = "";
355   char *subject = NULL;
356   char *includeFile = NULL;
357   char *draftFile = NULL;
358   char *newMagic = NULL;
359   HEADER *msg = NULL;
360   string_list_t *attach = NULL;
361   string_list_t *commands = NULL;
362   string_list_t *queries = NULL;
363   string_list_t *alias_queries = NULL;
364   int sendflags = 0;
365   int flags = 0;
366   int version = 0;
367   int i;
368   int explicit_folder = 0;
369   int dump_variables = -1;
370
371   /* initialize random number for tmp file creation */ 
372   srand48((unsigned int) time (NULL));
373   
374   /* sanity check against stupid administrators */
375   
376   if (getegid () != getgid ()) {
377     fprintf (stderr, "%s: I don't want to run with privileges!\n", argv[0]);
378     exit (1);
379   }
380
381 #ifdef ENABLE_NLS
382   /* FIXME what about init.c:1439 ? */
383   setlocale (LC_ALL, "");
384   bindtextdomain (PACKAGE, MUTTLOCALEDIR);
385   textdomain (PACKAGE);
386 #endif
387
388   setlocale (LC_CTYPE, "");
389
390   mutt_error = mutt_message = mutt_nocurses_error;
391   srand48 (time (NULL));
392   umask (077);
393
394   p_clear(Options, countof(Options));
395   p_clear(QuadOptions, countof(QuadOptions));
396
397   while ((i = getopt(argc, argv, "A:a:b:F:f:c:e:H:s:i:hm:npQ:RTtvyzZ"
398 #ifdef USE_NNTP
399                                                                     "g:G"
400 #endif
401                     )) >= 0)
402     switch (i) {
403     case 'A':
404       alias_queries = mutt_add_list (alias_queries, optarg);
405       break;
406     case 'a':
407       if (strlen(optarg)<=512)
408         attach = mutt_add_list (attach, optarg);
409       else{
410         printf("too long arguments. exiting ...\n");
411         exit(1);
412       }
413       break;
414
415     case 'F':
416       m_strreplace(&Muttrc, optarg);
417       break;
418
419     case 'f':
420       m_strcpy(folder, sizeof(folder), optarg);
421       explicit_folder = 1;
422       break;
423
424     case 'b':
425     case 'c':
426       if (!msg)
427         msg = header_new();
428       if (!msg->env)
429         msg->env = envelope_new();
430       if (i == 'b')
431         msg->env->bcc = rfc822_parse_adrlist (msg->env->bcc, optarg);
432       else
433         msg->env->cc = rfc822_parse_adrlist (msg->env->cc, optarg);
434       break;
435
436     case 't':
437       dump_variables = 2;
438       break;
439
440     case 'T':
441       dump_variables = 1;
442       break;
443
444     case 'e':
445       commands = mutt_add_list (commands, optarg);
446       break;
447
448     case 'H':
449       draftFile = optarg;
450       break;
451
452     case 'i':
453       includeFile = optarg;
454       break;
455
456     case 'm':
457       /* should take precedence over .muttrc setting, so save it for later */
458       newMagic = optarg;
459       break;
460
461     case 'n':
462       flags |= M_NOSYSRC;
463       break;
464
465     case 'p':
466       sendflags |= SENDPOSTPONED;
467       break;
468
469     case 'Q':
470       queries = mutt_add_list (queries, optarg);
471       break;
472
473     case 'R':
474       flags |= M_RO;            /* read-only mode */
475       break;
476
477     case 's':
478       subject = optarg;
479       break;
480
481     case 'v':
482       version++;
483       break;
484
485     case 'y':                  /* My special hack mode */
486       flags |= M_SELECT;
487       break;
488
489 #ifdef USE_NNTP
490     case 'g':                  /* Specify a newsserver */
491       {
492         char buf[LONG_STRING];
493
494         snprintf (buf, sizeof (buf), "set nntp_host=%s", optarg);
495         commands = mutt_add_list (commands, buf);
496       }
497
498     case 'G':                  /* List of newsgroups */
499       flags |= M_SELECT | M_NEWS;
500       break;
501 #endif
502
503     case 'z':
504       flags |= M_IGNORE;
505       break;
506
507     case 'Z':
508       flags |= M_BUFFY | M_IGNORE;
509       break;
510
511     default:
512       mutt_usage ();
513     }
514
515   if (version) {
516     show_version ();
517   }
518
519   /* Check for a batch send. */
520   if (!isatty (0) || queries || alias_queries || dump_variables > 0) {
521     set_option (OPTNOCURSES);
522     sendflags = SENDBATCH;
523   }
524
525   /* This must come before mutt_init() because curses needs to be started
526      before calling the init_pair() function to set the color scheme.  */
527   if (!option (OPTNOCURSES))
528     start_curses ();
529
530   /* set defaults and read init files */
531   mutt_init (flags & M_NOSYSRC, commands);
532   string_list_wipe(&commands);
533
534   if (queries)
535     return mutt_query_variables (queries);
536   if (dump_variables > 0)
537     return (mutt_dump_variables (dump_variables-1));
538
539   if (alias_queries) {
540     int rv = 0;
541     address_t *a;
542
543     for (; alias_queries; alias_queries = alias_queries->next) {
544       if ((a = address_list_dup(alias_lookup(alias_queries->data)))) {
545         /* output in machine-readable form */
546         mutt_addrlist_to_idna (a, NULL);
547         mutt_write_address_list (a, stdout, 0, 0);
548         address_list_wipe(&a);
549       } else {
550         rv = 1;
551         printf ("%s\n", alias_queries->data);
552       }
553     }
554     return rv;
555   }
556
557   if (newMagic)
558     mx_set_magic (newMagic);
559
560   if (!option (OPTNOCURSES)) {
561     SETCOLOR (MT_COLOR_NORMAL);
562     clear ();
563     mutt_error = mutt_curses_error;
564     mutt_message = mutt_curses_message;
565   }
566
567   /* Create the Maildir directory if it doesn't exist. */
568   if (!option (OPTNOCURSES) && Maildir) {
569     struct stat sb;
570     char fpath[_POSIX_PATH_MAX];
571     char mesg[STRING];
572
573     m_strcpy(fpath, sizeof(fpath), Maildir);
574     mutt_expand_path (fpath, sizeof (fpath));
575     /* we're not connected yet - skip mail folder creation */
576     if (mx_get_magic (fpath) != M_IMAP)
577       if (stat (fpath, &sb) == -1 && errno == ENOENT) {
578         snprintf (mesg, sizeof (mesg), _("%s does not exist. Create it?"),
579                   Maildir);
580         if (mutt_yesorno (mesg, M_YES) == M_YES) {
581           if (mkdir (fpath, 0700) == -1 && errno != EEXIST)
582             mutt_error (_("Can't create %s: %s."), Maildir, strerror (errno));
583         }
584       }
585   }
586
587   if (sendflags & SENDPOSTPONED) {
588     if (!option (OPTNOCURSES))
589       mutt_flushinp ();
590     ci_send_message (SENDPOSTPONED, NULL, NULL, NULL, NULL);
591     mutt_endwin (NULL);
592   }
593   else if (subject || msg || sendflags || draftFile || includeFile || attach
594            || optind < argc) {
595     FILE *fin = NULL;
596     char buf[LONG_STRING];
597     char *tempfile = NULL, *infile = NULL;
598     char *bodytext = NULL;
599     FILE *fout;
600
601     if (!option (OPTNOCURSES))
602       mutt_flushinp ();
603
604     if (!msg)
605       msg = header_new();
606
607     if (draftFile)
608       infile = draftFile;
609     else {
610       if (!msg->env)
611         msg->env = envelope_new();
612
613       for (i = optind; i < argc; i++) {
614         if (url_check_scheme (argv[i]) == U_MAILTO)
615           url_parse_mailto (msg->env, &bodytext, argv[i]);
616         else
617           msg->env->to = rfc822_parse_adrlist (msg->env->to, argv[i]);
618       }
619
620       if (option (OPTAUTOEDIT) && !msg->env->to && !msg->env->cc) {
621         if (!option (OPTNOCURSES))
622           mutt_endwin (NULL);
623         fputs (_("No recipients specified.\n"), stderr);
624         exit (1);
625       }
626
627       if (subject)
628         msg->env->subject = m_strdup(subject);
629
630       if (includeFile)
631         infile = includeFile;
632     }
633
634     if (infile || bodytext) {
635       if (infile) {
636         if (m_strcmp("-", infile) == 0)
637           fin = stdin;
638         else {
639           char path[_POSIX_PATH_MAX];
640
641           m_strcpy(path, sizeof(path), infile);
642           mutt_expand_path (path, sizeof (path));
643           if ((fin = fopen (path, "r")) == NULL) {
644             if (!option (OPTNOCURSES))
645               mutt_endwin (NULL);
646             perror (path);
647             exit (1);
648           }
649         }
650       }
651       else
652         fin = NULL;
653
654       if (draftFile)
655         msg->env = mutt_read_rfc822_header (fin, NULL, 1, 0);
656
657       /* is the following if still needed? */
658
659       fout = m_tempfile(buf, sizeof(buf), NONULL(MCore.tmpdir), NULL);
660       tempfile = m_strdup(buf);
661
662       if (tempfile) {
663         if (!fout) {
664           if (!option (OPTNOCURSES))
665             mutt_endwin (NULL);
666           perror (tempfile);
667           m_fclose(&fin);
668           p_delete(&tempfile);
669           exit (1);
670         }
671         if (fin)
672           mutt_copy_stream (fin, fout);
673         else if (bodytext)
674           fputs (bodytext, fout);
675         m_fclose(&fout);
676         if (fin && fin != stdin)
677           m_fclose(&fin);
678       }
679     }
680
681     p_delete(&bodytext);
682
683     if (attach) {
684       string_list_t *t = attach;
685       BODY *a = NULL;
686
687       while (t) {
688         if (a) {
689           a->next = mutt_make_file_attach (t->data);
690           a = a->next;
691         }
692         else
693           msg->content = a = mutt_make_file_attach (t->data);
694         if (!a) {
695           if (!option (OPTNOCURSES))
696             mutt_endwin (NULL);
697           fprintf (stderr, _("%s: unable to attach file.\n"), t->data);
698           string_list_wipe(&attach);
699           exit (1);
700         }
701         t = t->next;
702       }
703       string_list_wipe(&attach);
704     }
705
706     ci_send_message (sendflags, msg, tempfile, NULL, NULL);
707
708     if (!option (OPTNOCURSES))
709       mutt_endwin (NULL);
710   }
711   else {
712     if (flags & M_BUFFY) {
713       if (!buffy_check (0)) {
714         mutt_endwin _("No mailbox with new mail.");
715
716         exit (1);
717       }
718       folder[0] = 0;
719       buffy_next (folder, sizeof (folder));
720     }
721     else if (flags & M_SELECT) {
722 #ifdef USE_NNTP
723       if (flags & M_NEWS) {
724         set_option (OPTNEWS);
725         if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer))) {
726           mutt_endwin (Errorbuf);
727           exit (1);
728         }
729       } else
730 #endif
731       if (!Incoming.len) {
732         mutt_endwin _("No incoming mailboxes defined.");
733
734         exit (1);
735       }
736       folder[0] = 0;
737       mutt_select_file (folder, sizeof (folder), M_SEL_FOLDER | M_SEL_BUFFY);
738       if (!folder[0]) {
739         mutt_endwin (NULL);
740         exit (0);
741       }
742     }
743
744     if (!folder[0])
745       m_strcpy(folder, sizeof(folder), NONULL(Spoolfile));
746
747 #ifdef USE_NNTP
748     if (option (OPTNEWS)) {
749       unset_option (OPTNEWS);
750       nntp_expand_path (folder, sizeof (folder),
751                         &CurrentNewsSrv->conn->account);
752     } else
753 #endif
754       mutt_expand_path (folder, sizeof (folder));
755
756     m_strreplace(&CurrentFolder, folder);
757     m_strreplace(&LastFolder, folder);
758
759     if (flags & M_IGNORE) {
760       /* check to see if there are any messages in the folder */
761       switch (mx_check_empty (folder)) {
762       case -1:
763         mutt_endwin (strerror (errno));
764         exit (1);
765       case 1:
766         mutt_endwin _("Mailbox is empty.");
767         exit (1);
768       }
769     }
770
771     mutt_folder_hook (folder);
772
773     if ((Context = mx_open_mailbox (folder, ((flags & M_RO)
774                                              || option (OPTREADONLY)) ?
775                                     M_READONLY : 0, NULL))
776         || !explicit_folder) {
777       mutt_index_menu ();
778       if (option (OPTXTERMSETTITLES))
779         printf("\033]2;%s\007", NONULL(XtermLeave));
780       if (Context)
781         p_delete(&Context);
782     }
783     mutt_endwin (Errorbuf);
784   }
785
786   luaM_shutdown();
787   mutt_sasl_shutdown();
788   exit (0);
789 }