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