Annotation of src/usr.bin/mail/main.c, Revision 1.23
1.23 ! deraadt 1: /* $OpenBSD: main.c,v 1.22 2008/10/09 06:48:11 jmc 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;
52: char *subject;
53: char *ef;
54: char nosrc = 0;
1.5 millert 55: char *rc;
1.17 millert 56: extern const char version[];
1.1 deraadt 57:
58: /*
59: * Set up a reasonable environment.
60: * Figure out whether we are being run interactively,
61: * start the SIGCHLD catcher, and so forth.
62: */
1.6 millert 63: (void)signal(SIGCHLD, sigchild);
1.15 millert 64: (void)signal(SIGPIPE, SIG_IGN);
1.1 deraadt 65: if (isatty(0))
66: assign("interactive", "");
67: image = -1;
68: /*
69: * Now, determine how we are being used.
70: * We successively pick off - flags.
71: * If there is anything left, it is the base of the list
72: * of users to mail to. Argp will be set to point to the
73: * first of these users.
74: */
1.7 millert 75: ef = NULL;
1.16 millert 76: to = NULL;
77: cc = NULL;
78: bcc = NULL;
79: smopts = NULL;
1.7 millert 80: subject = NULL;
1.21 martynas 81: while ((i = getopt(argc, argv, "EINT:b:c:dfins:u:v")) != -1) {
1.1 deraadt 82: switch (i) {
83: case 'T':
84: /*
85: * Next argument is temp file to write which
86: * articles have been read/deleted for netnews.
87: */
88: Tflag = optarg;
1.5 millert 89: if ((i = creat(Tflag, 0600)) < 0)
1.12 millert 90: err(1, "%s", Tflag);
1.5 millert 91: (void)close(i);
1.1 deraadt 92: break;
93: case 'u':
94: /*
95: * Next argument is person to pretend to be.
96: */
1.13 millert 97: if (strlen(optarg) >= MAXLOGNAME)
1.14 millert 98: errx(1, "username `%s' too long", optarg);
1.3 deraadt 99: unsetenv("MAIL");
1.1 deraadt 100: myname = optarg;
1.11 millert 101: uflag = 1;
1.1 deraadt 102: break;
103: case 'i':
104: /*
105: * User wants to ignore interrupts.
106: * Set the variable "ignore"
107: */
108: assign("ignore", "");
109: break;
110: case 'd':
111: debug++;
112: break;
113: case 's':
114: /*
115: * Give a subject field for sending from
116: * non terminal
117: */
118: subject = optarg;
119: break;
120: case 'f':
121: /*
122: * User is specifying file to "edit" with Mail,
123: * as opposed to reading system mailbox.
124: * If no argument is given after -f, we read his
125: * mbox file.
126: *
127: * getopt() can't handle optional arguments, so here
128: * is an ugly hack to get around it.
129: */
130: if ((argv[optind]) && (argv[optind][0] != '-'))
131: ef = argv[optind++];
132: else
133: ef = "&";
134: break;
135: case 'n':
136: /*
137: * User doesn't want to source /usr/lib/Mail.rc
138: */
139: nosrc++;
140: break;
141: case 'N':
142: /*
143: * Avoid initial header printing.
144: */
145: assign("noheader", "");
146: break;
147: case 'v':
148: /*
149: * Send mailer verbose flag
150: */
151: assign("verbose", "");
152: break;
153: case 'I':
154: /*
155: * We're interactive
156: */
157: assign("interactive", "");
158: break;
159: case 'c':
160: /*
161: * Get Carbon Copy Recipient list
162: */
163: cc = cat(cc, nalloc(optarg, GCC));
164: break;
165: case 'b':
166: /*
167: * Get Blind Carbon Copy Recipient list
168: */
169: bcc = cat(bcc, nalloc(optarg, GBCC));
170: break;
1.21 martynas 171: case 'E':
172: /*
173: * Don't send messages with an empty body.
174: */
175: assign("skipempty", "");
176: break;
1.15 millert 177: default:
178: usage();
179: /*NOTREACHED*/
1.1 deraadt 180: }
181: }
182: for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
183: to = cat(to, nalloc(argv[i], GTO));
184: for (; argv[i]; i++)
185: smopts = cat(smopts, nalloc(argv[i], 0));
186: /*
187: * Check for inconsistent arguments.
188: */
1.16 millert 189: if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL))
1.5 millert 190: errx(1, "You must specify direct recipients with -s, -c, or -b");
1.16 millert 191: if (ef != NULL && to != NULL)
1.5 millert 192: errx(1, "Cannot give -f and people to send to");
1.15 millert 193: /*
194: * Block SIGINT except where we install an explicit handler for it.
195: */
196: sigemptyset(&intset);
197: sigaddset(&intset, SIGINT);
198: (void)sigprocmask(SIG_BLOCK, &intset, NULL);
199: /*
200: * Initialization.
201: */
1.1 deraadt 202: tinit();
203: setscreensize();
204: input = stdin;
205: rcvmode = !to;
206: spreserve();
207: if (!nosrc)
208: load(_PATH_MASTER_RC);
209: /*
210: * Expand returns a savestr, but load only uses the file name
211: * for fopen, so it's safe to do this.
212: */
1.5 millert 213: if ((rc = getenv("MAILRC")) == 0)
214: rc = "~/.mailrc";
215: load(expand(rc));
1.1 deraadt 216: if (!rcvmode) {
217: mail(to, cc, bcc, smopts, subject);
218: /*
219: * why wait?
220: */
221: exit(senderr);
222: }
223: /*
224: * Ok, we are reading mail.
225: * Decide whether we are editing a mailbox or reading
226: * the system mailbox, and open up the right stuff.
227: */
1.7 millert 228: if (ef == NULL)
1.1 deraadt 229: ef = "%";
230: if (setfile(ef) < 0)
231: exit(1); /* error already reported */
232:
1.15 millert 233: if (value("quiet") == NULL)
234: (void)printf("Mail version %s. Type ? for help.\n",
235: version);
236: announce();
237: (void)fflush(stdout);
1.1 deraadt 238: commands();
1.15 millert 239: (void)ignoresig(SIGHUP, NULL, NULL);
240: (void)ignoresig(SIGINT, NULL, NULL);
241: (void)ignoresig(SIGQUIT, NULL, NULL);
1.1 deraadt 242: quit();
243: exit(0);
244: }
245:
246: /*
247: * Compute what the screen size for printing headers should be.
248: * We use the following algorithm for the height:
249: * If baud rate < 1200, use 9
250: * If baud rate = 1200, use 14
251: * If baud rate > 1200, use 24 or ws_row
252: * Width is either 80 or ws_col;
253: */
254: void
1.16 millert 255: setscreensize(void)
1.1 deraadt 256: {
257: struct termios tbuf;
258: struct winsize ws;
259: speed_t ospeed;
260:
261: if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
262: ws.ws_col = ws.ws_row = 0;
263: if (tcgetattr(1, &tbuf) < 0)
264: ospeed = 9600;
265: else
266: ospeed = cfgetospeed(&tbuf);
1.8 millert 267: if (ospeed < B1200)
1.1 deraadt 268: screenheight = 9;
1.8 millert 269: else if (ospeed == B1200)
1.1 deraadt 270: screenheight = 14;
271: else if (ws.ws_row != 0)
272: screenheight = ws.ws_row;
273: else
274: screenheight = 24;
275: if ((realscreenheight = ws.ws_row) == 0)
276: realscreenheight = 24;
277: if ((screenwidth = ws.ws_col) == 0)
278: screenwidth = 80;
1.15 millert 279: }
280:
281: __dead void
1.16 millert 282: usage(void)
1.15 millert 283: {
284:
1.22 jmc 285: fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] "
1.20 sobrado 286: "[-s subject] to-addr ...\n", __progname);
287: fprintf(stderr, " %*s [-sendmail-options ...]\n",
1.15 millert 288: (int)strlen(__progname), "");
1.22 jmc 289: fprintf(stderr, " %s [-dEIiNnv] -f [file]\n", __progname);
290: fprintf(stderr, " %s [-dEIiNnv] [-u user]\n", __progname);
1.15 millert 291: exit(1);
1.1 deraadt 292: }