xref: /csrg-svn/usr.bin/mail/main.c (revision 68818)
122459Sdist /*
262083Sbostic  * Copyright (c) 1980, 1993
362083Sbostic  *	The Regents of the University of California.  All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622459Sdist  */
722459Sdist 
834905Sbostic #ifndef lint
962083Sbostic static char copyright[] =
1062083Sbostic "@(#) Copyright (c) 1980, 1993\n\
1162083Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234905Sbostic #endif /* not lint */
131240Skas 
1434905Sbostic #ifndef lint
15*68818Sdab static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 04/20/95";
1634905Sbostic #endif /* not lint */
1722459Sdist 
181240Skas #include "rcv.h"
1954505Sbostic #include <fcntl.h>
2054505Sbostic #include "extern.h"
211240Skas 
221240Skas /*
231240Skas  * Mail -- a mail program
241240Skas  *
251240Skas  * Startup -- interface with user.
261240Skas  */
271240Skas 
285780Skurt jmp_buf	hdrjmp;
295780Skurt 
3054505Sbostic int
main(argc,argv)311240Skas main(argc, argv)
3254505Sbostic 	int argc;
3354505Sbostic 	char *argv[];
341240Skas {
3534702Sedward 	register int i;
3634702Sedward 	struct name *to, *cc, *bcc, *smopts;
3734800Sedward 	char *subject;
3834800Sedward 	char *ef;
3934968Sedward 	char nosrc = 0;
4047708Sbostic 	void hdrstop();
4139612Sedward 	sig_t prevint;
4247708Sbostic 	void sigchild();
43*68818Sdab 	char *rc;
441240Skas 
451240Skas 	/*
4631142Sedward 	 * Set up a reasonable environment.
4734976Sedward 	 * Figure out whether we are being run interactively,
4834976Sedward 	 * start the SIGCHLD catcher, and so forth.
491240Skas 	 */
5034976Sedward 	(void) signal(SIGCHLD, sigchild);
5134751Sedward 	if (isatty(0))
5234751Sedward 		assign("interactive", "");
531240Skas 	image = -1;
541240Skas 	/*
551240Skas 	 * Now, determine how we are being used.
5634787Sedward 	 * We successively pick off - flags.
571240Skas 	 * If there is anything left, it is the base of the list
581240Skas 	 * of users to mail to.  Argp will be set to point to the
591240Skas 	 * first of these users.
601240Skas 	 */
611240Skas 	ef = NOSTR;
6234800Sedward 	to = NIL;
6334800Sedward 	cc = NIL;
6434800Sedward 	bcc = NIL;
6534800Sedward 	smopts = NIL;
6634800Sedward 	subject = NOSTR;
6734787Sedward 	while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) {
6834787Sedward 		switch (i) {
694019Skurt 		case 'T':
704019Skurt 			/*
714019Skurt 			 * Next argument is temp file to write which
724019Skurt 			 * articles have been read/deleted for netnews.
734019Skurt 			 */
7434702Sedward 			Tflag = optarg;
7534787Sedward 			if ((i = creat(Tflag, 0600)) < 0) {
765966Skurt 				perror(Tflag);
775966Skurt 				exit(1);
785966Skurt 			}
7934787Sedward 			close(i);
804019Skurt 			break;
811240Skas 		case 'u':
821240Skas 			/*
831240Skas 			 * Next argument is person to pretend to be.
841240Skas 			 */
8534968Sedward 			myname = optarg;
861240Skas 			break;
871240Skas 		case 'i':
881240Skas 			/*
891240Skas 			 * User wants to ignore interrupts.
901240Skas 			 * Set the variable "ignore"
911240Skas 			 */
921240Skas 			assign("ignore", "");
931240Skas 			break;
941240Skas 		case 'd':
951240Skas 			debug++;
961240Skas 			break;
971240Skas 		case 's':
981240Skas 			/*
991240Skas 			 * Give a subject field for sending from
1001240Skas 			 * non terminal
1011240Skas 			 */
10234800Sedward 			subject = optarg;
1031240Skas 			break;
1041240Skas 		case 'f':
1051240Skas 			/*
1061240Skas 			 * User is specifying file to "edit" with Mail,
1071240Skas 			 * as opposed to reading system mailbox.
1081240Skas 			 * If no argument is given after -f, we read his
10934753Sedward 			 * mbox file.
11034702Sedward 			 *
11134702Sedward 			 * getopt() can't handle optional arguments, so here
11234702Sedward 			 * is an ugly hack to get around it.
1131240Skas 			 */
11434704Sedward 			if ((argv[optind]) && (argv[optind][0] != '-'))
11534702Sedward 				ef = argv[optind++];
11634702Sedward 			else
11734753Sedward 				ef = "&";
1181240Skas 			break;
1191240Skas 		case 'n':
1201240Skas 			/*
1211240Skas 			 * User doesn't want to source /usr/lib/Mail.rc
1221240Skas 			 */
1231240Skas 			nosrc++;
1241240Skas 			break;
1252353Skas 		case 'N':
1262353Skas 			/*
1272353Skas 			 * Avoid initial header printing.
1282353Skas 			 */
12934704Sedward 			assign("noheader", "");
1302353Skas 			break;
13110581Sleres 		case 'v':
13210581Sleres 			/*
13310581Sleres 			 * Send mailer verbose flag
13410581Sleres 			 */
13510581Sleres 			assign("verbose", "");
13610581Sleres 			break;
13721091Sserge 		case 'I':
13821091Sserge 			/*
13921091Sserge 			 * We're interactive
14021091Sserge 			 */
14134751Sedward 			assign("interactive", "");
14221091Sserge 			break;
14334702Sedward 		case 'c':
14434702Sedward 			/*
14534702Sedward 			 * Get Carbon Copy Recipient list
14634702Sedward 			 */
14734800Sedward 			cc = cat(cc, nalloc(optarg, GCC));
14834702Sedward 			break;
14934702Sedward 		case 'b':
15034702Sedward 			/*
15134702Sedward 			 * Get Blind Carbon Copy Recipient list
15234702Sedward 			 */
15334800Sedward 			bcc = cat(bcc, nalloc(optarg, GBCC));
15434702Sedward 			break;
15534702Sedward 		case '?':
15634703Sedward 			fputs("\
15734703Sedward Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
15834703Sedward             [- sendmail-options ...]\n\
15934703Sedward        mail [-iInNv] -f [name]\n\
16034703Sedward        mail [-iInNv] [-u user]\n",
16134703Sedward 				stderr);
1621240Skas 			exit(1);
1631240Skas 		}
1641240Skas 	}
16534704Sedward 	for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
16634800Sedward 		to = cat(to, nalloc(argv[i], GTO));
16734702Sedward 	for (; argv[i]; i++)
16834800Sedward 		smopts = cat(smopts, nalloc(argv[i], 0));
1691240Skas 	/*
1701240Skas 	 * Check for inconsistent arguments.
1711240Skas 	 */
17234800Sedward 	if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) {
17334800Sedward 		fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr);
17434702Sedward 		exit(1);
17534702Sedward 	}
17634800Sedward 	if (ef != NOSTR && to != NIL) {
1771240Skas 		fprintf(stderr, "Cannot give -f and people to send to.\n");
1781240Skas 		exit(1);
1791240Skas 	}
1801240Skas 	tinit();
18131142Sedward 	setscreensize();
1825780Skurt 	input = stdin;
18334702Sedward 	rcvmode = !to;
18434968Sedward 	spreserve();
1855780Skurt 	if (!nosrc)
18637870Sbostic 		load(_PATH_MASTER_RC);
18735374Sedward 	/*
18835374Sedward 	 * Expand returns a savestr, but load only uses the file name
18943865Sedward 	 * for fopen, so it's safe to do this.
19035374Sedward 	 */
191*68818Sdab 	if ((rc = getenv("MAILRC")) == 0)
192*68818Sdab 		rc = "~/.mailrc";
193*68818Sdab 	load(expand(rc));
19434702Sedward 	if (!rcvmode) {
19534800Sedward 		mail(to, cc, bcc, smopts, subject);
1961240Skas 		/*
1971240Skas 		 * why wait?
1981240Skas 		 */
1991240Skas 		exit(senderr);
2001240Skas 	}
2011240Skas 	/*
2021240Skas 	 * Ok, we are reading mail.
2031240Skas 	 * Decide whether we are editing a mailbox or reading
2041240Skas 	 * the system mailbox, and open up the right stuff.
2051240Skas 	 */
20636734Sedward 	if (ef == NOSTR)
20734753Sedward 		ef = "%";
20836734Sedward 	if (setfile(ef) < 0)
20934753Sedward 		exit(1);		/* error already reported */
21034704Sedward 	if (setjmp(hdrjmp) == 0) {
21134754Sedward 		extern char *version;
21234754Sedward 
21334704Sedward 		if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
21434704Sedward 			signal(SIGINT, hdrstop);
21534754Sedward 		if (value("quiet") == NOSTR)
21634754Sedward 			printf("Mail version %s.  Type ? for help.\n",
21734754Sedward 				version);
21834754Sedward 		announce();
21934704Sedward 		fflush(stdout);
22034704Sedward 		signal(SIGINT, prevint);
2215780Skurt 	}
2221240Skas 	commands();
22336554Sedward 	signal(SIGHUP, SIG_IGN);
22436554Sedward 	signal(SIGINT, SIG_IGN);
22536554Sedward 	signal(SIGQUIT, SIG_IGN);
22636554Sedward 	quit();
2271240Skas 	exit(0);
2281240Skas }
2295780Skurt 
2305780Skurt /*
2315780Skurt  * Interrupt printing of the headers.
2325780Skurt  */
23347708Sbostic void
hdrstop(signo)23454505Sbostic hdrstop(signo)
23554505Sbostic 	int signo;
2365780Skurt {
2375780Skurt 
2385780Skurt 	fflush(stdout);
23916859Sralph 	fprintf(stderr, "\nInterrupt\n");
2405780Skurt 	longjmp(hdrjmp, 1);
2415780Skurt }
24231142Sedward 
24331142Sedward /*
24434749Sedward  * Compute what the screen size for printing headers should be.
24531142Sedward  * We use the following algorithm for the height:
24631142Sedward  *	If baud rate < 1200, use  9
24731142Sedward  *	If baud rate = 1200, use 14
24831142Sedward  *	If baud rate > 1200, use 24 or ws_row
24931142Sedward  * Width is either 80 or ws_col;
25031142Sedward  */
25154505Sbostic void
setscreensize()25231142Sedward setscreensize()
25331142Sedward {
254*68818Sdab 	struct termios tbuf;
25531142Sedward 	struct winsize ws;
256*68818Sdab 	int ospeed;
25731142Sedward 
25834751Sedward 	if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
25931142Sedward 		ws.ws_col = ws.ws_row = 0;
260*68818Sdab 	if (ioctl(1, TIOCGETA, &tbuf) < 0)
261*68818Sdab 		ospeed = B9600;
262*68818Sdab 	else
263*68818Sdab 		ospeed = cfgetospeed(&tbuf);
264*68818Sdab 	if (ospeed < B1200)
26531142Sedward 		screenheight = 9;
266*68818Sdab 	else if (ospeed == B1200)
26731142Sedward 		screenheight = 14;
26831142Sedward 	else if (ws.ws_row != 0)
26931142Sedward 		screenheight = ws.ws_row;
27031142Sedward 	else
27131142Sedward 		screenheight = 24;
27234749Sedward 	if ((realscreenheight = ws.ws_row) == 0)
27334749Sedward 		realscreenheight = 24;
27434749Sedward 	if ((screenwidth = ws.ws_col) == 0)
27531142Sedward 		screenwidth = 80;
27631142Sedward }
277