GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mail/main.c Lines: 41 98 41.8 %
Date: 2017-11-07 Branches: 15 52 28.8 %

Line Branch Exec Source
1
/*	$OpenBSD: main.c,v 1.33 2015/11/24 00:08:27 deraadt Exp $	*/
2
/*	$NetBSD: main.c,v 1.7 1997/05/13 06:15:57 mikel Exp $	*/
3
4
/*
5
 * Copyright (c) 1980, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include "rcv.h"
34
#include <fcntl.h>
35
#include <sys/ioctl.h>
36
#include "extern.h"
37
38
__dead	void	usage(void);
39
	int	main(int, char **);
40
41
/*
42
 * Mail -- a mail program
43
 *
44
 * Startup -- interface with user.
45
 */
46
47
int
48
main(int argc, char **argv)
49
{
50
	int i;
51
	struct name *to, *cc, *bcc, *smopts;
52
	char *fromaddr;
53
	char *subject;
54
	char *ef;
55
	char nosrc = 0;
56
	char *rc;
57
	extern const char version[];
58
59
6
	if (pledge("stdio rpath wpath cpath getpw tmppath fattr tty flock proc exec",
60
2
	    NULL) == -1)
61
		err(1, "pledge");
62
63
	/*
64
	 * Set up a reasonable environment.
65
	 * Figure out whether we are being run interactively,
66
	 * start the SIGCHLD catcher, and so forth.
67
	 */
68
2
	(void)signal(SIGCHLD, sigchild);
69
2
	(void)signal(SIGPIPE, SIG_IGN);
70
2
	if (isatty(0))
71
		assign("interactive", "");
72
2
	image = -1;
73
	/*
74
	 * Now, determine how we are being used.
75
	 * We successively pick off - flags.
76
	 * If there is anything left, it is the base of the list
77
	 * of users to mail to.  Argp will be set to point to the
78
	 * first of these users.
79
	 */
80
	ef = NULL;
81
	to = NULL;
82
	cc = NULL;
83
	bcc = NULL;
84
	smopts = NULL;
85
	fromaddr = NULL;
86
	subject = NULL;
87
6
	while ((i = getopt(argc, argv, "EINb:c:dfinr:s:u:v")) != -1) {
88



2
		switch (i) {
89
		case 'u':
90
			/*
91
			 * Next argument is person to pretend to be.
92
			 */
93
			if (strlen(optarg) >= LOGIN_NAME_MAX)
94
				errx(1, "username `%s' too long", optarg);
95
			unsetenv("MAIL");
96
			myname = optarg;
97
			uflag = 1;
98
			break;
99
		case 'i':
100
			/*
101
			 * User wants to ignore interrupts.
102
			 * Set the variable "ignore"
103
			 */
104
			assign("ignore", "");
105
			break;
106
		case 'd':
107
			debug++;
108
			break;
109
		case 'r':
110
			/*
111
			 * Set From: address
112
			 */
113
			fromaddr = optarg;
114
			break;
115
		case 's':
116
			/*
117
			 * Give a subject field for sending from
118
			 * non terminal
119
			 */
120
2
			subject = optarg;
121
2
			break;
122
		case 'f':
123
			/*
124
			 * User is specifying file to "edit" with Mail,
125
			 * as opposed to reading system mailbox.
126
			 * We read his mbox file unless another file
127
			 * is specified after the arguments.
128
			 */
129
			ef = "&";
130
			break;
131
		case 'n':
132
			/*
133
			 * User doesn't want to source /usr/lib/Mail.rc
134
			 */
135
			nosrc = 1;
136
			break;
137
		case 'N':
138
			/*
139
			 * Avoid initial header printing.
140
			 */
141
			assign("noheader", "");
142
			break;
143
		case 'v':
144
			/*
145
			 * Send mailer verbose flag
146
			 */
147
			assign("verbose", "");
148
			break;
149
		case 'I':
150
			/*
151
			 * We're interactive
152
			 */
153
			assign("interactive", "");
154
			break;
155
		case 'c':
156
			/*
157
			 * Get Carbon Copy Recipient list
158
			 */
159
			cc = cat(cc, nalloc(optarg, GCC));
160
			break;
161
		case 'b':
162
			/*
163
			 * Get Blind Carbon Copy Recipient list
164
			 */
165
			bcc = cat(bcc, nalloc(optarg, GBCC));
166
			break;
167
		case 'E':
168
			/*
169
			 * Don't send messages with an empty body.
170
			 */
171
			assign("skipempty", "");
172
			break;
173
		default:
174
			usage();
175
			/*NOTREACHED*/
176
		}
177
	}
178
2
	if (ef != NULL) {
179
		/* Check for optional mailbox file name. */
180
		if (optind < argc) {
181
			ef = argv[optind++];
182
			if (optind < argc)
183
			    errx(1, "Cannot give -f and people to send to");
184
		}
185
	} else {
186
8
		for (i = optind; argv[i]; i++)
187
2
			to = cat(to, nalloc(argv[i], GTO));
188
	}
189
	/*
190
	 * Check for inconsistent arguments.
191
	 */
192

2
	if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL ||
193
	    fromaddr != NULL))
