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