1 /* $OpenBSD: main.c,v 1.23 2009/10/27 23:59:40 deraadt Exp $ */ 2 /* $NetBSD: main.c,v 1.7 1997/05/13 06:15:57 mikel Exp $ */ 3 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. Neither the name of the University nor the names of its contributors 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> 35 #include <sys/ioctl.h> 36 #include "extern.h" 37 38 __dead void usage(void); 39 int main(int, char **); 40 41 /* 42 * Mail -- a mail program 43 * 44 * Startup -- interface with user. 45 */ 46 47 int 48 main(int argc, char **argv) 49 { 50 int i; 51 struct name *to, *cc, *bcc, *smopts; 52 char *subject; 53 char *ef; 54 char nosrc = 0; 55 char *rc; 56 extern const char version[]; 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 */ 63 (void)signal(SIGCHLD, sigchild); 64 (void)signal(SIGPIPE, SIG_IGN); 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 */ 75 ef = NULL; 76 to = NULL; 77 cc = NULL; 78 bcc = NULL; 79 smopts = NULL; 80 subject = NULL; 81 while ((i = getopt(argc, argv, "EINT:b:c:dfins:u:v")) != -1) { 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; 89 if ((i = creat(Tflag, 0600)) < 0) 90 err(1, "%s", Tflag); 91 (void)close(i); 92 break; 93 case 'u': 94 /* 95 * Next argument is person to pretend to be. 96 */ 97 if (strlen(optarg) >= MAXLOGNAME) 98 errx(1, "username `%s' too long", optarg); 99 unsetenv("MAIL"); 100 myname = optarg; 101 uflag = 1; 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; 171 case 'E': 172 /* 173 * Don't send messages with an empty body. 174 */ 175 assign("skipempty", ""); 176 break; 177 default: 178 usage(); 179 /*NOTREACHED*/ 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 */ 189 if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL)) 190 errx(1, "You must specify direct recipients with -s, -c, or -b"); 191 if (ef != NULL && to != NULL) 192 errx(1, "Cannot give -f and people to send to"); 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 */ 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 */ 213 if ((rc = getenv("MAILRC")) == 0) 214 rc = "~/.mailrc"; 215 load(expand(rc)); 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 */ 228 if (ef == NULL) 229 ef = "%"; 230 if (setfile(ef) < 0) 231 exit(1); /* error already reported */ 232 233 if (value("quiet") == NULL) 234 (void)printf("Mail version %s. Type ? for help.\n", 235 version); 236 announce(); 237 (void)fflush(stdout); 238 commands(); 239 (void)ignoresig(SIGHUP, NULL, NULL); 240 (void)ignoresig(SIGINT, NULL, NULL); 241 (void)ignoresig(SIGQUIT, NULL, NULL); 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 255 setscreensize(void) 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); 267 if (ospeed < B1200) 268 screenheight = 9; 269 else if (ospeed == B1200) 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; 279 } 280 281 __dead void 282 usage(void) 283 { 284 285 fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] " 286 "[-s subject] to-addr ...\n", __progname); 287 fprintf(stderr, " %*s [-sendmail-options ...]\n", 288 (int)strlen(__progname), ""); 289 fprintf(stderr, " %s [-dEIiNnv] -f [file]\n", __progname); 290 fprintf(stderr, " %s [-dEIiNnv] [-u user]\n", __progname); 291 exit(1); 292 } 293