1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #include "rcv.h" 41 #ifndef preSVr4 42 #include <locale.h> 43 #endif 44 45 /* 46 * mailx -- a modified version of a University of California at Berkeley 47 * mail program 48 * 49 * Startup -- interface with user. 50 */ 51 52 static void hdrstop(int); 53 54 static jmp_buf hdrjmp; 55 56 const char *const version = "mailx version 5.0"; 57 58 /* 59 * Find out who the user is, copy his mail file (if exists) into 60 * /tmp/Rxxxxx and set up the message pointers. Then, print out the 61 * message headers and read user commands. 62 * 63 * Command line syntax: 64 * mailx [ -i ] [ -r address ] [ -h number ] [ -f [ name ] ] 65 * or: 66 * mailx [ -i ] [ -r address ] [ -h number ] people ... 67 * 68 * and a bunch of other options. 69 */ 70 71 int 72 main(int argc, char **argv) 73 { 74 register char *ef; 75 register int argp; 76 int mustsend, f, goerr = 0; 77 void (*prevint)(int); 78 int loaded = 0; 79 struct termio tbuf; 80 struct termios tbufs; 81 int c; 82 char *cwd, *mf; 83 84 /* 85 * Set up a reasonable environment. 86 * Figure out whether we are being run interactively, set up 87 * all the temporary files, buffer standard output, and so forth. 88 */ 89 90 #ifndef preSVr4 91 (void)setlocale(LC_ALL, ""); 92 #endif 93 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 94 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 95 #endif 96 (void) textdomain(TEXT_DOMAIN); 97 98 #ifdef SIGCONT 99 sigset(SIGCONT, SIG_DFL); 100 #endif 101 rpterr = 0; /* initialize; set when we output to stderr */ 102 progname = argv[0]; 103 if (progname[strlen(progname) - 1] != 'x') { 104 assign("bsdcompat", ""); 105 } 106 myegid = getegid(); 107 myrgid = getgid(); 108 myeuid = geteuid(); 109 myruid = getuid(); 110 mypid = getpid(); 111 setgid(myrgid); 112 setuid(myruid); 113 inithost(); 114 intty = isatty(0); 115 if (ioctl(1, TCGETS, &tbufs) < 0) { 116 if (ioctl(1, TCGETA, &tbuf)==0) { 117 outtty = 1; 118 baud = tbuf.c_cflag & CBAUD; 119 } else 120 baud = B9600; 121 } else { 122 outtty = 1; 123 baud = cfgetospeed(&tbufs); 124 } 125 image = -1; 126 127 /* 128 * Now, determine how we are being used. 129 * We successively pick off instances of -r, -h, -f, and -i. 130 * If called as "rmail" we note this fact for letter sending. 131 * If there is anything left, it is the base of the list 132 * of users to mail to. Argp will be set to point to the 133 * first of these users. 134 */ 135 136 ef = NOSTR; 137 argp = -1; 138 mustsend = 0; 139 if (argc > 0 && **argv == 'r') 140 rmail++; 141 while ((c = getopt(argc, argv, "b:Bc:defFh:HiInNr:s:u:UtT:vV~")) != EOF) 142 switch (c) { 143 case 'e': 144 /* 145 * exit status only 146 */ 147 exitflg++; 148 break; 149 150 case 'r': 151 /* 152 * Next argument is address to be sent along 153 * to the mailer. 154 */ 155 mustsend++; 156 rflag = optarg; 157 break; 158 159 case 'T': 160 /* 161 * Next argument is temp file to write which 162 * articles have been read/deleted for netnews. 163 */ 164 Tflag = optarg; 165 if ((f = creat(Tflag, TEMPPERM)) < 0) { 166 perror(Tflag); 167 exit(1); 168 } 169 close(f); 170 /* fall through for -I too */ 171 /* FALLTHROUGH */ 172 173 case 'I': 174 /* 175 * print newsgroup in header summary 176 */ 177 newsflg++; 178 break; 179 180 case 'u': 181 /* 182 * Next argument is person's mailbox to use. 183 * Treated the same as "-f /var/mail/user". 184 */ 185 { 186 static char u[PATHSIZE]; 187 snprintf(u, sizeof (u), "%s%s", maildir, optarg); 188 ef = u; 189 break; 190 } 191 192 case 'i': 193 /* 194 * User wants to ignore interrupts. 195 * Set the variable "ignore" 196 */ 197 assign("ignore", ""); 198 break; 199 200 case 'U': 201 UnUUCP++; 202 break; 203 204 case 'd': 205 assign("debug", ""); 206 break; 207 208 case 'h': 209 /* 210 * Specified sequence number for network. 211 * This is the number of "hops" made so 212 * far (count of times message has been 213 * forwarded) to help avoid infinite mail loops. 214 */ 215 mustsend++; 216 hflag = atoi(optarg); 217 if (hflag == 0) { 218 fprintf(stderr, 219 gettext("-h needs non-zero number\n")); 220 goerr++; 221 } 222 break; 223 224 case 's': 225 /* 226 * Give a subject field for sending from 227 * non terminal 228 */ 229 mustsend++; 230 sflag = optarg; 231 break; 232 233 case 'c': /* Cc: from command line */ 234 mustsend++; 235 cflag = optarg; 236 break; 237 238 case 'b': /* Bcc: from command line */ 239 mustsend++; 240 bflag = optarg; 241 break; 242 243 case 'f': 244 /* 245 * User is specifying file to "edit" with mailx, 246 * as opposed to reading system mailbox. 247 * If no argument is given after -f, we read his/her 248 * $MBOX file or mbox in his/her home directory. 249 */ 250 ef = (argc == optind || *argv[optind] == '-') 251 ? "" : argv[optind++]; 252 if (*ef && *ef != '/' && *ef != '+') 253 cwd = getcwd(NOSTR, PATHSIZE); 254 break; 255 256 case 'F': 257 Fflag++; 258 mustsend++; 259 break; 260 261 case 'n': 262 /* 263 * User doesn't want to source 264 * /etc/mail/mailx.rc 265 */ 266 nosrc++; 267 break; 268 269 case 'N': 270 /* 271 * Avoid initial header printing. 272 */ 273 noheader++; 274 break; 275 276 case 'H': 277 /* 278 * Print headers and exit 279 */ 280 Hflag++; 281 break; 282 283 case 'V': 284 puts(version); 285 return 0; 286 287 case '~': 288 /* 289 * Permit tildas no matter where 290 * the input is coming from. 291 */ 292 assign("escapeok", ""); 293 break; 294 295 case 'v': 296 /* 297 * Send mailer verbose flag 298 */ 299 assign("verbose", ""); 300 break; 301 302 case 'B': 303 /* 304 * Don't buffer output 305 * (Line buffered is good enough) 306 */ 307 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 308 setvbuf(stderr, NULL, _IOLBF, BUFSIZ); 309 break; 310 311 case 't': 312 /* 313 * Like sendmail -t, read headers from text 314 */ 315 tflag++; 316 mustsend++; 317 break; 318 319 case '?': 320 default: 321 goerr++; 322 break; 323 } 324 325 if (optind != argc) 326 argp = optind; 327 328 /* 329 * Check for inconsistent arguments. 330 */ 331 332 if (newsflg && ef==NOSTR) { 333 fprintf(stderr, gettext("Need -f with -I flag\n")); 334 goerr++; 335 } 336 if (ef != NOSTR && argp != -1) { 337 fprintf(stderr, 338 gettext("Cannot give -f and people to send to.\n")); 339 goerr++; 340 } 341 if (exitflg && (mustsend || argp != -1)) 342 exit(1); /* nonsense flags involving -e simply exit */ 343 if (tflag && argp != -1) { 344 fprintf(stderr, 345 gettext("Ignoring recipients on command line with -t\n")); 346 argp = -1; 347 } else if (!tflag && mustsend && argp == -1) { 348 fprintf(stderr, 349 gettext("The flags you gave are used only when sending mail.\n")); 350 goerr++; 351 } 352 if (goerr) { 353 fprintf(stderr, 354 gettext("Usage: %s -eiIUdFntBNHvV~ -T FILE -u USER -h hops -r address\n"), 355 progname); 356 fprintf(stderr, 357 gettext("\t\t-s SUBJECT -f FILE users\n")); 358 exit(1); 359 } 360 tinit(); 361 input = stdin; 362 rcvmode = !tflag && argp == -1; 363 if (!nosrc) 364 load(MASTER); 365 366 if (!rcvmode) { 367 load(Getf("MAILRC")); 368 if (tflag) 369 tmail(); 370 else 371 mail(&argv[argp]); 372 exit(senderr ? senderr : rpterr); 373 } 374 375 /* 376 * Ok, we are reading mail. 377 * Decide whether we are editing a mailbox or reading 378 * the system mailbox, and open up the right stuff. 379 * 380 * Do this before sourcing the MAILRC, because there might be 381 * a 'chdir' there that breaks the -f option. But if the 382 * file specified with -f is a folder name, go ahead and 383 * source the MAILRC anyway so that "folder" will be defined. 384 */ 385 386 nstrcpy(origname, PATHSIZE, mailname); 387 editfile = mailname; 388 389 if (ef != NOSTR) { 390 if (ef == NOSTR || *ef == '\0' || *ef == '+') { 391 load(Getf("MAILRC")); 392 loaded++; 393 } 394 ef = *ef ? safeexpand(ef) : Getf("MBOX"); 395 nstrcpy(origname, PATHSIZE, ef); 396 if (ef[0] != '/') { 397 if (cwd == NOSTR) 398 cwd = getcwd(NOSTR, PATHSIZE); 399 nstrcat(cwd, PATHSIZE, "/"); 400 nstrcat(cwd, PATHSIZE, ef); 401 ef = cwd; 402 } 403 editfile = ef; 404 edit++; 405 } 406 407 if (setfile(editfile, edit) < 0) 408 exit(1); 409 410 if (!loaded) 411 load(Getf("MAILRC")); 412 if (msgCount > 0 && !noheader && value("header") != NOSTR) { 413 if (setjmp(hdrjmp) == 0) { 414 if ((prevint = sigset(SIGINT, SIG_IGN)) != SIG_IGN) 415 sigset(SIGINT, hdrstop); 416 announce(); 417 fflush(stdout); 418 sigset(SIGINT, prevint); 419 } 420 } 421 if (Hflag || (!edit && msgCount == 0)) { 422 if (!Hflag) { 423 fprintf(stderr, gettext("No mail for %s\n"), myname); 424 Verhogen(); 425 } 426 fflush(stdout); 427 exit(rpterr); 428 } 429 commands(); 430 sigset(SIGHUP, SIG_IGN); 431 sigset(SIGINT, SIG_IGN); 432 sigset(SIGQUIT, SIG_IGN); 433 if (!outtty) 434 sigset(SIGPIPE, SIG_IGN); 435 if (edit) 436 edstop(0); 437 else { 438 quit(0); 439 Verhogen(); 440 } 441 return (rpterr); 442 } 443 444 /* 445 * Interrupt printing of the headers. 446 */ 447 static void 448 #ifdef __cplusplus 449 hdrstop(int) 450 #else 451 /* ARGSUSED */ 452 hdrstop(int s) 453 #endif 454 { 455 456 fflush(stdout); 457 fprintf(stderr, gettext("\nInterrupt\n")); 458 # ifdef OLD_BSD_SIGS 459 sigrelse(SIGINT); 460 # endif 461 longjmp(hdrjmp, 1); 462 } 463