Annotation of src/usr.bin/mail/main.c, Revision 1.16
1.16 ! millert 1: /* $OpenBSD: main.c,v 1.15 2001/11/20 20:50:00 millert 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.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.16 ! millert 38: static const char copyright[] =
1.1 deraadt 39: "@(#) Copyright (c) 1980, 1993\n\
40: The Regents of the University of California. All rights reserved.\n";
41: #endif /* not lint */
42:
43: #ifndef lint
1.2 deraadt 44: #if 0
1.16 ! millert 45: static const char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95";
1.2 deraadt 46: #else
1.16 ! millert 47: static const char rcsid[] = "$OpenBSD: main.c,v 1.15 2001/11/20 20:50:00 millert Exp $";
1.2 deraadt 48: #endif
1.1 deraadt 49: #endif /* not lint */
50:
51: #include "rcv.h"
52: #include <fcntl.h>
1.2 deraadt 53: #include <sys/ioctl.h>
1.1 deraadt 54: #include "extern.h"
55:
1.16 ! millert 56: __dead void usage(void);
! 57: int main(int, char **);
1.10 millert 58:
1.1 deraadt 59: /*
60: * Mail -- a mail program
61: *
62: * Startup -- interface with user.
63: */
64:
65: int
1.16 ! millert 66: main(int argc, char **argv)
1.1 deraadt 67: {
1.10 millert 68: int i;
1.1 deraadt 69: struct name *to, *cc, *bcc, *smopts;
70: char *subject;
71: char *ef;
72: char nosrc = 0;
1.5 millert 73: char *rc;
1.15 millert 74: extern char *version;
1.1 deraadt 75:
76: /*
77: * Set up a reasonable environment.
78: * Figure out whether we are being run interactively,
79: * start the SIGCHLD catcher, and so forth.
80: */
1.6 millert 81: (void)signal(SIGCHLD, sigchild);
1.15 millert 82: (void)signal(SIGPIPE, SIG_IGN);
1.1 deraadt 83: if (isatty(0))
84: assign("interactive", "");
85: image = -1;
86: /*
87: * Now, determine how we are being used.
88: * We successively pick off - flags.
89: * If there is anything left, it is the base of the list
90: * of users to mail to. Argp will be set to point to the
91: * first of these users.
92: */
1.7 millert 93: ef = NULL;
1.16 ! millert 94: to = NULL;
! 95: cc = NULL;
! 96: bcc = NULL;
! 97: smopts = NULL;
1.7 millert 98: subject = NULL;
1.4 millert 99: while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != -1) {
1.1 deraadt 100: switch (i) {
101: case 'T':
102: /*
103: * Next argument is temp file to write which
104: * articles have been read/deleted for netnews.
105: */
106: Tflag = optarg;
1.5 millert 107: if ((i = creat(Tflag, 0600)) < 0)
1.12 millert 108: err(1, "%s", Tflag);
1.5 millert 109: (void)close(i);
1.1 deraadt 110: break;
111: case 'u':
112: /*
113: * Next argument is person to pretend to be.
114: */
1.13 millert 115: if (strlen(optarg) >= MAXLOGNAME)
1.14 millert 116: errx(1, "username `%s' too long", optarg);
1.3 deraadt 117: unsetenv("MAIL");
1.1 deraadt 118: myname = optarg;
1.11 millert 119: uflag = 1;
1.1 deraadt 120: break;
121: case 'i':
122: /*
123: * User wants to ignore interrupts.
124: * Set the variable "ignore"
125: */
126: assign("ignore", "");
127: break;
128: case 'd':
129: debug++;
130: break;
131: case 's':
132: /*
133: * Give a subject field for sending from
134: * non terminal
135: */
136: subject = optarg;
137: break;
138: case 'f':
139: /*
140: * User is specifying file to "edit" with Mail,
141: * as opposed to reading system mailbox.
142: * If no argument is given after -f, we read his
143: * mbox file.
144: *
145: * getopt() can't handle optional arguments, so here
146: * is an ugly hack to get around it.
147: */
148: if ((argv[optind]) && (argv[optind][0] != '-'))
149: ef = argv[optind++];
150: else
151: ef = "&";
152: break;
153: case 'n':
154: /*
155: * User doesn't want to source /usr/lib/Mail.rc
156: */
157: nosrc++;
158: break;
159: case 'N':
160: /*
161: * Avoid initial header printing.
162: */
163: assign("noheader", "");
164: break;
165: case 'v':
166: /*
167: * Send mailer verbose flag
168: */
169: assign("verbose", "");
170: break;
171: case 'I':
172: /*
173: * We're interactive
174: */
175: assign("interactive", "");
176: break;
177: case 'c':
178: /*
179: * Get Carbon Copy Recipient list
180: */
181: cc = cat(cc, nalloc(optarg, GCC));
182: break;
183: case 'b':
184: /*
185: * Get Blind Carbon Copy Recipient list
186: */
187: bcc = cat(bcc, nalloc(optarg, GBCC));
188: break;
1.15 millert 189: default:
190: usage();
191: /*NOTREACHED*/
1.1 deraadt 192: }
193: }
194: for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
195: to = cat(to, nalloc(argv[i], GTO));
196: for (; argv[i]; i++)
197: smopts = cat(smopts, nalloc(argv[i], 0));
198: /*
199: * Check for inconsistent arguments.
200: */
1.16 ! millert 201: if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL))
1.5 millert 202: errx(1, "You must specify direct recipients with -s, -c, or -b");
1.16 ! millert 203: if (ef != NULL && to != NULL)
1.5 millert 204: errx(1, "Cannot give -f and people to send to");
1.15 millert 205: /*
206: * Block SIGINT except where we install an explicit handler for it.
207: */
208: sigemptyset(&intset);
209: sigaddset(&intset, SIGINT);
210: (void)sigprocmask(SIG_BLOCK, &intset, NULL);
211: /*
212: * Initialization.
213: */
1.1 deraadt 214: tinit();
215: setscreensize();
216: input = stdin;
217: rcvmode = !to;
218: spreserve();
219: if (!nosrc)
220: load(_PATH_MASTER_RC);
221: /*
222: * Expand returns a savestr, but load only uses the file name
223: * for fopen, so it's safe to do this.
224: */
1.5 millert 225: if ((rc = getenv("MAILRC")) == 0)
226: rc = "~/.mailrc";
227: load(expand(rc));
1.1 deraadt 228: if (!rcvmode) {
229: mail(to, cc, bcc, smopts, subject);
230: /*
231: * why wait?
232: */
233: exit(senderr);
234: }
235: /*
236: * Ok, we are reading mail.
237: * Decide whether we are editing a mailbox or reading
238: * the system mailbox, and open up the right stuff.
239: */
1.7 millert 240: if (ef == NULL)
1.1 deraadt 241: ef = "%";
242: if (setfile(ef) < 0)
243: exit(1); /* error already reported */
244:
1.15 millert 245: if (value("quiet") == NULL)
246: (void)printf("Mail version %s. Type ? for help.\n",
247: version);
248: announce();
249: (void)fflush(stdout);
1.1 deraadt 250: commands();
1.15 millert 251: (void)ignoresig(SIGHUP, NULL, NULL);
252: (void)ignoresig(SIGINT, NULL, NULL);
253: (void)ignoresig(SIGQUIT, NULL, NULL);
1.1 deraadt 254: quit();
255: exit(0);
256: }
257:
258: /*
259: * Compute what the screen size for printing headers should be.
260: * We use the following algorithm for the height:
261: * If baud rate < 1200, use 9
262: * If baud rate = 1200, use 14
263: * If baud rate > 1200, use 24 or ws_row
264: * Width is either 80 or ws_col;
265: */
266: void
1.16 ! millert 267: setscreensize(void)
1.1 deraadt 268: {
269: struct termios tbuf;
270: struct winsize ws;
271: speed_t ospeed;
272:
273: if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)
274: ws.ws_col = ws.ws_row = 0;
275: if (tcgetattr(1, &tbuf) < 0)
276: ospeed = 9600;
277: else
278: ospeed = cfgetospeed(&tbuf);
1.8 millert 279: if (ospeed < B1200)
1.1 deraadt 280: screenheight = 9;
1.8 millert 281: else if (ospeed == B1200)
1.1 deraadt 282: screenheight = 14;
283: else if (ws.ws_row != 0)
284: screenheight = ws.ws_row;
285: else
286: screenheight = 24;
287: if ((realscreenheight = ws.ws_row) == 0)
288: realscreenheight = 24;
289: if ((screenwidth = ws.ws_col) == 0)
290: screenwidth = 80;
1.15 millert 291: }
292:
293: __dead void
1.16 ! millert 294: usage(void)
1.15 millert 295: {
296:
297: fprintf(stderr, "usage: %s [-iInv] [-s subject] [-c cc-addr] "
298: "[-b bcc-addr] to-addr ...\n", __progname);
299: fprintf(stderr, " %*s [- sendmail-options ...]\n",
300: (int)strlen(__progname), "");
301: fprintf(stderr, " %s [-iInNv] -f [name]\n", __progname);
302: fprintf(stderr, " %s [-iInNv] [-u user]\n", __progname);
303: exit(1);
1.1 deraadt 304: }