Home | History | Annotate | Line # | Download | only in mail
main.c revision 1.27.4.1
      1  1.27.4.1      matt /*	$NetBSD: main.c,v 1.27.4.1 2007/11/06 23:35:54 matt Exp $	*/
      2       1.5  christos 
      3       1.1       cgd /*
      4       1.3   deraadt  * Copyright (c) 1980, 1993
      5       1.3   deraadt  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15      1.18       agc  * 3. Neither the name of the University nor the names of its contributors
     16       1.1       cgd  *    may be used to endorse or promote products derived from this software
     17       1.1       cgd  *    without specific prior written permission.
     18       1.1       cgd  *
     19       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1       cgd  * SUCH DAMAGE.
     30       1.1       cgd  */
     31       1.1       cgd 
     32       1.8     lukem #include <sys/cdefs.h>
     33       1.1       cgd #ifndef lint
     34       1.8     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
     35       1.8     lukem 	The Regents of the University of California.  All rights reserved.\n");
     36       1.1       cgd #endif /* not lint */
     37       1.1       cgd 
     38       1.1       cgd #ifndef lint
     39       1.5  christos #if 0
     40       1.6       tls static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 4/20/95";
     41       1.5  christos #else
     42  1.27.4.1      matt __RCSID("$NetBSD: main.c,v 1.27.4.1 2007/11/06 23:35:54 matt Exp $");
     43       1.5  christos #endif
     44       1.1       cgd #endif /* not lint */
     45       1.1       cgd 
     46       1.9  wsanchez #define EXTERN
     47       1.1       cgd #include "rcv.h"
     48       1.9  wsanchez #undef EXTERN
     49      1.24  christos #include <assert.h>
     50      1.23  christos #include <util.h>
     51       1.9  wsanchez 
     52       1.3   deraadt #include "extern.h"
     53       1.1       cgd 
     54      1.23  christos #ifdef USE_EDITLINE
     55      1.22  christos #include "complete.h"
     56      1.22  christos #endif
     57      1.24  christos #include "format.h"
     58      1.23  christos #ifdef MIME_SUPPORT
     59      1.23  christos #include "mime.h"
     60      1.23  christos #endif
     61      1.25  christos #ifdef THREAD_SUPPORT
     62      1.25  christos #include "thread.h"
     63      1.25  christos #endif
     64       1.8     lukem 
     65       1.1       cgd /*
     66       1.1       cgd  * Mail -- a mail program
     67       1.1       cgd  *
     68       1.1       cgd  * Startup -- interface with user.
     69       1.1       cgd  */
     70       1.1       cgd 
     71      1.25  christos static jmp_buf	hdrjmp;
     72      1.25  christos 
     73      1.25  christos /*
     74      1.25  christos  * Interrupt printing of the headers.
     75      1.25  christos  */
     76      1.25  christos /*ARGSUSED*/
     77      1.25  christos static void
     78      1.25  christos hdrstop(int signo __unused)
     79      1.25  christos {
     80       1.1       cgd 
     81      1.25  christos 	(void)fflush(stdout);
     82      1.25  christos 	(void)fprintf(stderr, "\nInterrupt\n");
     83      1.25  christos 	longjmp(hdrjmp, 1);
     84      1.25  christos }
     85      1.25  christos 
     86      1.25  christos /*
     87      1.25  christos  * Compute what the screen size for printing headers should be.
     88      1.25  christos  * We use the following algorithm for the height:
     89      1.25  christos  *	If baud rate < 1200, use  9
     90      1.25  christos  *	If baud rate = 1200, use 14
     91      1.25  christos  *	If baud rate > 1200, use 24 or ws_row
     92      1.25  christos  * Width is either 80 or ws_col;
     93      1.25  christos  */
     94      1.25  christos PUBLIC void
     95      1.25  christos setscreensize(void)
     96      1.25  christos {
     97      1.25  christos 	struct termios tbuf;
     98      1.25  christos 	struct winsize ws;
     99      1.25  christos 	speed_t ospeed;
    100      1.25  christos 	char *cp;
    101      1.25  christos 
    102      1.25  christos 	if (ioctl(1, TIOCGWINSZ, &ws) < 0)
    103      1.25  christos 		ws.ws_col = ws.ws_row = 0;
    104      1.25  christos 	if (tcgetattr(1, &tbuf) < 0)
    105      1.25  christos 		ospeed = 9600;
    106      1.25  christos 	else
    107      1.25  christos 		ospeed = cfgetospeed(&tbuf);
    108      1.25  christos 	if (ospeed < 1200)
    109      1.25  christos 		screenheight = 9;
    110      1.25  christos 	else if (ospeed == 1200)
    111      1.25  christos 		screenheight = 14;
    112      1.25  christos 	else if (ws.ws_row != 0)
    113      1.25  christos 		screenheight = ws.ws_row;
    114      1.25  christos 	else
    115      1.25  christos 		screenheight = 24;
    116      1.25  christos 	if ((realscreenheight = ws.ws_row) == 0)
    117      1.25  christos 		realscreenheight = 24;
    118      1.25  christos 	if ((screenwidth = ws.ws_col) == 0)
    119      1.25  christos 		screenwidth = 80;
    120      1.25  christos 	/*
    121      1.25  christos 	 * Possible overrides from the rcfile.
    122      1.25  christos 	 */
    123      1.25  christos 	if ((cp = value(ENAME_SCREENWIDTH)) != NULL) {
    124      1.25  christos 		int width;
    125      1.25  christos 		width = *cp ? atoi(cp) : 0;
    126      1.25  christos 		if (width >= 0)
    127      1.25  christos 			screenwidth = width;
    128      1.25  christos 	}
    129      1.25  christos 	if ((cp = value(ENAME_SCREENHEIGHT)) != NULL) {
    130      1.25  christos 		int height;
    131      1.25  christos 		height = *cp ? atoi(cp) : 0;
    132      1.25  christos 		if (height >= 0) {
    133      1.25  christos 			realscreenheight = height;
    134      1.25  christos 			screenheight = height;
    135      1.25  christos 		}
    136      1.25  christos 	}
    137      1.25  christos }
    138      1.22  christos 
    139      1.22  christos /*
    140      1.22  christos  * Break up a white-space or comma delimited name list so that aliases
    141      1.22  christos  * can get expanded.  Without this, the CC: or BCC: list is broken too
    142      1.22  christos  * late for alias expansion to occur.
    143      1.22  christos  */
    144      1.25  christos PUBLIC struct name *
    145      1.22  christos lexpand(char *str, int ntype)
    146      1.22  christos {
    147      1.22  christos 	char *list;
    148      1.22  christos 	struct name *np = NULL;
    149      1.22  christos 	char *word, *p;
    150      1.22  christos 
    151      1.23  christos 	list = estrdup(str);
    152      1.22  christos 	word = list;
    153      1.23  christos 	for (word = list; *word; word = p) {
    154  1.27.4.1      matt 		word = skip_WSP(word);
    155      1.22  christos 		for (p = word;
    156  1.27.4.1      matt 		     *p && !is_WSP(*p) && *p != ',';
    157      1.23  christos 		     p++)
    158      1.22  christos 			continue;
    159      1.22  christos 		if (*p)
    160      1.22  christos 			*p++ = '\0';
    161      1.22  christos 		np = cat(np, nalloc(word, ntype));
    162      1.22  christos 	}
    163      1.22  christos 
    164      1.22  christos 	free(list);
    165      1.22  christos 	return np;
    166      1.22  christos }
    167      1.22  christos 
    168      1.25  christos PUBLIC int
    169      1.13       wiz main(int argc, char *argv[])
    170       1.1       cgd {
    171       1.8     lukem 	int i;
    172       1.1       cgd 	struct name *to, *cc, *bcc, *smopts;
    173      1.23  christos #ifdef MIME_SUPPORT
    174      1.24  christos 	struct name *attach_optargs;
    175      1.24  christos 	struct name *attach_end;
    176      1.23  christos #endif
    177       1.1       cgd 	char *subject;
    178      1.19  christos 	const char *ef;
    179       1.1       cgd 	char nosrc = 0;
    180       1.1       cgd 	sig_t prevint;
    181      1.19  christos 	const char *rc;
    182      1.24  christos 	int volatile Hflag;
    183       1.1       cgd 
    184       1.1       cgd 	/*
    185      1.27  christos 	 * For portability, call setprogname() early, before
    186      1.27  christos 	 * getprogname() is called.
    187      1.27  christos 	 */
    188      1.27  christos 	(void)setprogname(argv[0]);
    189      1.27  christos 
    190      1.27  christos 	/*
    191       1.1       cgd 	 * Set up a reasonable environment.
    192       1.1       cgd 	 * Figure out whether we are being run interactively,
    193       1.1       cgd 	 * start the SIGCHLD catcher, and so forth.
    194       1.1       cgd 	 */
    195      1.16       wiz 	(void)signal(SIGCHLD, sigchild);
    196       1.1       cgd 	if (isatty(0))
    197      1.25  christos 		assign(ENAME_INTERACTIVE, "");
    198       1.1       cgd 	image = -1;
    199       1.1       cgd 	/*
    200       1.1       cgd 	 * Now, determine how we are being used.
    201       1.1       cgd 	 * We successively pick off - flags.
    202       1.1       cgd 	 * If there is anything left, it is the base of the list
    203       1.1       cgd 	 * of users to mail to.  Argp will be set to point to the
    204       1.1       cgd 	 * first of these users.
    205       1.1       cgd 	 */
    206      1.14       wiz 	ef = NULL;
    207      1.15       wiz 	to = NULL;
    208      1.15       wiz 	cc = NULL;
    209      1.15       wiz 	bcc = NULL;
    210      1.15       wiz 	smopts = NULL;
    211      1.14       wiz 	subject = NULL;
    212      1.24  christos 	Hflag = 0;
    213      1.23  christos #ifdef MIME_SUPPORT
    214      1.24  christos 	attach_optargs = NULL;
    215      1.24  christos 	attach_end = NULL;
    216      1.24  christos 	while ((i = getopt(argc, argv, ":~EH:INT:a:b:c:dfins:u:v")) != -1)
    217      1.23  christos #else
    218      1.24  christos 	while ((i = getopt(argc, argv, ":~EH:INT:b:c:dfins:u:v")) != -1)
    219      1.23  christos #endif
    220      1.22  christos 	{
    221       1.1       cgd 		switch (i) {
    222       1.1       cgd 		case 'T':
    223       1.1       cgd 			/*
    224       1.1       cgd 			 * Next argument is temp file to write which
    225       1.1       cgd 			 * articles have been read/deleted for netnews.
    226       1.1       cgd 			 */
    227       1.1       cgd 			Tflag = optarg;
    228       1.1       cgd 			if ((i = creat(Tflag, 0600)) < 0) {
    229      1.17       wiz 				warn("%s", Tflag);
    230       1.1       cgd 				exit(1);
    231       1.1       cgd 			}
    232      1.20  christos 			(void)close(i);
    233       1.1       cgd 			break;
    234      1.23  christos #ifdef MIME_SUPPORT
    235      1.24  christos 		case 'a': {
    236      1.24  christos 			struct name *np;
    237      1.24  christos 			np = nalloc(optarg, 0);
    238      1.24  christos 			if (attach_end == NULL)
    239      1.24  christos 				attach_optargs = np;
    240      1.24  christos 			else {
    241      1.24  christos 				np->n_blink = attach_end;
    242      1.24  christos 				attach_end->n_flink = np;
    243      1.24  christos 			}
    244      1.24  christos 			attach_end = np;
    245      1.23  christos 			break;
    246      1.24  christos 		}
    247      1.23  christos #endif
    248       1.1       cgd 		case 'u':
    249       1.1       cgd 			/*
    250       1.1       cgd 			 * Next argument is person to pretend to be.
    251       1.1       cgd 			 */
    252       1.1       cgd 			myname = optarg;
    253      1.20  christos 			(void)unsetenv("MAIL");
    254       1.1       cgd 			break;
    255       1.1       cgd 		case 'i':
    256       1.1       cgd 			/*
    257       1.1       cgd 			 * User wants to ignore interrupts.
    258       1.1       cgd 			 * Set the variable "ignore"
    259       1.1       cgd 			 */
    260      1.25  christos 			assign(ENAME_IGNORE, "");
    261       1.1       cgd 			break;
    262       1.1       cgd 		case 'd':
    263       1.1       cgd 			debug++;
    264       1.1       cgd 			break;
    265       1.1       cgd 		case 's':
    266       1.1       cgd 			/*
    267       1.1       cgd 			 * Give a subject field for sending from
    268       1.1       cgd 			 * non terminal
    269       1.1       cgd 			 */
    270       1.1       cgd 			subject = optarg;
    271       1.1       cgd 			break;
    272       1.1       cgd 		case 'f':
    273       1.1       cgd 			/*
    274       1.1       cgd 			 * User is specifying file to "edit" with Mail,
    275       1.1       cgd 			 * as opposed to reading system mailbox.
    276       1.1       cgd 			 * If no argument is given after -f, we read his
    277       1.1       cgd 			 * mbox file.
    278       1.1       cgd 			 *
    279       1.1       cgd 			 * getopt() can't handle optional arguments, so here
    280       1.1       cgd 			 * is an ugly hack to get around it.
    281       1.1       cgd 			 */
    282       1.1       cgd 			if ((argv[optind]) && (argv[optind][0] != '-'))
    283       1.1       cgd 				ef = argv[optind++];
    284       1.1       cgd 			else
    285       1.1       cgd 				ef = "&";
    286       1.1       cgd 			break;
    287      1.24  christos 		case 'H':
    288      1.24  christos 			/*
    289      1.24  christos 			 * Print out the headers and quit.
    290      1.24  christos 			 */
    291      1.24  christos 			Hflag = get_Hflag(argv);
    292      1.24  christos 			break;
    293       1.1       cgd 		case 'n':
    294       1.1       cgd 			/*
    295       1.1       cgd 			 * User doesn't want to source /usr/lib/Mail.rc
    296       1.1       cgd 			 */
    297       1.1       cgd 			nosrc++;
    298       1.1       cgd 			break;
    299       1.1       cgd 		case 'N':
    300       1.1       cgd 			/*
    301       1.1       cgd 			 * Avoid initial header printing.
    302       1.1       cgd 			 */
    303      1.25  christos 			assign(ENAME_NOHEADER, "");
    304       1.1       cgd 			break;
    305       1.1       cgd 		case 'v':
    306       1.1       cgd 			/*
    307       1.1       cgd 			 * Send mailer verbose flag
    308       1.1       cgd 			 */
    309      1.25  christos 			assign(ENAME_VERBOSE, "");
    310       1.1       cgd 			break;
    311       1.1       cgd 		case 'I':
    312      1.11  christos 		case '~':
    313       1.1       cgd 			/*
    314       1.1       cgd 			 * We're interactive
    315       1.1       cgd 			 */
    316      1.25  christos 			assign(ENAME_INTERACTIVE, "");
    317       1.1       cgd 			break;
    318       1.1       cgd 		case 'c':
    319       1.1       cgd 			/*
    320       1.1       cgd 			 * Get Carbon Copy Recipient list
    321       1.1       cgd 			 */
    322      1.22  christos 			cc = cat(cc, lexpand(optarg, GCC));
    323       1.1       cgd 			break;
    324       1.1       cgd 		case 'b':
    325       1.1       cgd 			/*
    326       1.1       cgd 			 * Get Blind Carbon Copy Recipient list
    327       1.1       cgd 			 */
    328      1.22  christos 			bcc = cat(bcc, lexpand(optarg, GBCC));
    329      1.22  christos 
    330      1.22  christos 			break;
    331      1.11  christos 		case 'E':
    332      1.11  christos 			/*
    333      1.11  christos 			 * Don't send empty files.
    334      1.11  christos 			 */
    335      1.25  christos 			assign(ENAME_DONTSENDEMPTY, "");
    336      1.11  christos 			break;
    337      1.24  christos 		case ':':
    338      1.24  christos 			/*
    339      1.24  christos 			 * An optarg was expected but not found.
    340      1.24  christos 			 */
    341      1.24  christos 			if (optopt == 'H') {
    342      1.24  christos 				Hflag = get_Hflag(NULL);
    343      1.24  christos 				break;
    344      1.24  christos 			}
    345      1.24  christos 			(void)fprintf(stderr,
    346      1.24  christos 			    "%s: option requires an argument -- %c\n",
    347      1.24  christos 			    getprogname(), optopt);
    348  1.27.4.1      matt 
    349      1.24  christos 			/* FALLTHROUGH */
    350       1.1       cgd 		case '?':
    351      1.24  christos 			/*
    352      1.24  christos 			 * An unknown option flag.  We need to do the
    353      1.24  christos 			 * error message.
    354      1.24  christos 			 */
    355      1.24  christos 			if (optopt != '?')
    356      1.24  christos 				(void)fprintf(stderr,
    357      1.24  christos 				    "%s: unknown option -- %c\n", getprogname(),
    358      1.24  christos 				    optopt);
    359      1.23  christos #ifdef MIME_SUPPORT
    360      1.23  christos 			(void)fputs("\
    361      1.23  christos Usage: mail [-EiInv] [-s subject] [-a file] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
    362      1.23  christos             [- sendmail-options ...]\n\
    363      1.25  christos        mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
    364      1.25  christos        mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
    365      1.23  christos 				stderr);
    366      1.23  christos #else /* MIME_SUPPORT */
    367      1.20  christos 			(void)fputs("\
    368      1.11  christos Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
    369       1.1       cgd             [- sendmail-options ...]\n\
    370      1.25  christos        mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
    371      1.25  christos        mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
    372       1.1       cgd 				stderr);
    373      1.23  christos #endif /* MIME_SUPPORT */
    374      1.23  christos 
    375       1.1       cgd 			exit(1);
    376       1.1       cgd 		}
    377       1.1       cgd 	}
    378       1.1       cgd 	for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
    379       1.1       cgd 		to = cat(to, nalloc(argv[i], GTO));
    380  1.27.4.1      matt 	for (/*EMPTY*/; argv[i]; i++)
    381      1.22  christos 		smopts = cat(smopts, nalloc(argv[i], GSMOPTS));
    382       1.1       cgd 	/*
    383       1.1       cgd 	 * Check for inconsistent arguments.
    384       1.1       cgd 	 */
    385      1.21  christos 	if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL))
    386      1.21  christos 		errx(1, "You must specify direct recipients with -s, -c, or -b.");
    387      1.15       wiz 	if (ef != NULL && to != NULL) {
    388      1.21  christos 		errx(1, "Cannot give -f and people to send to.");
    389       1.1       cgd 	}
    390      1.24  christos 	if (Hflag != 0 && to != NULL)
    391      1.24  christos 		errx(EXIT_FAILURE, "Cannot give -H and people to send to.");
    392      1.23  christos #ifdef MIME_SUPPORT
    393      1.24  christos 	if (attach_optargs != NULL && to == NULL)
    394      1.24  christos 		errx(EXIT_FAILURE, "Cannot give -a without people to send to.");
    395      1.23  christos #endif
    396      1.24  christos 	tinit();	/* must be done before loading the rcfile */
    397       1.1       cgd 	input = stdin;
    398      1.25  christos 	mailmode = Hflag ? mm_hdrsonly :
    399      1.25  christos 	    to ? mm_sending : mm_receiving;
    400  1.27.4.1      matt 
    401       1.1       cgd 	spreserve();
    402       1.1       cgd 	if (!nosrc)
    403       1.1       cgd 		load(_PATH_MASTER_RC);
    404       1.1       cgd 	/*
    405       1.1       cgd 	 * Expand returns a savestr, but load only uses the file name
    406       1.1       cgd 	 * for fopen, so it's safe to do this.
    407       1.1       cgd 	 */
    408       1.6       tls 	if ((rc = getenv("MAILRC")) == 0)
    409       1.6       tls 		rc = "~/.mailrc";
    410       1.6       tls 	load(expand(rc));
    411      1.25  christos 	setscreensize();	/* do this after loading the rcfile */
    412      1.22  christos 
    413      1.23  christos #ifdef USE_EDITLINE
    414      1.26  christos 	/*
    415      1.26  christos 	 * This is after loading the MAILRC so we can use value().
    416      1.26  christos 	 * Avoid editline in mm_hdrsonly mode or pipelines will screw
    417      1.26  christos 	 * up.  XXX - there must be a better way!
    418      1.26  christos 	 */
    419      1.26  christos 	if (mailmode != mm_hdrsonly)
    420      1.26  christos 		init_editline();
    421      1.22  christos #endif
    422      1.22  christos 
    423      1.25  christos 	switch (mailmode) {
    424      1.25  christos 	case mm_sending:
    425      1.25  christos 		(void)mail(to, cc, bcc, smopts, subject,
    426      1.25  christos 		    mime_attach_optargs(attach_optargs));
    427       1.1       cgd 		/*
    428       1.1       cgd 		 * why wait?
    429       1.1       cgd 		 */
    430       1.1       cgd 		exit(senderr);
    431      1.25  christos 		break;	/* XXX - keep lint happy */
    432      1.25  christos 
    433      1.25  christos 	case mm_receiving:
    434      1.25  christos 	case mm_hdrsonly:
    435      1.25  christos 		/*
    436      1.25  christos 		 * Ok, we are reading mail.
    437      1.25  christos 		 * Decide whether we are editing a mailbox or reading
    438      1.25  christos 		 * the system mailbox, and open up the right stuff.
    439      1.25  christos 		 */
    440      1.25  christos 		if (ef == NULL)
    441      1.25  christos 			ef = "%";
    442      1.25  christos 		if (setfile(ef) < 0)
    443      1.25  christos 			exit(1);		/* error already reported */
    444      1.25  christos 		if (setjmp(hdrjmp) == 0) {
    445      1.25  christos 			if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
    446      1.25  christos 				(void)signal(SIGINT, hdrstop);
    447      1.25  christos 			if (value(ENAME_QUIET) == NULL)
    448      1.25  christos 				(void)printf("Mail version %s.  Type ? for help.\n",
    449      1.25  christos 				    version);
    450      1.25  christos 			if (mailmode == mm_hdrsonly)
    451      1.25  christos 				show_headers_and_exit(Hflag);	/* NORETURN */
    452      1.25  christos 			announce();
    453      1.25  christos 			(void)fflush(stdout);
    454      1.25  christos 			(void)signal(SIGINT, prevint);
    455      1.25  christos 		}
    456      1.25  christos 		commands();
    457      1.25  christos 		(void)signal(SIGHUP, SIG_IGN);
    458      1.25  christos 		(void)signal(SIGINT, SIG_IGN);
    459      1.25  christos 		(void)signal(SIGQUIT, SIG_IGN);
    460      1.25  christos 		quit();
    461      1.25  christos 		break;
    462  1.27.4.1      matt 
    463      1.25  christos 	default:
    464      1.25  christos 		assert(/*CONSTCOND*/0);
    465      1.25  christos 		break;
    466       1.1       cgd 	}
    467      1.25  christos 
    468      1.20  christos 	return 0;
    469       1.1       cgd }
    470