|
|
1.1 ! root 1: static char *rcsrev = "$Revision: 3.4 $"; ! 2: static char *rcshdr = ! 3: "$Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $"; ! 4: /* ! 5: * $Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $ ! 6: * $Log: /usr/local/src/dist/mail/usermail/RCS/mail.c,v $ ! 7: * Revision 3.4 91/02/18 17:14:10 piggy ! 8: * Fixed "q" command so that it works with a non-setuid mail. ! 9: * ! 10: * Revision 3.3 91/02/18 09:30:09 piggy ! 11: * Fixed two mishandlings of args[]. ! 12: * ! 13: * Revision 3.2 91/02/08 15:16:07 piggy ! 14: * Updated error messages to include malloc failures. ! 15: * ! 16: * Revision 3.1 91/02/08 14:34:28 piggy ! 17: * Made csplit non-destructive. ! 18: * ! 19: * Revision 3.0 91/02/07 15:19:14 piggy ! 20: * *** empty log message *** ! 21: * ! 22: * Revision 2.13 90/03/30 16:16:19 wgl ! 23: * Correct seek pointer work within readmail. ! 24: * ! 25: * Revision 2.12 90/03/12 14:19:08 wgl ! 26: * New version of send doing aliases in a different place. ! 27: * ! 28: * Revision 2.11 90/03/08 16:41:15 wgl ! 29: * Add code to get signature file. ! 30: * ! 31: * Revision 2.10 90/03/02 10:41:59 wgl ! 32: * Add the -a flag so that uucp does not look like it is coming from ! 33: * somewhere else. ! 34: * ! 35: * Revision 2.9 90/03/01 11:17:19 wgl ! 36: * Final conversion to rely soley on ^A^A as separators. ! 37: * Effectively delete concept of m_hsize. ! 38: * ! 39: * Revision 2.8 90/03/01 10:14:31 wgl ! 40: * Go buy separators, not "From_" lines. ! 41: * ! 42: * Revision 2.7 90/02/28 17:11:41 wgl ! 43: * Add version print, add some changes to the message-id field. ! 44: * ! 45: * Revision 2.6 90/02/28 16:42:09 wgl ! 46: * Version number fakeout. ! 47: * ! 48: * Revision 2.5 90/02/28 16:19:44 wgl ! 49: * Try again to get versioin number right. ! 50: * ! 51: * Revision 2.4 90/02/28 16:18:56 wgl ! 52: * Get version number right. ! 53: * ! 54: * Revision 2.3 90/02/28 16:04:59 wgl ! 55: * Many changes; ripped out send. ! 56: * Changes are to make it work with uucp and internet mail. ! 57: * ! 58: * Revision 1.6 89/02/22 05:34:00 bin ! 59: * Changes by rec to integrate with lauren's uumail. ! 60: * ! 61: * Revision 1.5 88/09/01 14:49:01 bin ! 62: * Source administration: Re-install declaration of getenv. ! 63: * It was inserted after epstein made his copy. ! 64: * ! 65: * Revision 1.4 88/09/01 14:44:49 bin ! 66: * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt ! 67: * handling during processing. ! 68: * ! 69: * Revision 1.3 88/09/01 14:27:41 bin ! 70: * declare getenv to get rid of integer pointer pun error message. ! 71: * ! 72: * Revision 1.2 88/09/01 11:02:23 bin ! 73: * Remove extra declaration of header which had rcs stuff in it. ! 74: * ! 75: * Revision 1.1 88/09/01 10:55:34 bin ! 76: * Initial revision ! 77: * ! 78: */ ! 79: /* ! 80: * The mail command. ! 81: * Coherent electronic postal system, user agent. ! 82: * With v3.0 this program no longer runs setuid. ! 83: * Modifications by rec january 1986 to include xmail. ! 84: * by epstein november 1987 to include CC: ! 85: * by epstein november 1987 to allow ^C exit to leave you in ! 86: * mail command processor ! 87: * by epstein november 1987 to substitute /usr/games/fortune ! 88: * for printing encrypted messages ! 89: * by rec february 1989 to tail to lauren weinstein's ! 90: * mail for alias expansion and uucp queuing. ! 91: * by wgl January 1990 to handle uucp mail more directly. ! 92: */ ! 93: ! 94: char isummary[] = "\ ! 95: \ ! 96: Command summary:\n\ ! 97: d Delete current message and print the next message\n\ ! 98: m [user ...] Mail current message to each named 'user'\n\ ! 99: p Print current message again\n\ ! 100: q Quit and update the mailbox\n\ ! 101: r Reverse direction of scan\n\ ! 102: s [file ...] Save message in each named 'file'\n\ ! 103: t [user ...] Mail standard input to each named 'user'\n\ ! 104: w [file ...] Save message in each named 'file' without its header\n\ ! 105: x Exit without updating mailbox\n\ ! 106: newline Print the next message\n\ ! 107: . Print current message again\n\ ! 108: + Print the next message\n\ ! 109: - Print the previous message\n\ ! 110: EOF Put undeleted mail back into mailbox and quit\n\ ! 111: ? Print this command summary\n\ ! 112: !command Pass 'command' to the shell to execute\n\ ! 113: If no 'file' is specified, 'mbox' in user's home directory is default.\n\ ! 114: If no 'user' is specified, the invoking user is default.\n\ ! 115: If the 'm', 'p', 't' commands are followed by an 'x',\n\ ! 116: then the public key cryptosystem is applied to the message.\n\ ! 117: \ ! 118: "; ! 119: ! 120: #include "mail.h" ! 121: ! 122: #define NARGS 64 /* Maximum # args to interactive command */ ! 123: ! 124: extern char *getenv(); ! 125: extern int optind; ! 126: extern char *optarg; ! 127: extern char getopt(); ! 128: extern char *malloc(); ! 129: int csplit(); ! 130: char *eat_ws(); ! 131: char *find_ws(); ! 132: char *revnop(); ! 133: ! 134: int mflag; /* `You have mail.' message to recipient */ ! 135: int rflag; /* Reverse order of print */ ! 136: int qflag; /* Exit after interrrupts */ ! 137: int pflag; /* Print mail */ ! 138: int verbflag; /* verbose */ ! 139: int callmexmail; /* Xmail modifier present */ ! 140: int callmermail; /* rmail modifier present */ ! 141: struct msg { ! 142: struct msg *m_next; /* Link to next message */ ! 143: struct msg *m_prev; /* Link to previous message */ ! 144: int m_flag; /* Flags - non-zero if deleted */ ! 145: int m_hsize; /* Size of header of message */ ! 146: fsize_t m_seek; /* Start position of message */ ! 147: fsize_t m_end; /* End of message */ ! 148: }; ! 149: struct msg *m_first = NULL; /* First message */ ! 150: struct msg *m_last = NULL; /* Last message */ ! 151: ! 152: struct tm *tp; ! 153: ! 154: char iusage[] = "Bad command--type '?' for command summary\n"; ! 155: char nombox[] = "No mailbox '%s'.\n"; ! 156: char nomail[] = "No mail.\n"; ! 157: char noperm[] = "Mailbox '%s' access denied.\n"; ! 158: char moerr[] = "Cannot open mailbox '%s'\n"; ! 159: char wrerr[] = "Write error on '%s'\n"; ! 160: char nosave[] = "Cannot save letter in '%s'\n"; ! 161: char allocerr[] = "%s: Can't malloc.\n"; ! 162: ! 163: FILE *mfp; /* Mailbox stream */ ! 164: int myuid; /* User-id of mail user */ ! 165: int mygid; /* Group-id of mail user */ ! 166: char myname[25]; /* User name */ ! 167: char myfullname[50]; ! 168: char mymbox[256]; /* $HOME/mbox */ ! 169: char mydead[256]; /* $HOME/dead.letter */ ! 170: char mysig[256]; /* $HOME/.sig.mail */ ! 171: char myalias[256]; /* $HOME/.aliases */ ! 172: char spoolname[50] = SPOOLDIR; ! 173: char *mailbox = spoolname; ! 174: char cmdname[1024]; /* Command for x{en,de}code filter */ ! 175: /* and for tail recursion to uumail */ ! 176: /* and for editor recursion */ ! 177: ! 178: char *args[NARGS]; /* Interactive command arglist */ ! 179: char msgline[NLINE]; ! 180: char cline[NCLINE] = "+\n"; ! 181: char *temp; /* Currently open temp file */ ! 182: char templ[] = "/tmp/mailXXXXXX"; /* Temp file name template */ ! 183: char *editname; /* name of editor */ ! 184: char *scatname; /* name of scat filter */ ! 185: char *askcc; /* Ask for CC: list? (YES/NO) */ ! 186: ! 187: fsize_t ftell(); ! 188: char *getlogin(); ! 189: char *mktemp(); ! 190: int catchintr(); ! 191: int catchpipe(); ! 192: char asuser [32]; ! 193: ! 194: main(argc, argv) ! 195: char *argv[]; ! 196: { ! 197: register char *ap; ! 198: char c, *foo; ! 199: int i; ! 200: ! 201: logopen(); ! 202: ! 203: /* Explicitly NULL out args. */ ! 204: for (i = 0; i < NARGS; ++i) { ! 205: args[i] = NULL; ! 206: } ! 207: ! 208: ap = argv[0]; ! 209: if ( (foo=rindex(ap, '/')) != NULL ) ! 210: ap = foo+1; ! 211: callmermail = (strcmp(ap, "rmail") == 0); ! 212: callmexmail = (strcmp(ap, "xmail") == 0); ! 213: ! 214: if (callmermail) ! 215: logdump("argv0 = rmail\n"); ! 216: ! 217: asuser [0] = '\0'; ! 218: signal(SIGINT, catchintr); ! 219: signal(SIGPIPE, catchpipe); ! 220: while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) { ! 221: switch(c) { ! 222: case 'f': ! 223: if (!callmermail) ! 224: mailbox = optarg; ! 225: break; ! 226: case 'a': ! 227: strcpy(asuser, optarg); ! 228: break; ! 229: case 'm': ! 230: mflag++; ! 231: break; ! 232: case 'p': ! 233: pflag++; ! 234: break; ! 235: case 'q': ! 236: qflag++; ! 237: break; ! 238: case 'r': ! 239: rflag++; ! 240: break; ! 241: case 'v': ! 242: fprintf(stderr, "mail, ver. %s\n", revnop()); ! 243: verbflag++; ! 244: break; ! 245: default: ! 246: usage(); ! 247: } ! 248: } ! 249: if (callmermail) ! 250: verbflag = mflag = pflag = rflag = 0; ! 251: setname(); ! 252: if (optind < argc) { ! 253: qflag = 1; ! 254: if ( send2(stdin, &argv[optind], (fsize_t)0, ! 255: (fsize_t)MAXLONG, 1) != 0 ) ! 256: rmexit(1); ! 257: } else { ! 258: if ( ! pflag) ! 259: callmexmail = 0; ! 260: commands(); ! 261: } ! 262: rmexit(0); ! 263: } ! 264: ! 265: /* ! 266: * Setup all the identities for the current user. ! 267: */ ! 268: setname() ! 269: { ! 270: register struct passwd *pwp; ! 271: register char *np; ! 272: extern struct passwd * getpwnam(); ! 273: ! 274: if (strlen(asuser) > 0) { ! 275: if((pwp = getpwnam(asuser)) == NULL) ! 276: merr("No such user %s.\n", asuser); ! 277: myuid = pwp -> pw_uid; ! 278: } else ! 279: myuid = getuid(); ! 280: if ((pwp = getpwuid(myuid)) == NULL) ! 281: merr("Who are you?\n"); ! 282: np = pwp->pw_name; ! 283: mygid = pwp->pw_gid; ! 284: strcat(spoolname, np); ! 285: strcpy(myname, np); ! 286: strcpy(myfullname, pwp->pw_gecos); ! 287: strcpy(mymbox, pwp->pw_dir); ! 288: strcat(mymbox, "/mbox"); ! 289: strcpy(mydead, pwp->pw_dir); ! 290: strcat(mydead, "/dead.letter"); ! 291: strcpy(mysig, pwp->pw_dir); ! 292: strcat(mysig, "/.sig.mail"); ! 293: strcpy(myalias, pwp->pw_dir); ! 294: strcat(myalias, "/.aliases"); ! 295: mktemp(templ); ! 296: ! 297: if ((editname=getenv("EDITOR"))==NULL) ! 298: editname = "/bin/ed"; ! 299: ! 300: if ( ((scatname=getenv("PAGER")) != NULL) && ! 301: (strlen(scatname) == 0) ) ! 302: scatname = NULL; ! 303: ! 304: if ((askcc=getenv("ASKCC")) != NULL) ! 305: if ( strcmp(askcc, "YES") ) ! 306: askcc = NULL; ! 307: } ! 308: ! 309: /* ! 310: * Process mail's interactive commands ! 311: * for reading/deleting/saving mail. ! 312: */ ! 313: commands() ! 314: { ! 315: register struct msg *mp; ! 316: struct msg *dest; ! 317: register char **fnp; ! 318: register FILE *fp; ! 319: fsize_t seek; ! 320: ! 321: readmail(); ! 322: mprint(mp = rflag ? m_last : m_first); ! 323: for (;;) { ! 324: readmail(); ! 325: intcheck(); ! 326: if ( ! pflag) { ! 327: callmexmail = 0; ! 328: mmsg("? "); ! 329: if (fgets(cline, sizeof cline, stdin) == NULL) { ! 330: if (intcheck()) ! 331: continue; ! 332: break; ! 333: } ! 334: } ! 335: switch (cline[0]) { ! 336: case 'd': ! 337: if (cline[1] != '\n') ! 338: goto usage; ! 339: mp->m_flag += 1; ! 340: goto advance; ! 341: ! 342: case 'm': ! 343: case 't': ! 344: if (csplit(cline, args) == 1) { ! 345: /* We don't want to put anything into ! 346: args that we didn't get from malloc. */ ! 347: ! 348: if (args[1] != NULL) { ! 349: free(args[1]); ! 350: } ! 351: args[1] = malloc(strlen(myname) + 1); ! 352: strcpy(args[1], myname); ! 353: args[2] = NULL; ! 354: } ! 355: callmexmail = (cline[1] == 'x'); ! 356: if (cline[0] == 'm') { ! 357: send2(mfp, args+1, mp->m_seek, mp->m_end - 3, 0); ! 358: fseek(mfp, mp->m_seek, 0); ! 359: } else ! 360: send2(stdin, args+1, 0L, (fsize_t)MAXLONG, 1); ! 361: break; ! 362: ! 363: case '.': ! 364: case 'p': ! 365: if (cline[1] == 'x') { ! 366: callmexmail = 1; ! 367: if (cline[2] != '\n') ! 368: goto usage; ! 369: } else if (cline[1] != '\n') ! 370: goto usage; ! 371: if (mprint(mp)) ! 372: break; ! 373: goto advance; ! 374: ! 375: case 'q': ! 376: if (cline[1] != '\n') ! 377: goto usage; ! 378: mquit(); ! 379: /* NOTREACHED */ ! 380: ! 381: case 'r': ! 382: if (cline[1] != '\n') ! 383: goto usage; ! 384: rflag = ! rflag; ! 385: break; ! 386: case 's': ! 387: case 'w': ! 388: if (csplit(cline, args) == 1) { ! 389: /* We don't want to put anything into ! 390: args that we didn't get from malloc. */ ! 391: ! 392: if (args[1] != NULL) { ! 393: free(args[1]); ! 394: } ! 395: args[1] = malloc(strlen(mymbox) + 1); ! 396: strcpy(args[1], mymbox); ! 397: args[2] = NULL; ! 398: } ! 399: seek = mp->m_seek; ! 400: if (cline[0] == 'w') ! 401: seek += mp->m_hsize; ! 402: for (fnp = &args[1]; *fnp != NULL; fnp++) { ! 403: fp = NULL; ! 404: if (maccess(*fnp) < 0 ! 405: || (fp = fopen(*fnp, "a")) == NULL ! 406: || mcopy(mfp, fp, seek, mp->m_end, 0)) ! 407: mmsg(nosave, *fnp); ! 408: if (fp != NULL) { ! 409: fclose(fp); ! 410: chown(*fnp, myuid, mygid); ! 411: } ! 412: } ! 413: break; ! 414: ! 415: case 'x': ! 416: if (cline[1] != '\n') ! 417: goto usage; ! 418: rmexit(0); ! 419: /* NOTREACHED */ ! 420: ! 421: case '!': ! 422: if (system(cline+1) == 127) ! 423: mmsg("Try again\n"); ! 424: else ! 425: mmsg("!\n"); ! 426: break; ! 427: ! 428: case '?': ! 429: mmsg(isummary); ! 430: break; ! 431: ! 432: case '-': ! 433: if (cline[1] != '\n') ! 434: goto usage; ! 435: dest = rflag ? m_last : m_first; ! 436: goto nextmsg; ! 437: ! 438: case '+': ! 439: if (cline[1] != '\n') ! 440: goto usage; ! 441: case '\n': ! 442: advance: ! 443: dest = rflag ? m_first : m_last; ! 444: nextmsg: ! 445: do { ! 446: if (mp == dest) { ! 447: if (pflag) ! 448: return; ! 449: mmsg("No more messages.\n"); ! 450: break; ! 451: } ! 452: mp = (dest==m_last) ? mp->m_next : mp->m_prev; ! 453: } while (mprint(mp) == 0); ! 454: break; ! 455: ! 456: default: ! 457: usage: ! 458: mmsg(iusage); ! 459: break; ! 460: } ! 461: } ! 462: putc('\n', stderr); ! 463: mquit(); ! 464: } ! 465: ! 466: /* ! 467: * Read through the mail-box file ! 468: * constructing list of letters. ! 469: * On subsequent calls, append any additional mail ! 470: * and notify the user. ! 471: */ ! 472: readmail() ! 473: { ! 474: register struct msg *mp; ! 475: struct stat sb; ! 476: static long m_last_end; ! 477: int datasw; ! 478: ! 479: if (m_first == NULL) { ! 480: if (stat(mailbox, &sb) < 0) ! 481: merr(nombox, mailbox); ! 482: if (sb.st_size == 0) ! 483: merr(nomail); ! 484: if (access(mailbox, AREAD) < 0) ! 485: merr(noperm, mailbox); ! 486: if ((mfp = fopen(mailbox, "r")) == NULL) ! 487: merr(moerr, mailbox); ! 488: m_last_end = 0; ! 489: } else { ! 490: fstat(fileno(mfp), &sb); ! 491: if (sb.st_size == m_last_end) ! 492: return; ! 493: mmsg("More mail received.\n"); ! 494: } ! 495: ! 496: for(mlock(myuid);;) { ! 497: fseek(mfp, m_last_end, 0); ! 498: datasw = 0; ! 499: while (fgets(msgline, sizeof msgline, mfp) != NULL) { ! 500: /* NB: this means the implicit message ! 501: seperator is actually "\n\1\1\n". */ ! 502: if(!(datasw = strcmp("\1\1\n", msgline))) { ! 503: /* message seperator */ ! 504: mp = (struct msg *)myalloc(sizeof(*mp)); ! 505: mp->m_next = NULL; ! 506: mp->m_prev = m_last; ! 507: mp->m_flag = mp->m_hsize = 0; ! 508: mp->m_seek = m_last_end; ! 509: mp->m_end = m_last_end = ftell(mfp); ! 510: if (m_first == NULL) ! 511: m_last = m_first = mp; ! 512: else ! 513: m_last = m_last->m_next = mp; ! 514: } ! 515: } ! 516: ! 517: if(!datasw) /* data ended with message seperator */ ! 518: break; ! 519: ! 520: /* unterminated data, patch and retry */ ! 521: fclose(mfp); ! 522: if ((mfp = fopen(mailbox, "a")) == NULL) ! 523: merr(moerr, mailbox); ! 524: fprintf(mfp, "\1\1\n"); /* terminate it */ ! 525: fclose(mfp); ! 526: if ((mfp = fopen(mailbox, "r")) == NULL) ! 527: merr(moerr, mailbox); ! 528: mmsg("Incomplete message found.\n"); ! 529: } ! 530: munlock(); ! 531: } ! 532: ! 533: /* ! 534: * Lock the appropriately-numbered mailbox ! 535: * (numbered by user-number) from multiple ! 536: * accesses. There is a (small) race here ! 537: * which will be overlooked for now. ! 538: */ ! 539: char *lockname; ! 540: ! 541: mlock(uid) ! 542: int uid; ! 543: { ! 544: register int fd; ! 545: static char lock[32]; ! 546: ! 547: lockname = lock; ! 548: sprintf(lock, "/tmp/maillock%d", uid); ! 549: while (access(lockname, 0) == 0) ! 550: sleep(1); ! 551: if ((fd = creat(lockname, 0)) >= 0) ! 552: close(fd); ! 553: } ! 554: ! 555: /* ! 556: * Unlock the currently-set lock (by `mlock') ! 557: * also called from rmexit. ! 558: */ ! 559: munlock() ! 560: { ! 561: if (lockname != NULL) ! 562: unlink(lockname); ! 563: lockname = NULL; ! 564: } ! 565: ! 566: /* ! 567: * Exit, after rewriting the ! 568: * mailbox ! 569: */ ! 570: mquit() ! 571: { ! 572: register struct msg *mp; ! 573: register FILE *nfp, *tmpfp; ! 574: struct stat sb; ! 575: ! 576: /* Get new stuff. */ ! 577: readmail(); ! 578: /* There is a slight race here. We really should ! 579: lock BEFORE the readmail(), but readmail() does unlocks... ! 580: FIX ME. */ ! 581: mlock(myuid); ! 582: ! 583: if (mailbox != spoolname && maccess(mailbox) < 0) ! 584: merr(noperm, mailbox); ! 585: fstat(fileno(mfp), &sb); ! 586: signal(SIGINT, SIG_IGN); ! 587: signal(SIGPIPE, SIG_IGN); ! 588: ! 589: /* Make a copy of the mail box; we're going to overwrite it. */ ! 590: tmpfp = tmp_copy(mfp); ! 591: fclose(mfp); ! 592: ! 593: if ((nfp = fopen(mailbox, "w")) == NULL) ! 594: merr("Cannot re-write '%s'\n", mailbox); ! 595: chown(mailbox, sb.st_uid, sb.st_gid); ! 596: chmod(mailbox, sb.st_mode&0777); ! 597: for (mp = m_first; mp != NULL; mp = mp->m_next) { ! 598: ! 599: if (mp->m_flag == 0) { ! 600: if (mcopy(tmpfp, nfp, mp->m_seek, mp->m_end, 0)) { ! 601: merr(wrerr, mailbox); ! 602: } ! 603: } /* if (mp->m_flag == 0) */ ! 604: ! 605: } /* for (walk through the linked list of messages) */ ! 606: ! 607: fclose(nfp); ! 608: fclose(tmpfp); ! 609: munlock(); ! 610: rmexit(0); ! 611: } ! 612: ! 613: /* ! 614: * Print the current message, given by ! 615: * the message pointer (`mp'). ! 616: */ ! 617: mprint(mp) ! 618: register struct msg *mp; ! 619: { ! 620: FILE *xfp; ! 621: ! 622: if (mp->m_flag) ! 623: return 0; ! 624: if (callmexmail) { ! 625: if (scatname != NULL) ! 626: sprintf(cmdname, "xdecode | %s", scatname); ! 627: else ! 628: sprintf(cmdname, "xdecode"); ! 629: if ((xfp = popen(cmdname, "w")) == NULL) ! 630: return 0; ! 631: mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1); ! 632: pclose(xfp); ! 633: } else { ! 634: fseek(mfp, mp->m_seek, 0); ! 635: if (fgets(msgline, sizeof msgline, mfp) != NULL && ! 636: strncmp(msgline, "From xmail", 10) == 0) { ! 637: printf("From xmail\n"); ! 638: system("/usr/games/fortune"); ! 639: return(1); ! 640: } ! 641: if (scatname != NULL) { ! 642: sprintf(cmdname, "%s", scatname); ! 643: if ((xfp = popen(cmdname, "w")) == NULL) ! 644: return(0); ! 645: mcopy(mfp, xfp, mp->m_seek, mp->m_end - 3, 1); ! 646: if ( ((pclose(xfp)>>8)&0xFF) == SIGINT ) ! 647: putc('\n', stdout); ! 648: } else { ! 649: mcopy(mfp, stdout, mp->m_seek, mp->m_end - 3, 1); ! 650: } ! 651: } ! 652: return (1); ! 653: } ! 654: ! 655: /* ! 656: * Get additional users to receive message (CC:) ! 657: */ ! 658: ! 659: char ** ! 660: getcc() ! 661: { ! 662: static char names[NCLINE]; ! 663: static char *ccargs[NARGS]; ! 664: ! 665: ccargs[0] = NULL; ! 666: mmsg("CC: "); ! 667: if ( fgets(names, sizeof names, stdin) == NULL ) ! 668: return(ccargs); ! 669: ! 670: csplit(names, ccargs); ! 671: return(ccargs); ! 672: } ! 673: ! 674: ! 675: /* ! 676: * Errors, usage, and exit removing ! 677: * any tempfiles left around. ! 678: */ ! 679: mmsg(x) ! 680: { ! 681: fprintf(stderr, "%r", &x); ! 682: } ! 683: ! 684: merr(x, s) ! 685: char *x, *s; ! 686: { ! 687: mmsg(x, s); ! 688: logdump("merr: "); ! 689: logdump(x, s); ! 690: rmexit(1); ! 691: } ! 692: ! 693: rmexit(s) ! 694: int s; ! 695: { ! 696: if (temp != NULL) ! 697: unlink(temp); ! 698: munlock(); ! 699: ! 700: logdump("About to exit, status = 0x%04x\n", s); ! 701: logclose(); ! 702: ! 703: exit(s); ! 704: } ! 705: ! 706: /* ! 707: * Catch interrupts, taking the ! 708: * appropriate action based on ! 709: * the `-q' option. ! 710: */ ! 711: int intrflag; /* On when interrupt sent */ ! 712: int pipeflag; /* On when broken pipe caught */ ! 713: ! 714: catchintr() ! 715: { ! 716: logdump("Caught SIGINT\n"); ! 717: if (qflag) ! 718: rmexit(1); ! 719: intrflag = 1; ! 720: signal(SIGINT, catchintr); ! 721: } ! 722: ! 723: catchpipe() ! 724: { ! 725: logdump("Caught SIGPIPE\n"); ! 726: pipeflag = 1; ! 727: signal(SIGPIPE, catchpipe); ! 728: } ! 729: ! 730: intcheck() ! 731: { ! 732: if (intrflag || pipeflag) { ! 733: if (intrflag) ! 734: putc('\n', stdout); ! 735: intrflag = pipeflag = 0; ! 736: return (1); ! 737: } ! 738: return (0); ! 739: } ! 740: ! 741: /* ! 742: * Call the system to execute a command line ! 743: * which is passed as an argument. ! 744: * Change the user id and group id. ! 745: */ ! 746: system(line) ! 747: char *line; ! 748: { ! 749: int status, pid; ! 750: register wpid; ! 751: register int (*intfun)(), (*quitfun)(); ! 752: ! 753: if ((pid = fork()) < 0) ! 754: return (-1); ! 755: if (pid == 0) { /* Child */ ! 756: setuid(myuid); ! 757: setgid(mygid); ! 758: execl("/bin/sh", "sh", "-c", line, NULL); ! 759: exit(0177); ! 760: } ! 761: intfun = signal(SIGINT, SIG_IGN); ! 762: quitfun = signal(SIGQUIT, SIG_IGN); ! 763: while ((wpid = wait(&status))!=pid && wpid>=0) ! 764: ; ! 765: if (wpid < 0) ! 766: status = wpid; ! 767: signal(SIGINT, intfun); ! 768: signal(SIGQUIT, quitfun); ! 769: return (status); ! 770: } ! 771: ! 772: char * ! 773: revnop() ! 774: { ! 775: register char *cp; ! 776: register char c; ! 777: static char revnobuf[32]; ! 778: ! 779: if ((cp = index(rcsrev, ' ')) != NULL) { ! 780: while (((c = *++cp) == ' ') && (c != '\0')) ! 781: ; ! 782: strcpy(revnobuf, cp); ! 783: if ((cp = index(revnobuf, ' ')) != NULL) ! 784: *cp = '\0'; ! 785: return (revnobuf); ! 786: } else ! 787: return("OOPS"); ! 788: } ! 789: ! 790: /* ! 791: * Split a command line up into ! 792: * argv (passed) and argc (returned). ! 793: * We assume that elements of "args" are either NULL or they were ! 794: * returned from malloc, so that they can be freed. ! 795: */ ! 796: int ! 797: csplit(command, args) ! 798: char *command; ! 799: char **args; ! 800: { ! 801: register char *cp; ! 802: int i, argsize; ! 803: ! 804: i = 0; /* Start filling in at the zero'th arg. */ ! 805: cp = eat_ws(command); ! 806: ! 807: /* Walk "cp" through "command", copying segments as we go. */ ! 808: while ( *cp != CNULL ) { ! 809: /* We've found an argument; find some space. */ ! 810: if (args[i] != NULL ) { ! 811: free(args[i]); ! 812: } ! 813: ! 814: /* Figure out how big the argment is. */ ! 815: argsize = (int) (find_ws(cp) - cp); ! 816: ! 817: /* Alloc enough space for it--include the trailing NULL. */ ! 818: if ((args[i] = malloc(argsize + 1)) == NULL) { ! 819: mmsg(allocerr, "csplit"); ! 820: return(0); /* Is this the approriate action?? */ ! 821: } ! 822: ! 823: /* Copy the argument into the space. */ ! 824: memcpy(args[i], cp, argsize); ! 825: args[i][argsize] = CNULL; /* This may be redundant. */ ! 826: ! 827: /* Make sure that cp points to after the argument. */ ! 828: cp += argsize; ! 829: ! 830: cp = eat_ws(cp); ! 831: ++i; ! 832: } /* while (walk "cp" through "command") */ ! 833: ! 834: args[i] = NULL; ! 835: return (i); ! 836: } ! 837: ! 838: /* ! 839: * Find the next occurence of non-white space in character string s. ! 840: */ ! 841: char * ! 842: eat_ws(s) ! 843: char *s; ! 844: { ! 845: while(isspace(*s)){ ! 846: ++s; ! 847: } ! 848: return(s); ! 849: } ! 850: ! 851: /* ! 852: * Find next occurence of white space in character string s. ! 853: */ ! 854: char * ! 855: find_ws(s) ! 856: register char *s; ! 857: { ! 858: while((*s != CNULL) && !isspace(*s) ){ ! 859: ++s; ! 860: } ! 861: return(s); ! 862: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.