xref: /original-bsd/usr.bin/mail/main.c (revision f25de740)
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 this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #ifdef notdef
14 char copyright[] =
15 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
16  All rights reserved.\n";
17 #endif /* notdef */
18 
19 #ifdef notdef
20 static char sccsid[] = "@(#)main.c	5.13 (Berkeley) 06/17/88";
21 #endif /* notdef */
22 
23 #include "rcv.h"
24 #include <sys/stat.h>
25 
26 /*
27  * Mail -- a mail program
28  *
29  * Startup -- interface with user.
30  */
31 
32 jmp_buf	hdrjmp;
33 
34 /*
35  * Find out who the user is, copy his mail file (if exists) into
36  * /tmp/Rxxxxx and set up the message pointers.  Then, print out the
37  * message headers and read user commands.
38  *
39  * Command line syntax:
40  *	Mail [ -i ] [ -r address ] [ -h number ] [ -f [ name ] ]
41  * or:
42  *	Mail [ -i ] [ -r address ] [ -h number ] people ...
43  */
44 
45 main(argc, argv)
46 	char **argv;
47 {
48 	register char *ef, opt;
49 	register int i;
50 	struct name *to, *cc, *bcc, *smopts;
51 	int mustsend, hdrstop(), (*prevint)(), f;
52 	extern int getopt(), optind, opterr;
53 	extern char *optarg;
54 
55 	/*
56 	 * Set up a reasonable environment.
57 	 * Figure out whether we are being run interactively, set up
58 	 * all the temporary files, buffer standard output, and so forth.
59 	 */
60 	mypid = getpid();
61 	if (isatty(0))
62 		assign("interactive", "");
63 	image = -1;
64 	/*
65 	 * Now, determine how we are being used.
66 	 * We successively pick off instances of -r, -h, -f, and -i.
67 	 * If called as "rmail" we note this fact for letter sending.
68 	 * If there is anything left, it is the base of the list
69 	 * of users to mail to.  Argp will be set to point to the
70 	 * first of these users.
71 	 */
72 	ef = NOSTR;
73 	to = NULL;
74 	cc = NULL;
75 	bcc = NULL;
76 	smopts = NULL;
77 	mustsend = 0;
78 	if (argc > 0 && **argv == 'r')
79 		rmail++;
80 	while ((opt = getopt(argc, argv, "INT:b:c:dfh:inr:s:u:v")) != EOF) {
81 		switch (opt) {
82 		case 'r':
83 			/*
84 			 * Next argument is address to be sent along
85 			 * to the mailer.
86 			 */
87 			mustsend++;
88 			rflag = optarg;
89 			break;
90 		case 'T':
91 			/*
92 			 * Next argument is temp file to write which
93 			 * articles have been read/deleted for netnews.
94 			 */
95 			Tflag = optarg;
96 			if ((f = creat(Tflag, 0600)) < 0) {
97 				perror(Tflag);
98 				exit(1);
99 			}
100 			close(f);
101 			break;
102 		case 'u':
103 			/*
104 			 * Next argument is person to pretend to be.
105 			 */
106 			strcpy(myname, optarg);
107 			break;
108 		case 'i':
109 			/*
110 			 * User wants to ignore interrupts.
111 			 * Set the variable "ignore"
112 			 */
113 			assign("ignore", "");
114 			break;
115 		case 'd':
116 			debug++;
117 			break;
118 		case 'h':
119 			/*
120 			 * Specified sequence number for network.
121 			 * This is the number of "hops" made so
122 			 * far (count of times message has been
123 			 * forwarded) to help avoid infinite mail loops.
124 			 */
125 			mustsend++;
126 			hflag = atoi(optarg);
127 			if (hflag == 0) {
128 				fprintf(stderr, "-h needs non-zero number\n");
129 				exit(1);
130 			}
131 			break;
132 		case 's':
133 			/*
134 			 * Give a subject field for sending from
135 			 * non terminal
136 			 */
137 			mustsend++;
138 			sflag = optarg;
139 			break;
140 		case 'f':
141 			/*
142 			 * User is specifying file to "edit" with Mail,
143 			 * as opposed to reading system mailbox.
144 			 * If no argument is given after -f, we read his
145 			 * mbox file.
146 			 *
147 			 * getopt() can't handle optional arguments, so here
148 			 * is an ugly hack to get around it.
149 			 */
150 			if ((argv[optind]) && (argv[optind][0] != '-'))
151 				ef = argv[optind++];
152 			else
153 				ef = "&";
154 			break;
155 		case 'n':
156 			/*
157 			 * User doesn't want to source /usr/lib/Mail.rc
158 			 */
159 			nosrc++;
160 			break;
161 		case 'N':
162 			/*
163 			 * Avoid initial header printing.
164 			 */
165 			assign("noheader", "");
166 			break;
167 		case 'v':
168 			/*
169 			 * Send mailer verbose flag
170 			 */
171 			assign("verbose", "");
172 			break;
173 		case 'I':
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));
184 			mustsend++;
185 			break;
186 		case 'b':
187 			/*
188 			 * Get Blind Carbon Copy Recipient list
189 			 */
190 			bcc = cat(bcc, nalloc(optarg));
191 			mustsend++;
192 			break;
193 		case '?':
194 			fputs("\
195 Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
196             [- sendmail-options ...]\n\
197        mail [-iInNv] -f [name]\n\
198        mail [-iInNv] [-u user]\n",
199 				stderr);
200 			exit(1);
201 		}
202 	}
203 	for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
204 		to = cat(to, nalloc(argv[i]));
205 	for (; argv[i]; i++)
206 		smopts = cat(smopts, nalloc(argv[i]));
207 	/*
208 	 * Check for inconsistent arguments.
209 	 */
210 	if (!to && (cc || bcc)) {
211 		fputs("You must also specify direct recipients of mail.\n", stderr);
212 		exit(1);
213 	}
214 	if ((ef != NOSTR) && to) {
215 		fprintf(stderr, "Cannot give -f and people to send to.\n");
216 		exit(1);
217 	}
218 	if (mustsend && !to) {
219 		fprintf(stderr, "The flags you gave make no sense since you're not sending mail.\n");
220 		exit(1);
221 	}
222 	tinit();
223 	setscreensize();
224 	input = stdin;
225 	rcvmode = !to;
226 	if (!nosrc)
227 		load(MASTER);
228 	load(mailrc);
229 	if (!rcvmode) {
230 		mail(to, cc, bcc, smopts);
231 
232 		/*
233 		 * why wait?
234 		 */
235 
236 		exit(senderr);
237 	}
238 
239 	/*
240 	 * Ok, we are reading mail.
241 	 * Decide whether we are editing a mailbox or reading
242 	 * the system mailbox, and open up the right stuff.
243 	 */
244 	if (ef != NOSTR)
245 		edit++;
246 	else
247 		ef = "%";
248 	if ((ef = expand(ef)) == NOSTR)
249 		exit(1);		/* error already reported */
250 	if (setfile(ef, edit) < 0) {
251 		if (edit)
252 			perror(ef);
253 		else
254 			fprintf(stderr, "No mail for %s\n", myname);
255 		exit(1);
256 	}
257 	if (setjmp(hdrjmp) == 0) {
258 		extern char *version;
259 
260 		if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
261 			signal(SIGINT, hdrstop);
262 		if (value("quiet") == NOSTR)
263 			printf("Mail version %s.  Type ? for help.\n",
264 				version);
265 		announce();
266 		fflush(stdout);
267 		signal(SIGINT, prevint);
268 	}
269 	if (!edit && msgCount == 0) {
270 		printf("No mail\n");
271 		fflush(stdout);
272 		exit(0);
273 	}
274 	commands();
275 	if (!edit) {
276 		signal(SIGHUP, SIG_IGN);
277 		signal(SIGINT, SIG_IGN);
278 		signal(SIGQUIT, SIG_IGN);
279 		quit();
280 	}
281 	exit(0);
282 }
283 
284 /*
285  * Interrupt printing of the headers.
286  */
287 hdrstop()
288 {
289 
290 	fflush(stdout);
291 	fprintf(stderr, "\nInterrupt\n");
292 	longjmp(hdrjmp, 1);
293 }
294 
295 /*
296  * Compute what the screen size for printing headers should be.
297  * We use the following algorithm for the height:
298  *	If baud rate < 1200, use  9
299  *	If baud rate = 1200, use 14
300  *	If baud rate > 1200, use 24 or ws_row
301  * Width is either 80 or ws_col;
302  */
303 setscreensize()
304 {
305 	struct sgttyb tbuf;
306 #ifdef	TIOCGWINSZ
307 	struct winsize ws;
308 
309 	if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
310 #endif
311 		ws.ws_col = ws.ws_row = 0;
312 	if (gtty(1, &tbuf) < 0)
313 		tbuf.sg_ospeed = B9600;
314 	if (tbuf.sg_ospeed < B1200)
315 		screenheight = 9;
316 	else if (tbuf.sg_ospeed == B1200)
317 		screenheight = 14;
318 	else if (ws.ws_row != 0)
319 		screenheight = ws.ws_row;
320 	else
321 		screenheight = 24;
322 	if ((realscreenheight = ws.ws_row) == 0)
323 		realscreenheight = 24;
324 	if ((screenwidth = ws.ws_col) == 0)
325 		screenwidth = 80;
326 }
327