xref: /original-bsd/usr.bin/mail/main.c (revision b3f911e0)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)main.c	5.25 (Berkeley) 11/24/89";
26 #endif /* not lint */
27 
28 #include "rcv.h"
29 #include <sys/stat.h>
30 
31 /*
32  * Mail -- a mail program
33  *
34  * Startup -- interface with user.
35  */
36 
37 jmp_buf	hdrjmp;
38 
39 main(argc, argv)
40 	char **argv;
41 {
42 	register int i;
43 	struct name *to, *cc, *bcc, *smopts;
44 	char *subject;
45 	char *ef;
46 	char nosrc = 0;
47 	int hdrstop();
48 	sig_t prevint;
49 	int sigchild();
50 	extern int getopt(), optind, opterr;
51 	extern char *optarg;
52 
53 	/*
54 	 * Set up a reasonable environment.
55 	 * Figure out whether we are being run interactively,
56 	 * start the SIGCHLD catcher, and so forth.
57 	 */
58 	(void) signal(SIGCHLD, sigchild);
59 	if (isatty(0))
60 		assign("interactive", "");
61 	image = -1;
62 	/*
63 	 * Now, determine how we are being used.
64 	 * We successively pick off - flags.
65 	 * If there is anything left, it is the base of the list
66 	 * of users to mail to.  Argp will be set to point to the
67 	 * first of these users.
68 	 */
69 	ef = NOSTR;
70 	to = NIL;
71 	cc = NIL;
72 	bcc = NIL;
73 	smopts = NIL;
74 	subject = NOSTR;
75 	while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) {
76 		switch (i) {
77 		case 'T':
78 			/*
79 			 * Next argument is temp file to write which
80 			 * articles have been read/deleted for netnews.
81 			 */
82 			Tflag = optarg;
83 			if ((i = creat(Tflag, 0600)) < 0) {
84 				perror(Tflag);
85 				exit(1);
86 			}
87 			close(i);
88 			break;
89 		case 'u':
90 			/*
91 			 * Next argument is person to pretend to be.
92 			 */
93 			myname = optarg;
94 			break;
95 		case 'i':
96 			/*
97 			 * User wants to ignore interrupts.
98 			 * Set the variable "ignore"
99 			 */
100 			assign("ignore", "");
101 			break;
102 		case 'd':
103 			debug++;
104 			break;
105 		case 's':
106 			/*
107 			 * Give a subject field for sending from
108 			 * non terminal
109 			 */
110 			subject = optarg;
111 			break;
112 		case 'f':
113 			/*
114 			 * User is specifying file to "edit" with Mail,
115 			 * as opposed to reading system mailbox.
116 			 * If no argument is given after -f, we read his
117 			 * mbox file.
118 			 *
119 			 * getopt() can't handle optional arguments, so here
120 			 * is an ugly hack to get around it.
121 			 */
122 			if ((argv[optind]) && (argv[optind][0] != '-'))
123 				ef = argv[optind++];
124 			else
125 				ef = "&";
126 			break;
127 		case 'n':
128 			/*
129 			 * User doesn't want to source /usr/lib/Mail.rc
130 			 */
131 			nosrc++;
132 			break;
133 		case 'N':
134 			/*
135 			 * Avoid initial header printing.
136 			 */
137 			assign("noheader", "");
138 			break;
139 		case 'v':
140 			/*
141 			 * Send mailer verbose flag
142 			 */
143 			assign("verbose", "");
144 			break;
145 		case 'I':
146 			/*
147 			 * We're interactive
148 			 */
149 			assign("interactive", "");
150 			break;
151 		case 'c':
152 			/*
153 			 * Get Carbon Copy Recipient list
154 			 */
155 			cc = cat(cc, nalloc(optarg, GCC));
156 			break;
157 		case 'b':
158 			/*
159 			 * Get Blind Carbon Copy Recipient list
160 			 */
161 			bcc = cat(bcc, nalloc(optarg, GBCC));
162 			break;
163 		case '?':
164 			fputs("\
165 Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
166             [- sendmail-options ...]\n\
167        mail [-iInNv] -f [name]\n\
168        mail [-iInNv] [-u user]\n",
169 				stderr);
170 			exit(1);
171 		}
172 	}
173 	for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
174 		to = cat(to, nalloc(argv[i], GTO));
175 	for (; argv[i]; i++)
176 		smopts = cat(smopts, nalloc(argv[i], 0));
177 	/*
178 	 * Check for inconsistent arguments.
179 	 */
180 	if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) {
181 		fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr);
182 		exit(1);
183 	}
184 	if (ef != NOSTR && to != NIL) {
185 		fprintf(stderr, "Cannot give -f and people to send to.\n");
186 		exit(1);
187 	}
188 	tinit();
189 	setscreensize();
190 	input = stdin;
191 	rcvmode = !to;
192 	spreserve();
193 	if (!nosrc)
194 		load(_PATH_MASTER_RC);
195 	/*
196 	 * Expand returns a savestr, but load only uses the file name
197 	 * for fopen, so it's save to do this.
198 	 */
199 	load(expand("~/.mailrc"));
200 	if (!rcvmode) {
201 		mail(to, cc, bcc, smopts, subject);
202 		/*
203 		 * why wait?
204 		 */
205 		exit(senderr);
206 	}
207 	/*
208 	 * Ok, we are reading mail.
209 	 * Decide whether we are editing a mailbox or reading
210 	 * the system mailbox, and open up the right stuff.
211 	 */
212 	if (ef == NOSTR)
213 		ef = "%";
214 	if (setfile(ef) < 0)
215 		exit(1);		/* error already reported */
216 	if (setjmp(hdrjmp) == 0) {
217 		extern char *version;
218 
219 		if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
220 			signal(SIGINT, hdrstop);
221 		if (value("quiet") == NOSTR)
222 			printf("Mail version %s.  Type ? for help.\n",
223 				version);
224 		announce();
225 		fflush(stdout);
226 		signal(SIGINT, prevint);
227 	}
228 	commands();
229 	signal(SIGHUP, SIG_IGN);
230 	signal(SIGINT, SIG_IGN);
231 	signal(SIGQUIT, SIG_IGN);
232 	quit();
233 	exit(0);
234 }
235 
236 /*
237  * Interrupt printing of the headers.
238  */
239 hdrstop()
240 {
241 
242 	fflush(stdout);
243 	fprintf(stderr, "\nInterrupt\n");
244 	longjmp(hdrjmp, 1);
245 }
246 
247 /*
248  * Compute what the screen size for printing headers should be.
249  * We use the following algorithm for the height:
250  *	If baud rate < 1200, use  9
251  *	If baud rate = 1200, use 14
252  *	If baud rate > 1200, use 24 or ws_row
253  * Width is either 80 or ws_col;
254  */
255 setscreensize()
256 {
257 	struct sgttyb tbuf;
258 	struct winsize ws;
259 
260 	if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
261 		ws.ws_col = ws.ws_row = 0;
262 	if (ioctl(1, TIOCGETP, &tbuf) < 0)
263 		tbuf.sg_ospeed = B9600;
264 	if (tbuf.sg_ospeed < B1200)
265 		screenheight = 9;
266 	else if (tbuf.sg_ospeed == B1200)
267 		screenheight = 14;
268 	else if (ws.ws_row != 0)
269 		screenheight = ws.ws_row;
270 	else
271 		screenheight = 24;
272 	if ((realscreenheight = ws.ws_row) == 0)
273 		realscreenheight = 24;
274 	if ((screenwidth = ws.ws_col) == 0)
275 		screenwidth = 80;
276 }
277