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