|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)delivermail.c 4.37 (Berkeley) 6/24/90"; ! 3: #endif ! 4: ! 5: #include <sys/param.h> ! 6: #include <sys/stat.h> ! 7: #include <sys/file.h> ! 8: ! 9: #include <ctype.h> ! 10: #include <stdio.h> ! 11: #include <pwd.h> ! 12: #include <utmp.h> ! 13: #include <signal.h> ! 14: #include <setjmp.h> ! 15: #include <sysexits.h> ! 16: #include "pathnames.h" ! 17: ! 18: /* copylet flags */ ! 19: #define REMOTE 1 /* remote mail, add rmtmsg */ ! 20: #define ORDINARY 2 ! 21: #define ZAP 3 /* zap header and trailing empty line */ ! 22: #define FORWARD 4 ! 23: ! 24: #define LSIZE 256 ! 25: #define MAXLET 300 /* maximum number of letters */ ! 26: #define MAILMODE 0600 /* mode of created mail */ ! 27: ! 28: char line[LSIZE]; ! 29: char resp[LSIZE]; ! 30: struct let { ! 31: long adr; ! 32: char change; ! 33: } let[MAXLET]; ! 34: int nlet = 0; ! 35: char lfil[50]; ! 36: long iop, time(); ! 37: char *getenv(); ! 38: char *index(); ! 39: char lettmp[] = _PATH_TMP; ! 40: char maildir[sizeof(_PATH_MAILDIR) + 5] = _PATH_MAILDIR; ! 41: char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; ! 42: char dead[] = "dead.letter"; ! 43: char forwmsg[] = " forwarded\n"; ! 44: FILE *tmpf; ! 45: FILE *malf; ! 46: char my_name[60]; ! 47: char *getlogin(); ! 48: int error; ! 49: int changed; ! 50: int forward; ! 51: char from[] = "From "; ! 52: long ftell(); ! 53: int delex(); ! 54: char *ctime(); ! 55: int flgf; ! 56: int flgp; ! 57: int delflg = 1; ! 58: int hseqno; ! 59: jmp_buf sjbuf; ! 60: int rmail; ! 61: ! 62: main(argc, argv) ! 63: char **argv; ! 64: { ! 65: register int i; ! 66: char *name; ! 67: struct passwd *pwent; ! 68: ! 69: (void)strcat(maildir, "/"); ! 70: if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || ! 71: getuid() != pwent->pw_uid) ! 72: pwent = getpwuid(getuid()); ! 73: strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1); ! 74: if (setjmp(sjbuf)) ! 75: done(); ! 76: for (i=SIGHUP; i<=SIGTERM; i++) ! 77: setsig(i, delex); ! 78: i = mkstemp(lettmp); ! 79: tmpf = fdopen(i, "r+"); ! 80: if (i < 0 || tmpf == NULL) ! 81: panic("mail: %s: cannot open for writing", lettmp); ! 82: /* ! 83: * This protects against others reading mail from temp file and ! 84: * if we exit, the file will be deleted already. ! 85: */ ! 86: unlink(lettmp); ! 87: if (argv[0][0] == 'r') ! 88: rmail++; ! 89: if (argv[0][0] != 'r' && /* no favors for rmail*/ ! 90: (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) ! 91: printmail(argc, argv); ! 92: else ! 93: bulkmail(argc, argv); ! 94: done(); ! 95: } ! 96: ! 97: setsig(i, f) ! 98: int i; ! 99: int (*f)(); ! 100: { ! 101: if (signal(i, SIG_IGN) != SIG_IGN) ! 102: signal(i, f); ! 103: } ! 104: ! 105: any(c, str) ! 106: register int c; ! 107: register char *str; ! 108: { ! 109: ! 110: while (*str) ! 111: if (c == *str++) ! 112: return(1); ! 113: return(0); ! 114: } ! 115: ! 116: printmail(argc, argv) ! 117: char **argv; ! 118: { ! 119: int flg, i, j, print; ! 120: char *p, *getarg(); ! 121: struct stat statb; ! 122: ! 123: setuid(getuid()); ! 124: cat(mailfile, maildir, my_name); ! 125: #ifdef notdef ! 126: if (stat(mailfile, &statb) >= 0 ! 127: && (statb.st_mode & S_IFMT) == S_IFDIR) { ! 128: strcat(mailfile, "/"); ! 129: strcat(mailfile, my_name); ! 130: } ! 131: #endif ! 132: for (; argc > 1; argv++, argc--) { ! 133: if (argv[1][0] != '-') ! 134: break; ! 135: switch (argv[1][1]) { ! 136: ! 137: case 'p': ! 138: flgp++; ! 139: /* fall thru... */ ! 140: case 'q': ! 141: delflg = 0; ! 142: break; ! 143: ! 144: case 'f': ! 145: if (argc >= 3) { ! 146: strcpy(mailfile, argv[2]); ! 147: argv++, argc--; ! 148: } ! 149: break; ! 150: ! 151: case 'b': ! 152: forward = 1; ! 153: break; ! 154: ! 155: default: ! 156: panic("unknown option %c", argv[1][1]); ! 157: /*NOTREACHED*/ ! 158: } ! 159: } ! 160: malf = fopen(mailfile, "r"); ! 161: if (malf == NULL) { ! 162: printf("No mail.\n"); ! 163: return; ! 164: } ! 165: flock(fileno(malf), LOCK_SH); ! 166: copymt(malf, tmpf); ! 167: fclose(malf); /* implicit unlock */ ! 168: fseek(tmpf, 0L, L_SET); ! 169: ! 170: changed = 0; ! 171: print = 1; ! 172: for (i = 0; i < nlet; ) { ! 173: j = forward ? i : nlet - i - 1; ! 174: if (setjmp(sjbuf)) { ! 175: print = 0; ! 176: } else { ! 177: if (print) ! 178: copylet(j, stdout, ORDINARY); ! 179: print = 1; ! 180: } ! 181: if (flgp) { ! 182: i++; ! 183: continue; ! 184: } ! 185: setjmp(sjbuf); ! 186: fputs("? ", stdout); ! 187: fflush(stdout); ! 188: if (fgets(resp, LSIZE, stdin) == NULL) ! 189: break; ! 190: switch (resp[0]) { ! 191: ! 192: default: ! 193: printf("usage\n"); ! 194: case '?': ! 195: print = 0; ! 196: printf("q\tquit\n"); ! 197: printf("x\texit without changing mail\n"); ! 198: printf("p\tprint\n"); ! 199: printf("s[file]\tsave (default mbox)\n"); ! 200: printf("w[file]\tsame without header\n"); ! 201: printf("-\tprint previous\n"); ! 202: printf("d\tdelete\n"); ! 203: printf("+\tnext (no delete)\n"); ! 204: printf("m user\tmail to user\n"); ! 205: printf("! cmd\texecute cmd\n"); ! 206: break; ! 207: ! 208: case '+': ! 209: case 'n': ! 210: case '\n': ! 211: i++; ! 212: break; ! 213: case 'x': ! 214: changed = 0; ! 215: case 'q': ! 216: goto donep; ! 217: case 'p': ! 218: break; ! 219: case '^': ! 220: case '-': ! 221: if (--i < 0) ! 222: i = 0; ! 223: break; ! 224: case 'y': ! 225: case 'w': ! 226: case 's': ! 227: flg = 0; ! 228: if (resp[1] != '\n' && resp[1] != ' ') { ! 229: printf("illegal\n"); ! 230: flg++; ! 231: print = 0; ! 232: continue; ! 233: } ! 234: if (resp[1] == '\n' || resp[1] == '\0') { ! 235: p = getenv("HOME"); ! 236: if (p != 0) ! 237: cat(resp+1, p, "/mbox"); ! 238: else ! 239: cat(resp+1, "", "mbox"); ! 240: } ! 241: for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { ! 242: malf = fopen(lfil, "a"); ! 243: if (malf == NULL) { ! 244: printf("mail: %s: cannot append\n", ! 245: lfil); ! 246: flg++; ! 247: continue; ! 248: } ! 249: copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); ! 250: fclose(malf); ! 251: } ! 252: if (flg) ! 253: print = 0; ! 254: else { ! 255: let[j].change = 'd'; ! 256: changed++; ! 257: i++; ! 258: } ! 259: break; ! 260: case 'm': ! 261: flg = 0; ! 262: if (resp[1] == '\n' || resp[1] == '\0') { ! 263: i++; ! 264: continue; ! 265: } ! 266: if (resp[1] != ' ') { ! 267: printf("invalid command\n"); ! 268: flg++; ! 269: print = 0; ! 270: continue; ! 271: } ! 272: for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) ! 273: if (!sendmail(j, lfil, my_name)) ! 274: flg++; ! 275: if (flg) ! 276: print = 0; ! 277: else { ! 278: let[j].change = 'd'; ! 279: changed++; ! 280: i++; ! 281: } ! 282: break; ! 283: case '!': ! 284: system(resp+1); ! 285: printf("!\n"); ! 286: print = 0; ! 287: break; ! 288: case 'd': ! 289: let[j].change = 'd'; ! 290: changed++; ! 291: i++; ! 292: if (resp[1] == 'q') ! 293: goto donep; ! 294: break; ! 295: } ! 296: } ! 297: donep: ! 298: if (changed) ! 299: copyback(); ! 300: } ! 301: ! 302: /* copy temp or whatever back to /usr/spool/mail */ ! 303: copyback() ! 304: { ! 305: register int i, c; ! 306: long oldmask; ! 307: int fd, new = 0; ! 308: struct stat stbuf; ! 309: ! 310: oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT)); ! 311: fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); ! 312: if (fd >= 0) { ! 313: flock(fd, LOCK_EX); ! 314: malf = fdopen(fd, "r+"); ! 315: } ! 316: if (fd < 0 || malf == NULL) ! 317: panic("can't rewrite %s", lfil); ! 318: fstat(fd, &stbuf); ! 319: if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ ! 320: fseek(malf, let[nlet].adr, L_SET); ! 321: fseek(tmpf, let[nlet].adr, L_SET); ! 322: while ((c = getc(malf)) != EOF) ! 323: putc(c, tmpf); ! 324: let[++nlet].adr = stbuf.st_size; ! 325: new = 1; ! 326: fseek(malf, 0L, L_SET); ! 327: } ! 328: ftruncate(fd, 0L); ! 329: for (i = 0; i < nlet; i++) ! 330: if (let[i].change != 'd') ! 331: copylet(i, malf, ORDINARY); ! 332: fclose(malf); /* implict unlock */ ! 333: if (new) ! 334: printf("New mail has arrived.\n"); ! 335: sigsetmask(oldmask); ! 336: } ! 337: ! 338: /* copy mail (f1) to temp (f2) */ ! 339: copymt(f1, f2) ! 340: FILE *f1, *f2; ! 341: { ! 342: long nextadr; ! 343: ! 344: nlet = nextadr = 0; ! 345: let[0].adr = 0; ! 346: while (fgets(line, LSIZE, f1) != NULL) { ! 347: if (isfrom(line)) ! 348: let[nlet++].adr = nextadr; ! 349: nextadr += strlen(line); ! 350: fputs(line, f2); ! 351: } ! 352: let[nlet].adr = nextadr; /* last plus 1 */ ! 353: } ! 354: ! 355: copylet(n, f, type) ! 356: FILE *f; ! 357: { ! 358: int ch; ! 359: long k; ! 360: char hostname[MAXHOSTNAMELEN]; ! 361: ! 362: fseek(tmpf, let[n].adr, L_SET); ! 363: k = let[n+1].adr - let[n].adr; ! 364: while (k-- > 1 && (ch = getc(tmpf)) != '\n') ! 365: if (type != ZAP) ! 366: putc(ch, f); ! 367: switch (type) { ! 368: ! 369: case REMOTE: ! 370: gethostname(hostname, sizeof (hostname)); ! 371: fprintf(f, " remote from %s\n", hostname); ! 372: break; ! 373: ! 374: case FORWARD: ! 375: fprintf(f, forwmsg); ! 376: break; ! 377: ! 378: case ORDINARY: ! 379: putc(ch, f); ! 380: break; ! 381: ! 382: case ZAP: ! 383: break; ! 384: ! 385: default: ! 386: panic("Bad letter type %d to copylet.", type); ! 387: } ! 388: while (k-- > 1) { ! 389: ch = getc(tmpf); ! 390: putc(ch, f); ! 391: } ! 392: if (type != ZAP || ch != '\n') ! 393: putc(getc(tmpf), f); ! 394: } ! 395: ! 396: isfrom(lp) ! 397: register char *lp; ! 398: { ! 399: register char *p; ! 400: ! 401: for (p = from; *p; ) ! 402: if (*lp++ != *p++) ! 403: return(0); ! 404: return(1); ! 405: } ! 406: ! 407: bulkmail(argc, argv) ! 408: char **argv; ! 409: { ! 410: char *truename; ! 411: int first; ! 412: register char *cp; ! 413: char *newargv[1000]; ! 414: register char **ap; ! 415: register char **vp; ! 416: int dflag; ! 417: ! 418: dflag = 0; ! 419: delflg = 0; ! 420: if (argc < 1) { ! 421: fprintf(stderr, "puke\n"); ! 422: return; ! 423: } ! 424: for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) ! 425: if (ap[0][0] == '-' && ap[0][1] == 'd') ! 426: dflag++; ! 427: if (!dflag) { ! 428: /* give it to sendmail, rah rah! */ ! 429: unlink(lettmp); ! 430: ap = newargv+1; ! 431: if (rmail) ! 432: *ap-- = "-s"; ! 433: *ap = "-sendmail"; ! 434: setuid(getuid()); ! 435: execv(_PATH_SENDMAIL, ap); ! 436: perror(_PATH_SENDMAIL); ! 437: exit(EX_UNAVAILABLE); ! 438: } ! 439: ! 440: truename = 0; ! 441: line[0] = '\0'; ! 442: ! 443: /* ! 444: * When we fall out of this, argv[1] should be first name, ! 445: * argc should be number of names + 1. ! 446: */ ! 447: ! 448: while (argc > 1 && *argv[1] == '-') { ! 449: cp = *++argv; ! 450: argc--; ! 451: switch (cp[1]) { ! 452: case 'r': ! 453: if (argc <= 1) ! 454: usage(); ! 455: truename = argv[1]; ! 456: fgets(line, LSIZE, stdin); ! 457: if (strncmp("From", line, 4) == 0) ! 458: line[0] = '\0'; ! 459: argv++; ! 460: argc--; ! 461: break; ! 462: ! 463: case 'h': ! 464: if (argc <= 1) ! 465: usage(); ! 466: hseqno = atoi(argv[1]); ! 467: argv++; ! 468: argc--; ! 469: break; ! 470: ! 471: case 'd': ! 472: break; ! 473: ! 474: default: ! 475: usage(); ! 476: } ! 477: } ! 478: if (argc <= 1) ! 479: usage(); ! 480: if (truename == 0) ! 481: truename = my_name; ! 482: time(&iop); ! 483: fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); ! 484: iop = ftell(tmpf); ! 485: flgf = first = 1; ! 486: for (;;) { ! 487: if (first) { ! 488: first = 0; ! 489: if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) ! 490: break; ! 491: } else { ! 492: if (fgets(line, LSIZE, stdin) == NULL) ! 493: break; ! 494: } ! 495: if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) ! 496: break; ! 497: if (isfrom(line)) ! 498: putc('>', tmpf); ! 499: fputs(line, tmpf); ! 500: flgf = 0; ! 501: } ! 502: putc('\n', tmpf); ! 503: nlet = 1; ! 504: let[0].adr = 0; ! 505: let[1].adr = ftell(tmpf); ! 506: if (flgf) ! 507: return; ! 508: while (--argc > 0) ! 509: if (!sendmail(0, *++argv, truename)) ! 510: error++; ! 511: if (error && safefile(dead)) { ! 512: setuid(getuid()); ! 513: malf = fopen(dead, "w"); ! 514: if (malf == NULL) { ! 515: printf("mail: cannot open %s\n", dead); ! 516: fclose(tmpf); ! 517: return; ! 518: } ! 519: copylet(0, malf, ZAP); ! 520: fclose(malf); ! 521: printf("Mail saved in %s\n", dead); ! 522: } ! 523: fclose(tmpf); ! 524: } ! 525: ! 526: sendrmt(n, name) ! 527: char *name; ! 528: { ! 529: FILE *rmf, *popen(); ! 530: register char *p; ! 531: char rsys[64], cmd[64]; ! 532: register pid; ! 533: int sts; ! 534: ! 535: #ifdef notdef ! 536: if (any('^', name)) { ! 537: while (p = index(name, '^')) ! 538: *p = '!'; ! 539: if (strncmp(name, "researc", 7)) { ! 540: strcpy(rsys, "research"); ! 541: if (*name != '!') ! 542: --name; ! 543: goto skip; ! 544: } ! 545: } ! 546: #endif ! 547: for (p=rsys; *name!='!'; *p++ = *name++) ! 548: if (*name=='\0') ! 549: return(0); /* local address, no '!' */ ! 550: *p = '\0'; ! 551: if (name[1]=='\0') { ! 552: printf("null name\n"); ! 553: return(0); ! 554: } ! 555: skip: ! 556: if ((pid = fork()) == -1) { ! 557: fprintf(stderr, "mail: can't create proc for remote\n"); ! 558: return(0); ! 559: } ! 560: if (pid) { ! 561: while (wait(&sts) != pid) { ! 562: if (wait(&sts)==-1) ! 563: return(0); ! 564: } ! 565: return(!sts); ! 566: } ! 567: setuid(getuid()); ! 568: if (any('!', name+1)) ! 569: (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); ! 570: else ! 571: (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); ! 572: if ((rmf=popen(cmd, "w")) == NULL) ! 573: exit(1); ! 574: copylet(n, rmf, REMOTE); ! 575: exit(pclose(rmf) != 0); ! 576: } ! 577: ! 578: usage() ! 579: { ! 580: ! 581: fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); ! 582: error = EX_USAGE; ! 583: done(); ! 584: } ! 585: ! 586: #include <sys/socket.h> ! 587: #include <netinet/in.h> ! 588: #include <netdb.h> ! 589: ! 590: notifybiff(msg) ! 591: char *msg; ! 592: { ! 593: static struct sockaddr_in addr; ! 594: static int f = -1; ! 595: ! 596: if (addr.sin_family == 0) { ! 597: struct hostent *hp = gethostbyname("localhost"); ! 598: struct servent *sp = getservbyname("biff", "udp"); ! 599: ! 600: if (hp && sp) { ! 601: addr.sin_family = hp->h_addrtype; ! 602: bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); ! 603: addr.sin_port = sp->s_port; ! 604: } ! 605: } ! 606: if (addr.sin_family) { ! 607: if (f < 0) ! 608: f = socket(AF_INET, SOCK_DGRAM, 0); ! 609: if (f >= 0) ! 610: sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); ! 611: } ! 612: } ! 613: ! 614: sendmail(n, name, fromaddr) ! 615: int n; ! 616: char *name, *fromaddr; ! 617: { ! 618: char file[256]; ! 619: int mask, fd; ! 620: struct passwd *pw; ! 621: #ifdef notdef ! 622: struct stat statb; ! 623: #endif ! 624: char buf[128]; ! 625: ! 626: if (*name=='!') ! 627: name++; ! 628: if (any('!', name)) ! 629: return (sendrmt(n, name)); ! 630: if ((pw = getpwnam(name)) == NULL) { ! 631: printf("mail: can't send to %s\n", name); ! 632: return(0); ! 633: } ! 634: cat(file, maildir, name); ! 635: #ifdef notdef ! 636: if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { ! 637: strcat(file, "/"); ! 638: strcat(file, name); ! 639: } ! 640: #endif ! 641: if (!safefile(file)) ! 642: return(0); ! 643: fd = open(file, O_WRONLY | O_CREAT, MAILMODE); ! 644: if (fd >= 0) { ! 645: flock(fd, LOCK_EX); ! 646: malf = fdopen(fd, "a"); ! 647: } ! 648: if (fd < 0 || malf == NULL) { ! 649: close(fd); ! 650: printf("mail: %s: cannot append\n", file); ! 651: return(0); ! 652: } ! 653: fchown(fd, pw->pw_uid, pw->pw_gid); ! 654: (void)sprintf(buf, "%s@%ld\n", name, ftell(malf)); ! 655: copylet(n, malf, ORDINARY); ! 656: fclose(malf); ! 657: notifybiff(buf); ! 658: return(1); ! 659: } ! 660: ! 661: delex(i) ! 662: { ! 663: if (i != SIGINT) { ! 664: setsig(i, SIG_DFL); ! 665: sigsetmask(sigblock(0L) &~ sigmask(i)); ! 666: } ! 667: putc('\n', stderr); ! 668: if (delflg) ! 669: longjmp(sjbuf, 1); ! 670: if (error == 0) ! 671: error = i; ! 672: done(); ! 673: } ! 674: ! 675: done() ! 676: { ! 677: ! 678: unlink(lettmp); ! 679: exit(error); ! 680: } ! 681: ! 682: cat(to, from1, from2) ! 683: char *to, *from1, *from2; ! 684: { ! 685: register char *cp, *dp; ! 686: ! 687: cp = to; ! 688: for (dp = from1; *cp = *dp++; cp++) ! 689: ; ! 690: for (dp = from2; *cp++ = *dp++; ) ! 691: ; ! 692: } ! 693: ! 694: /* copy p... into s, update p */ ! 695: char * ! 696: getarg(s, p) ! 697: register char *s, *p; ! 698: { ! 699: while (*p == ' ' || *p == '\t') ! 700: p++; ! 701: if (*p == '\n' || *p == '\0') ! 702: return(NULL); ! 703: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') ! 704: *s++ = *p++; ! 705: *s = '\0'; ! 706: return(p); ! 707: } ! 708: ! 709: safefile(f) ! 710: char *f; ! 711: { ! 712: struct stat statb; ! 713: ! 714: if (lstat(f, &statb) < 0) ! 715: return (1); ! 716: if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { ! 717: fprintf(stderr, ! 718: "mail: %s has more than one link or is a symbolic link\n", ! 719: f); ! 720: return (0); ! 721: } ! 722: return (1); ! 723: } ! 724: ! 725: panic(msg, a1, a2, a3) ! 726: char *msg; ! 727: { ! 728: ! 729: fprintf(stderr, "mail: "); ! 730: fprintf(stderr, msg, a1, a2, a3); ! 731: fprintf(stderr, "\n"); ! 732: done(); ! 733: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.