194
		errx(1, "You must specify direct recipients with -s, -c, -b, "
195
		    "or -r");
196
	/*
197
	 * Block SIGINT except where we install an explicit handler for it.
198
	 */
199
2
	sigemptyset(&intset);
200
2
	sigaddset(&intset, SIGINT);
201
2
	(void)sigprocmask(SIG_BLOCK, &intset, NULL);
202
	/*
203
	 * Initialization.
204
	 */
205
2
	tinit();
206
2
	setscreensize();
207
2
	input = stdin;
208
2
	rcvmode = !to;
209
2
	spreserve();
210
2
	if (!nosrc)
211
2
		load(_PATH_MASTER_RC);
212
	/*
213
	 * Expand returns a savestr, but load only uses the file name
214
	 * for fopen, so it's safe to do this.
215
	 */
216
2
	if ((rc = getenv("MAILRC")) == 0)
217
		rc = "~/.mailrc";
218
2
	load(expand(rc));
219
2
	if (!rcvmode) {
220
		mail(to, cc, bcc, smopts, fromaddr, subject);
221
		/*
222
		 * why wait?
223
		 */
224
		exit(senderr);
225
	}
226
	/*
227
	 * Ok, we are reading mail.
228
	 * Decide whether we are editing a mailbox or reading
229
	 * the system mailbox, and open up the right stuff.
230
	 */
231
	if (ef == NULL)
232
		ef = "%";
233
	if (setfile(ef) < 0)
234
		exit(1);		/* error already reported */
235
236
	if (value("quiet") == NULL)
237
		(void)printf("Mail version %s.  Type ? for help.\n",
238
			version);
239
	announce();
240
	(void)fflush(stdout);
241
	commands();
242
	(void)ignoresig(SIGHUP, NULL, NULL);
243
	(void)ignoresig(SIGINT, NULL, NULL);
244
	(void)ignoresig(SIGQUIT, NULL, NULL);
245
	quit();
246
	exit(0);
247
}
248
249
/*
250
 * Compute what the screen size for printing headers should be.
251
 * We use the following algorithm for the height:
252
 *	If baud rate < 1200, use  9
253
 *	If baud rate = 1200, use 14
254
 *	If baud rate > 1200, use 24 or ws_row
255
 * Width is either 80 or ws_col;
256
 */
257
void
258
setscreensize(void)
259
{
260
4
	struct termios tbuf;
261
2
	struct winsize ws;
262
	speed_t ospeed;
263
264
2
	if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
265
2
		ws.ws_col = ws.ws_row = 0;
266
2
	if (tcgetattr(1, &tbuf) < 0)
267
2
		ospeed = 9600;
268
	else
269
		ospeed = cfgetospeed(&tbuf);
270
2
	if (ospeed < B1200)
271
		screenheight = 9;
272
2
	else if (ospeed == B1200)
273
		screenheight = 14;
274
2
	else if (ws.ws_row != 0)
275
		screenheight = ws.ws_row;
276
	else
277
		screenheight = 24;
278
2
	if ((realscreenheight = ws.ws_row) == 0)
279
2
		realscreenheight = 24;
280
2
	if ((screenwidth = ws.ws_col) == 0)
281
2
		screenwidth = 80;
282
2
}
283
284
__dead void
285
usage(void)
286
{
287
288
	fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] "
289
	    "[-r from-addr] [-s subject] to-addr ...\n", __progname);
290
	fprintf(stderr, "       %s [-dEIiNnv] -f [file]\n", __progname);
291
	fprintf(stderr, "       %s [-dEIiNnv] [-u user]\n", __progname);
292
	exit(1);
293
}