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