Home | History | Annotate | Line # | Download | only in mail
main.c revision 1.15
      1 /*	$NetBSD: main.c,v 1.15 2002/03/04 03:16:10 wiz Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1980, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
     39 	The Regents of the University of California.  All rights reserved.\n");
     40 #endif /* not lint */
     41 
     42 #ifndef lint
     43 #if 0
     44 static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 4/20/95";
     45 #else
     46 __RCSID("$NetBSD: main.c,v 1.15 2002/03/04 03:16:10 wiz Exp $");
     47 #endif
     48 #endif /* not lint */
     49 
     50 #define EXTERN
     51 #include "rcv.h"
     52 #undef EXTERN
     53 
     54 #include "extern.h"
     55 
     56 extern char *version;
     57 
     58 int	main(int, char **);
     59 
     60 /*
     61  * Mail -- a mail program
     62  *
     63  * Startup -- interface with user.
     64  */
     65 
     66 jmp_buf	hdrjmp;
     67 
     68 int
     69 main(int argc, char *argv[])
     70 {
     71 	int i;
     72 	struct name *to, *cc, *bcc, *smopts;
     73 	char *subject;
     74 	char *ef;
     75 	char nosrc = 0;
     76 	sig_t prevint;
     77 	char *rc;
     78 
     79 	/*
     80 	 * Set up a reasonable environment.
     81 	 * Figure out whether we are being run interactively,
     82 	 * start the SIGCHLD catcher, and so forth.
     83 	 */
     84 	(void) signal(SIGCHLD, sigchild);
     85 	if (isatty(0))
     86 		assign("interactive", "");
     87 	image = -1;
     88 	/*
     89 	 * Now, determine how we are being used.
     90 	 * We successively pick off - flags.
     91 	 * If there is anything left, it is the base of the list
     92 	 * of users to mail to.  Argp will be set to point to the
     93 	 * first of these users.
     94 	 */
     95 	ef = NULL;
     96 	to = NULL;
     97 	cc = NULL;
     98 	bcc = NULL;
     99 	smopts = NULL;
    100 	subject = NULL;
    101 	while ((i = getopt(argc, argv, "~EINT:b:c:dfins:u:v")) != -1) {
    102 		switch (i) {
    103 		case 'T':
    104 			/*
    105 			 * Next argument is temp file to write which
    106 			 * articles have been read/deleted for netnews.
    107 			 */
    108 			Tflag = optarg;
    109 			if ((i = creat(Tflag, 0600)) < 0) {
    110 				perror(Tflag);
    111 				exit(1);
    112 			}
    113 			close(i);
    114 			break;
    115 		case 'u':
    116 			/*
    117 			 * Next argument is person to pretend to be.
    118 			 */
    119 			myname = optarg;
    120 			unsetenv("MAIL");
    121 			break;
    122 		case 'i':
    123 			/*
    124 			 * User wants to ignore interrupts.
    125 			 * Set the variable "ignore"
    126 			 */
    127 			assign("ignore", "");
    128 			break;
    129 		case 'd':
    130 			debug++;
    131 			break;
    132 		case 's':
    133 			/*
    134 			 * Give a subject field for sending from
    135 			 * non terminal
    136 			 */
    137 			subject = optarg;
    138 			break;
    139 		case 'f':
    140 			/*
    141 			 * User is specifying file to "edit" with Mail,
    142 			 * as opposed to reading system mailbox.
    143 			 * If no argument is given after -f, we read his
    144 			 * mbox file.
    145 			 *
    146 			 * getopt() can't handle optional arguments, so here
    147 			 * is an ugly hack to get around it.
    148 			 */
    149 			if ((argv[optind]) && (argv[optind][0] != '-'))
    150 				ef = argv[optind++];
    151 			else
    152 				ef = "&";
    153 			break;
    154 		case 'n':
    155 			/*
    156 			 * User doesn't want to source /usr/lib/Mail.rc
    157 			 */
    158 			nosrc++;
    159 			break;
    160 		case 'N':
    161 			/*
    162 			 * Avoid initial header printing.
    163 			 */
    164 			assign("noheader", "");
    165 			break;
    166 		case 'v':
    167 			/*
    168 			 * Send mailer verbose flag
    169 			 */
    170 			assign("verbose", "");
    171 			break;
    172 		case 'I':
    173 		case '~':
    174 			/*
    175 			 * We're interactive
    176 			 */
    177 			assign("interactive", "");
    178 			break;
    179 		case 'c':
    180 			/*
    181 			 * Get Carbon Copy Recipient list
    182 			 */
    183 			cc = cat(cc, nalloc(optarg, GCC));
    184 			break;
    185 		case 'b':
    186 			/*
    187 			 * Get Blind Carbon Copy Recipient list
    188 			 */
    189 			bcc = cat(bcc, nalloc(optarg, GBCC));
    190 			break;
    191 		case 'E':
    192 			/*
    193 			 * Don't send empty files.
    194 			 */
    195 			assign("dontsendempty", "");
    196 			break;
    197 		case '?':
    198 			fputs("\
    199 Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
    200             [- sendmail-options ...]\n\
    201        mail [-EiInNv] -f [name]\n\
    202        mail [-EiInNv] [-u user]\n",
    203 				stderr);
    204 			exit(1);
    205 		}
    206 	}
    207 	for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
    208 		to = cat(to, nalloc(argv[i], GTO));
    209 	for (; argv[i]; i++)
    210 		smopts = cat(smopts, nalloc(argv[i], 0));
    211 	/*
    212 	 * Check for inconsistent arguments.
    213 	 */
    214 	if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL)) {
    215 		fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr);
    216 		exit(1);
    217 	}
    218 	if (ef != NULL && to != NULL) {
    219 		fprintf(stderr, "Cannot give -f and people to send to.\n");
    220 		exit(1);
    221 	}
    222 	tinit();
    223 	setscreensize();
    224 	input = stdin;
    225 	rcvmode = !to;
    226 	spreserve();
    227 	if (!nosrc)
    228 		load(_PATH_MASTER_RC);
    229 	/*
    230 	 * Expand returns a savestr, but load only uses the file name
    231 	 * for fopen, so it's safe to do this.
    232 	 */
    233 	if ((rc = getenv("MAILRC")) == 0)
    234 		rc = "~/.mailrc";
    235 	load(expand(rc));
    236 	if (!rcvmode) {
    237 		mail(to, cc, bcc, smopts, subject);
    238 		/*
    239 		 * why wait?
    240 		 */
    241 		exit(senderr);
    242 	}
    243 	/*
    244 	 * Ok, we are reading mail.
    245 	 * Decide whether we are editing a mailbox or reading
    246 	 * the system mailbox, and open up the right stuff.
    247 	 */
    248 	if (ef == NULL)
    249 		ef = "%";
    250 	if (setfile(ef) < 0)
    251 		exit(1);		/* error already reported */
    252 	if (setjmp(hdrjmp) == 0) {
    253 		if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
    254 			signal(SIGINT, hdrstop);
    255 		if (value("quiet") == NULL)
    256 			printf("Mail version %s.  Type ? for help.\n",
    257 				version);
    258 		announce();
    259 		fflush(stdout);
    260 		signal(SIGINT, prevint);
    261 	}
    262 	commands();
    263 	signal(SIGHUP, SIG_IGN);
    264 	signal(SIGINT, SIG_IGN);
    265 	signal(SIGQUIT, SIG_IGN);
    266 	quit();
    267 	exit(0);
    268 }
    269 
    270 /*
    271  * Interrupt printing of the headers.
    272  */
    273 void
    274 hdrstop(int signo)
    275 {
    276 
    277 	fflush(stdout);
    278 	fprintf(stderr, "\nInterrupt\n");
    279 	longjmp(hdrjmp, 1);
    280 }
    281 
    282 /*
    283  * Compute what the screen size for printing headers should be.
    284  * We use the following algorithm for the height:
    285  *	If baud rate < 1200, use  9
    286  *	If baud rate = 1200, use 14
    287  *	If baud rate > 1200, use 24 or ws_row
    288  * Width is either 80 or ws_col;
    289  */
    290 void
    291 setscreensize(void)
    292 {
    293 	struct termios tbuf;
    294 	struct winsize ws;
    295 	speed_t ospeed;
    296 
    297 	if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
    298 		ws.ws_col = ws.ws_row = 0;
    299 	if (tcgetattr(1, &tbuf) < 0)
    300 		ospeed = 9600;
    301 	else
    302 		ospeed = cfgetospeed(&tbuf);
    303 	if (ospeed < 1200)
    304 		screenheight = 9;
    305 	else if (ospeed == 1200)
    306 		screenheight = 14;
    307 	else if (ws.ws_row != 0)
    308 		screenheight = ws.ws_row;
    309 	else
    310 		screenheight = 24;
    311 	if ((realscreenheight = ws.ws_row) == 0)
    312 		realscreenheight = 24;
    313 	if ((screenwidth = ws.ws_col) == 0)
    314 		screenwidth = 80;
    315 }
    316