]> git.llucax.com Git - software/mutt-debian.git/blob - main.c
Imported Upstream version 1.5.18
[software/mutt-debian.git] / main.c
1 /*
2  * Copyright (C) 1996-2007 Michael R. Elkins <me@mutt.org>
3  * Copyright (C) 1999-2007 Thomas Roessler <roessler@does-not-exist.org>
4  * Copyright (C) 2004 g10 Code GmbH
5  * 
6  *     This program is free software; you can redistribute it and/or modify
7  *     it under the terms of the GNU General Public License as published by
8  *     the Free Software Foundation; either version 2 of the License, or
9  *     (at your option) any later version.
10  * 
11  *     This program is distributed in the hope that it will be useful,
12  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *     GNU General Public License for more details.
15  * 
16  *     You should have received a copy of the GNU General Public License
17  *     along with this program; if not, write to the Free Software
18  *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */ 
20
21 #define MAIN_C 1
22
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include "mutt.h"
28 #include "mutt_curses.h"
29 #include "keymap.h"
30 #include "mailbox.h"
31 #include "url.h"
32 #include "mutt_crypt.h"
33 #include "mutt_idna.h"
34
35 #ifdef USE_SASL
36 #include "mutt_sasl.h"
37 #endif
38
39 #ifdef USE_IMAP
40 #include "imap/imap.h"
41 #endif
42
43 #ifdef USE_HCACHE
44 #include "hcache.h"
45 #endif
46
47 #include <string.h>
48 #include <stdlib.h>
49 #include <locale.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <sys/stat.h>
53 #include <sys/utsname.h>
54
55 #ifdef HAVE_GETOPT_H
56 #include <getopt.h>
57 #endif
58
59 #ifdef HAVE_LIBIDN
60 #include <stringprep.h>
61 #endif
62
63 static const char *ReachingUs = N_("\
64 To contact the developers, please mail to <mutt-dev@mutt.org>.\n\
65 To report a bug, please visit http://bugs.mutt.org/.\n");
66
67 static const char *Notice = N_("\
68 Copyright (C) 1996-2008 Michael R. Elkins and others.\n\
69 Mutt comes with ABSOLUTELY NO WARRANTY; for details type `mutt -vv'.\n\
70 Mutt is free software, and you are welcome to redistribute it\n\
71 under certain conditions; type `mutt -vv' for details.\n");
72
73 static const char *Copyright = N_("\
74 Copyright (C) 1996-2007 Michael R. Elkins <me@mutt.org>\n\
75 Copyright (C) 1996-2002 Brandon Long <blong@fiction.net>\n\
76 Copyright (C) 1997-2007 Thomas Roessler <roessler@does-not-exist.org>\n\
77 Copyright (C) 1998-2005 Werner Koch <wk@isil.d.shuttle.de>\n\
78 Copyright (C) 1999-2008 Brendan Cully <brendan@kublai.com>\n\
79 Copyright (C) 1999-2002 Tommi Komulainen <Tommi.Komulainen@iki.fi>\n\
80 Copyright (C) 2000-2002 Edmund Grimley Evans <edmundo@rano.org>\n\
81 \n\
82 Many others not mentioned here contributed code, fixes,\n\
83 and suggestions.\n");
84
85 static const char *Licence = N_("\
86     This program is free software; you can redistribute it and/or modify\n\
87     it under the terms of the GNU General Public License as published by\n\
88     the Free Software Foundation; either version 2 of the License, or\n\
89     (at your option) any later version.\n\
90 \n\
91     This program is distributed in the hope that it will be useful,\n\
92     but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
93     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
94     GNU General Public License for more details.\n");
95 static const char *Obtaining = N_("\
96     You should have received a copy of the GNU General Public License\n\
97     along with this program; if not, write to the Free Software\n\
98     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\
99 ");
100
101 void mutt_exit (int code)
102 {
103   mutt_endwin (NULL);
104   exit (code);
105 }
106
107 static void mutt_usage (void)
108 {
109   puts (mutt_make_version ());
110
111   puts _(
112 "usage: mutt [<options>] [-z] [-f <file> | -yZ]\n\
113        mutt [<options>] [-x] [-Hi <file>] [-s <subj>] [-bc <addr>] [-a <file> [...]] [--] <addr> [...]\n\
114        mutt [<options>] -p\n\
115        mutt [<options>] -A <alias> [...]\n\
116        mutt [<options>] -Q <query> [...]\n\
117        mutt [<options>] -D\n\
118        mutt -v[v]\n");
119
120   puts _("\
121 options:\n\
122   -A <alias>\texpand the given alias\n\
123   -a <file>\tattach a file to the message\n\
124   -b <address>\tspecify a blind carbon-copy (BCC) address\n\
125   -c <address>\tspecify a carbon-copy (CC) address\n\
126   -D\t\tprint the value of all variables to stdout");
127 #if DEBUG
128   puts _("  -d <level>\tlog debugging output to ~/.muttdebug0");
129 #endif
130   puts _(
131 "  -e <command>\tspecify a command to be executed after initialization\n\
132   -f <file>\tspecify which mailbox to read\n\
133   -F <file>\tspecify an alternate muttrc file\n\
134   -H <file>\tspecify a draft file to read header and body from\n\
135   -i <file>\tspecify a file which Mutt should include in the body\n\
136   -m <type>\tspecify a default mailbox type\n\
137   -n\t\tcauses Mutt not to read the system Muttrc\n\
138   -p\t\trecall a postponed message");
139   
140   puts _("\
141   -Q <variable>\tquery a configuration variable\n\
142   -R\t\topen mailbox in read-only mode\n\
143   -s <subj>\tspecify a subject (must be in quotes if it has spaces)\n\
144   -v\t\tshow version and compile-time definitions\n\
145   -x\t\tsimulate the mailx send mode\n\
146   -y\t\tselect a mailbox specified in your `mailboxes' list\n\
147   -z\t\texit immediately if there are no messages in the mailbox\n\
148   -Z\t\topen the first folder with new message, exit immediately if none\n\
149   -h\t\tthis help message");
150   puts _("  --\t\ttreat remaining arguments as addr even if starting with a dash\n\
151 \t\twhen using -a with multiple filenames using -- is mandatory");
152
153   exit (0);
154 }
155
156 static void show_version (void)
157 {
158   struct utsname uts;
159
160   puts (mutt_make_version());
161   puts (_(Notice));
162
163   uname (&uts);
164
165 #ifdef _AIX
166   printf ("System: %s %s.%s", uts.sysname, uts.version, uts.release);
167 #elif defined (SCO)
168   printf ("System: SCO %s", uts.release);
169 #else
170   printf ("System: %s %s", uts.sysname, uts.release);
171 #endif
172
173   printf (" (%s)", uts.machine);
174
175 #ifdef NCURSES_VERSION
176   printf ("\nncurses: %s (compiled with %s)", curses_version(), NCURSES_VERSION);
177 #elif defined(USE_SLANG_CURSES)
178   printf ("\nslang: %d", SLANG_VERSION);
179 #endif
180
181 #ifdef _LIBICONV_VERSION
182   printf ("\nlibiconv: %d.%d", _LIBICONV_VERSION >> 8,
183           _LIBICONV_VERSION & 0xff);
184 #endif
185
186 #ifdef HAVE_LIBIDN
187   printf ("\nlibidn: %s (compiled with %s)", stringprep_check_version (NULL), 
188           STRINGPREP_VERSION);
189 #endif
190
191 #ifdef USE_HCACHE
192   printf ("\nhcache backend: %s", mutt_hcache_backend ());
193 #endif
194
195   puts (_("\nCompile options:"));
196
197 #ifdef DOMAIN
198   printf ("DOMAIN=\"%s\"\n", DOMAIN);
199 #else
200   puts ("-DOMAIN");
201 #endif
202
203 #ifdef DEBUG
204   puts ("+DEBUG");
205 #else
206   puts ("-DEBUG");
207 #endif
208   
209
210   
211   puts (
212
213 #ifdef HOMESPOOL
214         "+HOMESPOOL  "
215 #else
216         "-HOMESPOOL  "
217 #endif
218
219 #ifdef USE_SETGID
220         "+USE_SETGID  "
221 #else
222         "-USE_SETGID  "
223 #endif
224
225 #ifdef USE_DOTLOCK
226         "+USE_DOTLOCK  "
227 #else
228         "-USE_DOTLOCK  "
229 #endif
230
231 #ifdef DL_STANDALONE
232         "+DL_STANDALONE  "
233 #else
234         "-DL_STANDALONE  "
235 #endif
236
237         "\n"
238         
239 #ifdef USE_FCNTL
240         "+USE_FCNTL  "
241 #else
242         "-USE_FCNTL  "
243 #endif
244
245 #ifdef USE_FLOCK
246         "+USE_FLOCK   "
247 #else
248         "-USE_FLOCK   "
249 #endif
250         );
251   puts (
252 #ifdef USE_POP
253         "+USE_POP  "
254 #else
255         "-USE_POP  "
256 #endif
257
258 #ifdef USE_IMAP
259         "+USE_IMAP  "
260 #else
261         "-USE_IMAP  "
262 #endif
263
264 #ifdef USE_SMTP
265         "+USE_SMTP  "
266 #else
267         "-USE_SMTP  "
268 #endif
269
270 #ifdef USE_GSS
271         "+USE_GSS  "
272 #else
273         "-USE_GSS  "
274 #endif
275
276         
277 #ifdef USE_SSL_OPENSSL
278         "+USE_SSL_OPENSSL  "
279 #else
280         "-USE_SSL_OPENSSL  "
281 #endif
282
283 #ifdef USE_SSL_GNUTLS
284         "+USE_SSL_GNUTLS  "
285 #else
286         "-USE_SSL_GNUTLS  "
287 #endif
288
289 #ifdef USE_SASL
290         "+USE_SASL  "
291 #else
292         "-USE_SASL  "
293 #endif
294
295 #if HAVE_GETADDRINFO
296         "+HAVE_GETADDRINFO  "
297 #else
298         "-HAVE_GETADDRINFO  "
299 #endif
300         );
301         
302   puts (
303 #ifdef HAVE_REGCOMP
304         "+HAVE_REGCOMP  "
305 #else
306         "-HAVE_REGCOMP  "
307 #endif
308
309 #ifdef USE_GNU_REGEX
310         "+USE_GNU_REGEX  "
311 #else
312         "-USE_GNU_REGEX  "
313 #endif
314
315         "\n"
316         
317 #ifdef HAVE_COLOR
318         "+HAVE_COLOR  "
319 #else
320         "-HAVE_COLOR  "
321 #endif
322         
323 #ifdef HAVE_START_COLOR
324         "+HAVE_START_COLOR  "
325 #else
326         "-HAVE_START_COLOR  "
327 #endif
328         
329 #ifdef HAVE_TYPEAHEAD
330         "+HAVE_TYPEAHEAD  "
331 #else
332         "-HAVE_TYPEAHEAD  "
333 #endif
334         
335 #ifdef HAVE_BKGDSET
336         "+HAVE_BKGDSET  "
337 #else
338         "-HAVE_BKGDSET  "
339 #endif
340
341         "\n"
342         
343 #ifdef HAVE_CURS_SET
344         "+HAVE_CURS_SET  "
345 #else
346         "-HAVE_CURS_SET  "
347 #endif
348         
349 #ifdef HAVE_META
350         "+HAVE_META  "
351 #else
352         "-HAVE_META  "
353 #endif
354         
355 #ifdef HAVE_RESIZETERM
356         "+HAVE_RESIZETERM  "
357 #else
358         "-HAVE_RESIZETERM  "
359 #endif
360         );      
361   
362   puts (
363 #ifdef CRYPT_BACKEND_CLASSIC_PGP
364         "+CRYPT_BACKEND_CLASSIC_PGP  "
365 #else
366         "-CRYPT_BACKEND_CLASSIC_PGP  "
367 #endif
368 #ifdef CRYPT_BACKEND_CLASSIC_SMIME
369         "+CRYPT_BACKEND_CLASSIC_SMIME  "
370 #else
371         "-CRYPT_BACKEND_CLASSIC_SMIME  "
372 #endif
373 #ifdef CRYPT_BACKEND_GPGME
374         "+CRYPT_BACKEND_GPGME  "
375 #else
376         "-CRYPT_BACKEND_GPGME  "
377 #endif
378         );
379   
380   puts (
381 #ifdef EXACT_ADDRESS
382         "+EXACT_ADDRESS  "
383 #else
384         "-EXACT_ADDRESS  "
385 #endif
386
387 #ifdef SUN_ATTACHMENT
388         "+SUN_ATTACHMENT  "
389 #else
390         "-SUN_ATTACHMENT  "
391 #endif
392
393         "\n"
394         
395 #ifdef ENABLE_NLS
396         "+ENABLE_NLS  "
397 #else
398         "-ENABLE_NLS  "
399 #endif
400
401 #ifdef LOCALES_HACK
402         "+LOCALES_HACK  "
403 #else
404         "-LOCALES_HACK  "
405 #endif
406               
407 #ifdef HAVE_WC_FUNCS
408         "+HAVE_WC_FUNCS  "
409 #else
410         "-HAVE_WC_FUNCS  "
411 #endif
412         
413 #ifdef HAVE_LANGINFO_CODESET
414         "+HAVE_LANGINFO_CODESET  "
415 #else
416         "-HAVE_LANGINFO_CODESET  "
417 #endif
418
419         
420 #ifdef HAVE_LANGINFO_YESEXPR
421         "+HAVE_LANGINFO_YESEXPR  "
422 #else
423         "-HAVE_LANGINFO_YESEXPR  "
424 #endif
425         
426         "\n"
427
428 #if HAVE_ICONV
429         "+HAVE_ICONV  "
430 #else
431         "-HAVE_ICONV  "
432 #endif
433
434 #if ICONV_NONTRANS
435         "+ICONV_NONTRANS  "
436 #else
437         "-ICONV_NONTRANS  "
438 #endif
439
440 #if HAVE_LIBIDN
441         "+HAVE_LIBIDN  "
442 #else
443         "-HAVE_LIBIDN  "
444 #endif
445         
446 #if HAVE_GETSID
447         "+HAVE_GETSID  "
448 #else
449         "-HAVE_GETSID  "
450 #endif
451
452 #if USE_HCACHE
453         "+USE_HCACHE  "
454 #else
455         "-USE_HCACHE  "
456 #endif
457
458         );
459
460 #ifdef ISPELL
461   printf ("ISPELL=\"%s\"\n", ISPELL);
462 #else
463   puts ("-ISPELL");
464 #endif
465
466   printf ("SENDMAIL=\"%s\"\n", SENDMAIL);
467   printf ("MAILPATH=\"%s\"\n", MAILPATH);
468   printf ("PKGDATADIR=\"%s\"\n", PKGDATADIR);
469   printf ("SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
470   printf ("EXECSHELL=\"%s\"\n", EXECSHELL);
471 #ifdef MIXMASTER
472   printf ("MIXMASTER=\"%s\"\n", MIXMASTER);
473 #else
474   puts ("-MIXMASTER");
475 #endif
476
477   puts(_(ReachingUs));
478
479   mutt_print_patchlist();
480   
481   exit (0);
482 }
483
484 static void start_curses (void)
485 {
486   km_init (); /* must come before mutt_init */
487
488 #ifdef USE_SLANG_CURSES
489   SLtt_Ignore_Beep = 1; /* don't do that #*$@^! annoying visual beep! */
490   SLsmg_Display_Eight_Bit = 128; /* characters above this are printable */
491   SLtt_set_color(0, NULL, "default", "default");
492 #if SLANG_VERSION >= 20000
493   SLutf8_enable(-1);
494 #endif
495 #else
496   /* should come before initscr() so that ncurses 4.2 doesn't try to install
497      its own SIGWINCH handler */
498   mutt_signal_init ();
499 #endif
500   if (initscr () == NULL)
501   {
502     puts _("Error initializing terminal.");
503     exit (1);
504   }
505 #if 1 /* USE_SLANG_CURSES  - commenting out suggested in #455. */
506   /* slang requires the signal handlers to be set after initializing */
507   mutt_signal_init ();
508 #endif
509   ci_start_color ();
510   keypad (stdscr, TRUE);
511   cbreak ();
512   noecho ();
513 #if HAVE_TYPEAHEAD
514   typeahead (-1);       /* simulate smooth scrolling */
515 #endif
516 #if HAVE_META
517   meta (stdscr, TRUE);
518 #endif
519 }
520
521 #define M_IGNORE  (1<<0)        /* -z */
522 #define M_BUFFY   (1<<1)        /* -Z */
523 #define M_NOSYSRC (1<<2)        /* -n */
524 #define M_RO      (1<<3)        /* -R */
525 #define M_SELECT  (1<<4)        /* -y */
526
527 int main (int argc, char **argv)
528 {
529   char folder[_POSIX_PATH_MAX] = "";
530   char *subject = NULL;
531   char *includeFile = NULL;
532   char *draftFile = NULL;
533   char *newMagic = NULL;
534   HEADER *msg = NULL;
535   LIST *attach = NULL;
536   LIST *commands = NULL;
537   LIST *queries = NULL;
538   LIST *alias_queries = NULL;
539   int sendflags = 0;
540   int flags = 0;
541   int version = 0;
542   int i;
543   int explicit_folder = 0;
544   int dump_variables = 0;
545   extern char *optarg;
546   extern int optind;
547   int attach_sep = 0;
548
549   /* sanity check against stupid administrators */
550   
551   if(getegid() != getgid())
552   {
553     fprintf(stderr, "%s: I don't want to run with privileges!\n",
554             argv[0]);
555     exit(1);
556   }
557
558 #ifdef ENABLE_NLS
559   /* FIXME what about init.c:1439 ? */
560   setlocale (LC_ALL, "");
561   bindtextdomain (PACKAGE, MUTTLOCALEDIR);
562   textdomain (PACKAGE);
563 #endif
564
565   setlocale (LC_CTYPE, "");
566
567   mutt_error = mutt_nocurses_error;
568   mutt_message = mutt_nocurses_error;
569   SRAND (time (NULL));
570   umask (077);
571
572   memset (Options, 0, sizeof (Options));
573   memset (QuadOptions, 0, sizeof (QuadOptions));
574
575   for (i = 1; i < argc; i++)
576     if (!strcmp(argv[i], "--"))
577     {
578       attach_sep = i;
579       break;
580     }
581
582   while ((i = getopt (argc, argv, "A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) != EOF)
583     switch (i)
584     {
585       case 'A':
586         alias_queries = mutt_add_list (alias_queries, optarg);
587         break;
588       case 'a':
589         attach = mutt_add_list (attach, optarg);
590         break;
591
592       case 'F':
593         mutt_str_replace (&Muttrc, optarg);
594         break;
595
596       case 'f':
597         strfcpy (folder, optarg, sizeof (folder));
598         explicit_folder = 1;
599         break;
600
601       case 'b':
602       case 'c':
603         if (!msg)
604           msg = mutt_new_header ();
605         if (!msg->env)
606           msg->env = mutt_new_envelope ();
607         if (i == 'b')
608           msg->env->bcc = rfc822_parse_adrlist (msg->env->bcc, optarg);
609         else
610           msg->env->cc = rfc822_parse_adrlist (msg->env->cc, optarg);
611         break;
612
613       case 'D':
614         dump_variables = 1;
615         break;
616
617       case 'd':
618 #ifdef DEBUG
619         debuglevel = atoi (optarg);
620         printf (_("Debugging at level %d.\n"), debuglevel);
621 #else
622         printf _("DEBUG was not defined during compilation.  Ignored.\n");
623 #endif
624         break;
625
626       case 'e':
627         commands = mutt_add_list (commands, optarg);
628         break;
629
630       case 'H':
631         draftFile = optarg;
632         break;
633
634       case 'i':
635         includeFile = optarg;
636         break;
637
638       case 'm':
639         /* should take precedence over .muttrc setting, so save it for later */
640         newMagic = optarg; 
641         break;
642
643       case 'n':
644         flags |= M_NOSYSRC;
645         break;
646
647       case 'p':
648         sendflags |= SENDPOSTPONED;
649         break;
650
651       case 'Q':
652         queries = mutt_add_list (queries, optarg);
653         break;
654       
655       case 'R':
656         flags |= M_RO; /* read-only mode */
657         break;
658
659       case 's':
660         subject = optarg;
661         break;
662
663       case 'v':
664         version++;
665         break;
666
667       case 'x': /* mailx compatible send mode */
668         sendflags |= SENDMAILX;
669         break;
670
671       case 'y': /* My special hack mode */
672         flags |= M_SELECT;
673         break;
674
675       case 'z':
676         flags |= M_IGNORE;
677         break;
678
679       case 'Z':
680         flags |= M_BUFFY | M_IGNORE;
681         break;
682
683       default:
684         mutt_usage ();
685     }
686
687   switch (version)
688   {
689     case 0:
690       break;
691     case 1:
692       show_version ();
693       break;
694     default:
695       puts (mutt_make_version ());
696       puts (_(Copyright));
697       puts (_(Licence));
698       puts (_(Obtaining));
699       puts (_(ReachingUs));
700       exit (0);
701   }
702
703   /* Check for a batch send. */
704   if (!isatty (0) || queries || alias_queries || dump_variables)
705   {
706     set_option (OPTNOCURSES);
707     sendflags = SENDBATCH;
708   }
709
710   /* This must come before mutt_init() because curses needs to be started
711      before calling the init_pair() function to set the color scheme.  */
712   if (!option (OPTNOCURSES))
713     start_curses ();
714
715   /* set defaults and read init files */
716   mutt_init (flags & M_NOSYSRC, commands);
717   mutt_free_list (&commands);
718
719   /* Initialize crypto backends.  */
720   crypt_init ();
721
722   if (queries)
723   {
724     for (; optind < argc; optind++)
725       queries = mutt_add_list (queries, argv[optind]);
726     return mutt_query_variables (queries);
727   }
728   if (dump_variables)
729     return mutt_dump_variables();
730
731   if (alias_queries)
732   {
733     int rv = 0;
734     ADDRESS *a;
735     for (; optind < argc; optind++)
736       alias_queries = mutt_add_list (alias_queries, argv[optind]);
737     for (; alias_queries; alias_queries = alias_queries->next)
738     {
739       if ((a = mutt_lookup_alias (alias_queries->data)))
740       { 
741         /* output in machine-readable form */
742         mutt_addrlist_to_idna (a, NULL);
743         mutt_write_address_list (a, stdout, 0, 0);
744       }
745       else
746       {
747         rv = 1;
748         printf ("%s\n", alias_queries->data);
749       }
750     }
751     return rv;
752   }
753
754   /* if an -a option is present, all non-option arguments before -- are considered attachments */
755   if (attach)
756     for (; optind <= attach_sep; optind++)
757       attach = mutt_add_list (attach, argv[optind]);
758
759   if (newMagic)
760     mx_set_magic (newMagic);
761
762   if (!option (OPTNOCURSES))
763   {
764     SETCOLOR (MT_COLOR_NORMAL);
765     clear ();
766     mutt_error = mutt_curses_error;
767     mutt_message = mutt_curses_message;
768   }
769
770   /* Create the Maildir directory if it doesn't exist. */
771   if (!option (OPTNOCURSES) && Maildir)
772   {
773     struct stat sb;
774     char fpath[_POSIX_PATH_MAX];
775     char msg[STRING];
776
777     strfcpy (fpath, Maildir, sizeof (fpath));
778     mutt_expand_path (fpath, sizeof (fpath));
779 #ifdef USE_IMAP
780     /* we're not connected yet - skip mail folder creation */
781     if (!mx_is_imap (fpath))
782 #endif
783     if (stat (fpath, &sb) == -1 && errno == ENOENT)
784     {
785       snprintf (msg, sizeof (msg), _("%s does not exist. Create it?"), Maildir);
786       if (mutt_yesorno (msg, M_YES) == M_YES)
787       {
788         if (mkdir (fpath, 0700) == -1 && errno != EEXIST)
789           mutt_error ( _("Can't create %s: %s."), Maildir, strerror (errno));
790       }
791     }
792   }
793
794   if (sendflags & SENDPOSTPONED)
795   {
796     if (!option (OPTNOCURSES))
797       mutt_flushinp ();
798     ci_send_message (SENDPOSTPONED, NULL, NULL, NULL, NULL);
799     mutt_endwin (NULL);
800   }
801   else if (subject || msg || sendflags || draftFile || includeFile || attach ||
802            optind < argc)
803   {
804     FILE *fin = NULL;
805     char buf[LONG_STRING];
806     char *tempfile = NULL, *infile = NULL;
807     char *bodytext = NULL;
808     int rv = 0;
809     
810     if (!option (OPTNOCURSES))
811       mutt_flushinp ();
812
813     if (!msg)
814       msg = mutt_new_header ();
815
816     if (draftFile)
817       infile = draftFile;
818     else
819     {
820       if (!msg->env)
821         msg->env = mutt_new_envelope ();
822
823       for (i = optind; i < argc; i++)
824       {
825         if (url_check_scheme (argv[i]) == U_MAILTO)
826         {
827           if (url_parse_mailto (msg->env, &bodytext, argv[i]) < 0)
828           {
829             if (!option (OPTNOCURSES))
830               mutt_endwin (NULL);
831             fputs (_("Failed to parse mailto: link\n"), stderr);
832             exit (1);
833           }
834         }
835         else
836           msg->env->to = rfc822_parse_adrlist (msg->env->to, argv[i]);
837       }
838
839       if (option (OPTAUTOEDIT) && !msg->env->to && !msg->env->cc)
840       {
841         if (!option (OPTNOCURSES))
842           mutt_endwin (NULL);
843         fputs (_("No recipients specified.\n"), stderr);
844         exit (1);
845       }
846
847       if (subject)
848         msg->env->subject = safe_strdup (subject);
849
850       if (includeFile)
851         infile = includeFile;
852     }
853
854     if (infile || bodytext)
855     {
856       if (infile)
857       {
858         if (mutt_strcmp ("-", infile) == 0)
859           fin = stdin;
860         else 
861         {
862           char path[_POSIX_PATH_MAX];
863           
864           strfcpy (path, infile, sizeof (path));
865           mutt_expand_path (path, sizeof (path));
866           if ((fin = fopen (path, "r")) == NULL)
867           {
868             if (!option (OPTNOCURSES))
869               mutt_endwin (NULL);
870             perror (path);
871             exit (1);
872           }
873         }
874       }
875       else
876         fin = NULL;
877
878       mutt_mktemp (buf);
879       tempfile = safe_strdup (buf);
880
881       if (draftFile)
882         msg->env = mutt_read_rfc822_header (fin, NULL, 1, 0);
883
884       /* is the following if still needed? */
885       
886       if (tempfile)
887       {
888         FILE *fout;
889
890         if ((fout = safe_fopen (tempfile, "w")) == NULL)
891         {
892           if (!option (OPTNOCURSES))
893             mutt_endwin (NULL);
894           perror (tempfile);
895           fclose (fin);
896           FREE (&tempfile);
897           exit (1);
898         }
899         if (fin)
900           mutt_copy_stream (fin, fout);
901         else if (bodytext)
902           fputs (bodytext, fout);
903         fclose (fout);
904         if (fin && fin != stdin)
905           fclose (fin);
906       }
907     }
908
909     FREE (&bodytext);
910     
911     if (attach)
912     {
913       LIST *t = attach;
914       BODY *a = NULL;
915
916       while (t)
917       {
918         if (a)
919         {
920           a->next = mutt_make_file_attach (t->data);
921           a = a->next;
922         }
923         else
924           msg->content = a = mutt_make_file_attach (t->data);
925         if (!a)
926         {
927           if (!option (OPTNOCURSES))
928             mutt_endwin (NULL);
929           fprintf (stderr, _("%s: unable to attach file.\n"), t->data);
930           mutt_free_list (&attach);
931           exit (1);
932         }
933         t = t->next;
934       }
935       mutt_free_list (&attach);
936     }
937
938     rv = ci_send_message (sendflags, msg, tempfile, NULL, NULL);
939
940     if (!option (OPTNOCURSES))
941       mutt_endwin (NULL);
942
943     if (rv)
944       exit(1);
945   }
946   else
947   {
948     if (flags & M_BUFFY)
949     {
950       if (!mutt_buffy_check (0))
951       {
952         mutt_endwin _("No mailbox with new mail.");
953         exit (1);
954       }
955       folder[0] = 0;
956       mutt_buffy (folder, sizeof (folder));
957     }
958     else if (flags & M_SELECT)
959     {
960       if (!Incoming) {
961         mutt_endwin _("No incoming mailboxes defined.");
962         exit (1);
963       }
964       folder[0] = 0;
965       mutt_select_file (folder, sizeof (folder), M_SEL_FOLDER | M_SEL_BUFFY);
966       if (!folder[0])
967       {
968         mutt_endwin (NULL);
969         exit (0);
970       }
971     }
972
973     if (!folder[0])
974       strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
975     mutt_expand_path (folder, sizeof (folder));
976
977     mutt_str_replace (&CurrentFolder, folder);
978     mutt_str_replace (&LastFolder, folder);
979
980     if (flags & M_IGNORE)
981     {
982       /* check to see if there are any messages in the folder */
983       switch (mx_check_empty (folder))
984       {
985         case -1:
986           mutt_endwin (strerror (errno));
987           exit (1);
988         case 1:
989           mutt_endwin _("Mailbox is empty.");
990           exit (1);
991       }
992     }
993
994     mutt_folder_hook (folder);
995
996     if((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL))
997        || !explicit_folder)
998     {
999       mutt_index_menu ();
1000       if (Context)
1001         FREE (&Context);
1002     }
1003 #ifdef USE_IMAP
1004     imap_logout_all ();
1005 #endif
1006 #ifdef USE_SASL
1007     mutt_sasl_done ();
1008 #endif
1009     mutt_free_opts ();
1010     mutt_endwin (Errorbuf);
1011   }
1012
1013   exit (0);
1014 }