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