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