Annotation of src/usr.bin/mail/main.c, Revision 1.33
1.33 ! deraadt 1: /* $OpenBSD: main.c,v 1.32 2015/11/16 21:20:40 deraadt Exp $ */
1.5 millert 2: /* $NetBSD: main.c,v 1.7 1997/05/13 06:15:57 mikel Exp $ */
1.2 deraadt 3:
1.1 deraadt 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.
1.18 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 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>
1.2 deraadt 35: #include <sys/ioctl.h>
1.1 deraadt 36: #include "extern.h"
37:
1.16 millert 38: __dead void usage(void);
39: int main(int, char **);
1.10 millert 40:
1.1 deraadt 41: /*
42: * Mail -- a mail program
43: *
44: * Startup -- interface with user.
45: */
46:
47: int
1.16 millert 48: main(int argc, char **argv)
1.1 deraadt 49: {
1.10 millert 50: int i;
1.1 deraadt 51: struct name *to, *cc, *bcc, *smopts;
1.28 millert 52: char *fromaddr;
1.1 deraadt 53: char *subject;
54: char *ef;
55: char nosrc = 0;
1.5 millert 56: char *rc;
1.17 millert 57: extern const char version[];
1.32 deraadt 58:
1.33 ! deraadt 59: if (pledge("stdio rpath wpath cpath getpw tmppath fattr tty flock proc exec",
1.32 deraadt 60: NULL) == -1)
61: err(1, "pledge");
1.1 deraadt 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: */
1.6 millert 68: (void)signal(SIGCHLD, sigchild);
1.15 millert 69: (void)signal(SIGPIPE, SIG_IGN);
1.1 deraadt 70: if (isatty(0))
71: assign("interactive", "");
72: 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: */
1.7 millert 80: ef = NULL;
1.16 millert 81: to = NULL;
82: cc = NULL;
83: bcc = NULL;
84: smopts = NULL;
1.28 millert 85: fromaddr = NULL;
1.7 millert 86: subject = NULL;
1.30 millert 87: while ((i = getopt(argc, argv, "EINb:c:dfinr:s:u:v")) != -1) {
1.1 deraadt 88: switch (i) {
89: case 'u':
90: /*
91: * Next argument is person to pretend to be.
92: */
1.27 deraadt 93: if (strlen(optarg) >= LOGIN_NAME_MAX)
1.14 millert 94: errx(1, "username `%s' too long", optarg);
1.3 deraadt 95: unsetenv("MAIL");
1.1 deraadt 96: myname = optarg;
1.11 millert 97: uflag = 1;
1.1 deraadt 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;
1.28 millert 109: case 'r':
110: /*
111: * Set From: address
112: */
113: fromaddr = optarg;
114: break;
1.1 deraadt 115: case 's':
116: /*
117: * Give a subject field for sending from
118: * non terminal
119: */
120: subject = optarg;
121: break;
122: case 'f':
123: /*
124: * User is specifying file to "edit" with Mail,
125: * as opposed to reading system mailbox.
1.25 millert 126: * We read his mbox file unless another file
127: * is specified after the arguments.
128: */
129: ef = "&";
1.1 deraadt 130: break;
131: case 'n':
132: /*
133: * User doesn't want to source /usr/lib/Mail.rc
134: */
1.31 deraadt 135: nosrc = 1;
1.1 deraadt 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;
1.21 martynas 167: case 'E':
168: /*
169: * Don't send messages with an empty body.
170: */
171: assign("skipempty", "");
172: break;
1.15 millert 173: default:
174: usage();
175: /*NOTREACHED*/
1.1 deraadt 176: }
177: }
1.25 millert 178: 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 {
1.26 millert 186: for (i = optind; argv[i]; i++)
1.25 millert 187: to = cat(to, nalloc(argv[i], GTO));
188: }
1.1 deraadt 189: /*
190: * Check for inconsistent arguments.
191: */
1.29 millert 192: 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");
1.15 millert 196: /*
197: * Block SIGINT except where we install an explicit handler for it.
198: */
199: sigemptyset(&intset);
200: sigaddset(&intset, SIGINT);
201: (void)sigprocmask(SIG_BLOCK, &intset, NULL);
202: /*
203: * Initialization.
204: */
1.1 deraadt 205: tinit();
206: setscreensize();
207: input = stdin;
208: rcvmode = !to;
209: spreserve();
210: if (!nosrc)
211: 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: */
1.5 millert 216: if ((rc = getenv("MAILRC")) == 0)
217: rc = "~/.mailrc";
218: load(expand(rc));
1.1 deraadt 219: if (!rcvmode) {
1.28 millert 220: mail(to, cc, bcc, smopts, fromaddr, subject);
1.1 deraadt 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: */
1.7 millert 231: if (ef == NULL)
1.1 deraadt 232: ef = "%";
233: if (setfile(ef) < 0)
234: exit(1); /* error already reported */
235:
1.15 millert 236: if (value("quiet") == NULL)
237: (void)printf("Mail version %s. Type ? for help.\n",
238: version);
239: announce();
240: (void)fflush(stdout);
1.1 deraadt 241: commands();
1.15 millert 242: (void)ignoresig(SIGHUP, NULL, NULL);
243: (void)ignoresig(SIGINT, NULL, NULL);
244: (void)ignoresig(SIGQUIT, NULL, NULL);
1.1 deraadt 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
1.16 millert 258: setscreensize(void)
1.1 deraadt 259: {
260: struct termios tbuf;
261: struct winsize ws;
262: speed_t ospeed;
263:
264: if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
265: ws.ws_col = ws.ws_row = 0;
266: if (tcgetattr(1, &tbuf) < 0)
267: ospeed = 9600;
268: else
269: ospeed = cfgetospeed(&tbuf);
1.8 millert 270: if (ospeed < B1200)
1.1 deraadt 271: screenheight = 9;
1.8 millert 272: else if (ospeed == B1200)
1.1 deraadt 273: screenheight = 14;
274: else if (ws.ws_row != 0)
275: screenheight = ws.ws_row;
276: else
277: screenheight = 24;
278: if ((realscreenheight = ws.ws_row) == 0)
279: realscreenheight = 24;
280: if ((screenwidth = ws.ws_col) == 0)
281: screenwidth = 80;
1.15 millert 282: }
283:
284: __dead void
1.16 millert 285: usage(void)
1.15 millert 286: {
287:
1.22 jmc 288: fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] "
1.28 millert 289: "[-r from-addr] [-s subject] to-addr ...\n", __progname);
1.22 jmc 290: fprintf(stderr, " %s [-dEIiNnv] -f [file]\n", __progname);
291: fprintf(stderr, " %s [-dEIiNnv] [-u user]\n", __progname);
1.15 millert 292: exit(1);
1.1 deraadt 293: }