|
|
1.1 ! root 1: #include <ctype.h> ! 2: #include <stdio.h> ! 3: #include <pwd.h> ! 4: #include <utmp.h> ! 5: #include <signal.h> ! 6: #include <sys/types.h> ! 7: #include <sys/stat.h> ! 8: #include <setjmp.h> ! 9: #include <whoami.h> ! 10: ! 11: /*copylet flags */ ! 12: /*remote mail, add rmtmsg */ ! 13: #define REMOTE 1 ! 14: /* zap header and trailing empty line */ ! 15: #define ZAP 3 ! 16: #define ORDINARY 2 ! 17: #define FORWARD 4 ! 18: #define LSIZE 256 ! 19: #define MAXLET 300 /* maximum number of letters */ ! 20: #define MAILMODE (~0644) /* mode of created mail */ ! 21: #define RMAIL "/usr/net/bin/sendmail" ! 22: ! 23: char line[LSIZE]; ! 24: char resp[LSIZE]; ! 25: struct let { ! 26: long adr; ! 27: char change; ! 28: } let[MAXLET]; ! 29: int nlet = 0; ! 30: char lfil[50]; ! 31: long iop, time(); ! 32: char *getenv(); ! 33: char *index(); ! 34: char lettmp[] = "/tmp/maXXXXX"; ! 35: char maildir[] = "/usr/spool/mail/"; ! 36: char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx"; ! 37: char dead[] = "dead.letter"; ! 38: char *thissys = sysname; ! 39: char *netname = "vax"; ! 40: char forwmsg[] = " forwarded\n"; ! 41: char *curlock; ! 42: int lockerror; ! 43: FILE *tmpf; ! 44: FILE *malf; ! 45: char *my_name; ! 46: char *getlogin(); ! 47: struct passwd *getpwuid(); ! 48: int error; ! 49: int locked; ! 50: int changed; ! 51: int forward; ! 52: char from[] = "From "; ! 53: long ftell(); ! 54: int delete(); ! 55: char *ctime(); ! 56: int flgf; ! 57: int flgp; ! 58: int delflg = 1; ! 59: jmp_buf sjbuf; ! 60: ! 61: main(argc, argv) ! 62: char **argv; ! 63: { ! 64: register i; ! 65: char sobuf[BUFSIZ]; ! 66: ! 67: setbuf(stdout, sobuf); ! 68: mktemp(lettmp); ! 69: unlink(lettmp); ! 70: my_name = getlogin(); ! 71: if (my_name == NULL || strlen(my_name) == 0) { ! 72: struct passwd *pwent; ! 73: pwent = getpwuid(getuid()); ! 74: if (pwent==NULL) ! 75: my_name = "???"; ! 76: else ! 77: my_name = pwent->pw_name; ! 78: } ! 79: if(setjmp(sjbuf)) done(); ! 80: for (i=0; i<20; i++) ! 81: setsig(i, delete); ! 82: tmpf = fopen(lettmp, "w"); ! 83: if (tmpf == NULL) { ! 84: fprintf(stderr, "mail: cannot open %s for writing\n", lettmp); ! 85: done(); ! 86: } ! 87: if (argv[0][0] != 'r' && /* no favors for rmail*/ ! 88: (argc == 1 || argv[1][0] == '-' && argv[1][1] != 'r')) ! 89: printmail(argc, argv); ! 90: else ! 91: sendmail(argc, argv); ! 92: done(); ! 93: } ! 94: ! 95: setsig(i, f) ! 96: int i; ! 97: int (*f)(); ! 98: { ! 99: if(signal(i, SIG_IGN)!=SIG_IGN) ! 100: signal(i, f); ! 101: } ! 102: ! 103: printmail(argc, argv) ! 104: char **argv; ! 105: { ! 106: int flg, i, j, print; ! 107: char *p, *getarg(); ! 108: ! 109: setuid(getuid()); ! 110: cat(mailfile, maildir, my_name); ! 111: for (; argc>1; argv++, argc--) { ! 112: if (argv[1][0]=='-') { ! 113: if (argv[1][1]=='q') ! 114: delflg = 0; ! 115: else if (argv[1][1]=='p') { ! 116: flgp++; ! 117: delflg = 0; ! 118: } else if (argv[1][1]=='f') { ! 119: if (argc>=3) { ! 120: strcpy(mailfile, argv[2]); ! 121: argv++; ! 122: argc--; ! 123: } ! 124: } else if (argv[1][1]=='r') { ! 125: forward = 1; ! 126: } else { ! 127: fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); ! 128: done(); ! 129: } ! 130: } else ! 131: break; ! 132: } ! 133: malf = fopen(mailfile, "r"); ! 134: if (malf == NULL) { ! 135: fprintf(stdout, "No mail.\n"); ! 136: return; ! 137: } ! 138: lock(mailfile); ! 139: copymt(malf, tmpf); ! 140: fclose(malf); ! 141: fclose(tmpf); ! 142: unlock(); ! 143: tmpf = fopen(lettmp, "r"); ! 144: ! 145: changed = 0; ! 146: print = 1; ! 147: for (i = 0; i < nlet; ) { ! 148: j = forward ? i : nlet - i - 1; ! 149: if(setjmp(sjbuf)) { ! 150: print=0; ! 151: } else { ! 152: if (print) ! 153: copylet(j, stdout, ORDINARY); ! 154: print = 1; ! 155: } ! 156: if (flgp) { ! 157: i++; ! 158: continue; ! 159: } ! 160: setjmp(sjbuf); ! 161: fprintf(stdout, "? "); ! 162: fflush(stdout); ! 163: if (fgets(resp, LSIZE, stdin) == NULL) ! 164: break; ! 165: switch (resp[0]) { ! 166: ! 167: default: ! 168: fprintf(stderr, "usage\n"); ! 169: case '?': ! 170: print = 0; ! 171: fprintf(stderr, "q\tquit\n"); ! 172: fprintf(stderr, "x\texit without changing mail\n"); ! 173: fprintf(stderr, "p\tprint\n"); ! 174: fprintf(stderr, "s[file]\tsave (default mbox)\n"); ! 175: fprintf(stderr, "w[file]\tsame without header\n"); ! 176: fprintf(stderr, "-\tprint previous\n"); ! 177: fprintf(stderr, "d\tdelete\n"); ! 178: fprintf(stderr, "+\tnext (no delete)\n"); ! 179: fprintf(stderr, "m user\tmail to user\n"); ! 180: fprintf(stderr, "! cmd\texecute cmd\n"); ! 181: break; ! 182: ! 183: case '+': ! 184: case 'n': ! 185: case '\n': ! 186: i++; ! 187: break; ! 188: case 'x': ! 189: changed = 0; ! 190: case 'q': ! 191: goto donep; ! 192: case 'p': ! 193: break; ! 194: case '^': ! 195: case '-': ! 196: if (--i < 0) ! 197: i = 0; ! 198: break; ! 199: case 'y': ! 200: case 'w': ! 201: case 's': ! 202: flg = 0; ! 203: if (resp[1] != '\n' && resp[1] != ' ') { ! 204: printf("illegal\n"); ! 205: flg++; ! 206: print = 0; ! 207: continue; ! 208: } ! 209: if (resp[1] == '\n' || resp[1] == '\0') { ! 210: p = getenv("HOME"); ! 211: if(p != 0) ! 212: cat(resp+1, p, "/mbox"); ! 213: else ! 214: cat(resp+1, "", "mbox"); ! 215: } ! 216: for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { ! 217: malf = fopen(lfil, "a"); ! 218: if (malf == NULL) { ! 219: fprintf(stdout, "mail: cannot append to %s\n", lfil); ! 220: flg++; ! 221: continue; ! 222: } ! 223: copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); ! 224: fclose(malf); ! 225: } ! 226: if (flg) ! 227: print = 0; ! 228: else { ! 229: let[j].change = 'd'; ! 230: changed++; ! 231: i++; ! 232: } ! 233: break; ! 234: case 'm': ! 235: flg = 0; ! 236: if (resp[1] == '\n' || resp[1] == '\0') { ! 237: i++; ! 238: continue; ! 239: } ! 240: if (resp[1] != ' ') { ! 241: printf("invalid command\n"); ! 242: flg++; ! 243: print = 0; ! 244: continue; ! 245: } ! 246: for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) ! 247: if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */ ! 248: flg++; ! 249: if (flg) ! 250: print = 0; ! 251: else { ! 252: let[j].change = 'd'; ! 253: changed++; ! 254: i++; ! 255: } ! 256: break; ! 257: case '!': ! 258: system(resp+1); ! 259: printf("!\n"); ! 260: print = 0; ! 261: break; ! 262: case 'd': ! 263: let[j].change = 'd'; ! 264: changed++; ! 265: i++; ! 266: if (resp[1] == 'q') ! 267: goto donep; ! 268: break; ! 269: } ! 270: } ! 271: donep: ! 272: if (changed) ! 273: copyback(); ! 274: } ! 275: ! 276: copyback() /* copy temp or whatever back to /usr/spool/mail */ ! 277: { ! 278: register i, n, c; ! 279: int new = 0; ! 280: struct stat stbuf; ! 281: ! 282: signal(SIGINT, SIG_IGN); ! 283: signal(SIGHUP, SIG_IGN); ! 284: signal(SIGQUIT, SIG_IGN); ! 285: lock(mailfile); ! 286: stat(mailfile, &stbuf); ! 287: if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ ! 288: malf = fopen(mailfile, "r"); ! 289: if (malf == NULL) { ! 290: fprintf(stdout, "mail: can't re-read %s\n", mailfile); ! 291: done(); ! 292: } ! 293: fseek(malf, let[nlet].adr, 0); ! 294: fclose(tmpf); ! 295: tmpf = fopen(lettmp, "a"); ! 296: fseek(tmpf, let[nlet].adr, 0); ! 297: while ((c = fgetc(malf)) != EOF) ! 298: fputc(c, tmpf); ! 299: fclose(malf); ! 300: fclose(tmpf); ! 301: tmpf = fopen(lettmp, "r"); ! 302: let[++nlet].adr = stbuf.st_size; ! 303: new = 1; ! 304: } ! 305: malf = fopen(mailfile, "w"); ! 306: if (malf == NULL) { ! 307: fprintf(stderr, "mail: can't rewrite %s\n", lfil); ! 308: done(); ! 309: } ! 310: n = 0; ! 311: for (i = 0; i < nlet; i++) ! 312: if (let[i].change != 'd') { ! 313: copylet(i, malf, ORDINARY); ! 314: n++; ! 315: } ! 316: fclose(malf); ! 317: if (new) ! 318: fprintf(stdout, "new mail arrived\n"); ! 319: unlock(); ! 320: } ! 321: ! 322: copymt(f1, f2) /* copy mail (f1) to temp (f2) */ ! 323: FILE *f1, *f2; ! 324: { ! 325: long nextadr; ! 326: ! 327: nlet = nextadr = 0; ! 328: let[0].adr = 0; ! 329: while (fgets(line, LSIZE, f1) != NULL) { ! 330: if (isfrom(line)) ! 331: let[nlet++].adr = nextadr; ! 332: nextadr += strlen(line); ! 333: fputs(line, f2); ! 334: } ! 335: let[nlet].adr = nextadr; /* last plus 1 */ ! 336: } ! 337: ! 338: copylet(n, f, type) FILE *f; ! 339: { int ch, k; ! 340: fseek(tmpf, let[n].adr, 0); ! 341: k = let[n+1].adr - let[n].adr; ! 342: while(k-- > 1 && (ch=fgetc(tmpf))!='\n') ! 343: if(type!=ZAP) fputc(ch,f); ! 344: if(type==REMOTE) ! 345: fprintf(f, " remote from %s\n", thissys); ! 346: else if (type==FORWARD) ! 347: fprintf(f, forwmsg); ! 348: else if(type==ORDINARY) ! 349: fputc(ch,f); ! 350: while(k-->1) ! 351: fputc(ch=fgetc(tmpf), f); ! 352: if(type!=ZAP || ch!= '\n') ! 353: fputc(fgetc(tmpf), f); ! 354: } ! 355: ! 356: isfrom(lp) ! 357: register char *lp; ! 358: { ! 359: register char *p; ! 360: ! 361: for (p = from; *p; ) ! 362: if (*lp++ != *p++) ! 363: return(0); ! 364: return(1); ! 365: } ! 366: ! 367: sendmail(argc, argv) ! 368: char **argv; ! 369: { ! 370: char truename[100]; ! 371: int first; ! 372: ! 373: truename[0] = 0; ! 374: line[0] = '\0'; ! 375: if (argc > 4 && strcmp(argv[1], "-r") == 0) { ! 376: strcpy(truename, argv[2]); ! 377: strcat(truename, ":"); ! 378: strcat(truename, argv[3]); ! 379: argc -= 3; ! 380: argv += 3; ! 381: fgets(line, LSIZE, stdin); ! 382: if (strcmpn("From", line, 4) == 0) ! 383: line[0] = '\0'; ! 384: } else ! 385: strcpy(truename, my_name); ! 386: time(&iop); ! 387: fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); ! 388: iop = ftell(tmpf); ! 389: flgf = 1; ! 390: for (first = 1;; first = 0) { ! 391: if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL) ! 392: break; ! 393: if (!first && fgets(line, LSIZE, stdin) == NULL) ! 394: break; ! 395: if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin))) ! 396: break; ! 397: if (isfrom(line)) ! 398: fputs(">", tmpf); ! 399: fputs(line, tmpf); ! 400: flgf = 0; ! 401: } ! 402: fputs("\n", tmpf); ! 403: nlet = 1; ! 404: let[0].adr = 0; ! 405: let[1].adr = ftell(tmpf); ! 406: fclose(tmpf); ! 407: if (flgf) ! 408: return; ! 409: tmpf = fopen(lettmp, "r"); ! 410: if (tmpf == NULL) { ! 411: fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp); ! 412: return; ! 413: } ! 414: while (--argc > 0) ! 415: if (!send(0, *++argv)) /* couldn't send to him */ ! 416: error++; ! 417: if (error) { ! 418: setuid(getuid()); ! 419: malf = fopen(dead, "w"); ! 420: if (malf == NULL) { ! 421: fprintf(stdout, "mail: cannot open %s\n", dead); ! 422: fclose(tmpf); ! 423: return; ! 424: } ! 425: copylet(0, malf, ZAP); ! 426: fclose(malf); ! 427: fprintf(stdout, "Mail saved in %s\n", dead); ! 428: } ! 429: fclose(tmpf); ! 430: } ! 431: ! 432: sendrmt(n, name, rcmd) ! 433: char *name; ! 434: char *rcmd; ! 435: { ! 436: FILE *rmf, *popen(); ! 437: register char *p; ! 438: char rsys[64], cmd[64]; ! 439: register local, pid; ! 440: int sts; ! 441: ! 442: local = 0; ! 443: if (index(name, '^')) { ! 444: while (p = index(name, '^')) ! 445: *p = '!'; ! 446: if (strncmp(name, "researc", 7)) { ! 447: strcpy(rsys, "research"); ! 448: if (*name != '!') ! 449: --name; ! 450: goto skip; ! 451: } ! 452: } ! 453: if (*name=='!') ! 454: name++; ! 455: for(p=rsys; *name!='!'; *p++ = *name++) ! 456: if (*name=='\0') { ! 457: local++; ! 458: break; ! 459: } ! 460: *p = '\0'; ! 461: if ((!local && *name=='\0') || (local && *rsys=='\0')) { ! 462: fprintf(stdout, "null name\n"); ! 463: return(0); ! 464: } ! 465: skip: ! 466: if ((pid = fork()) == -1) { ! 467: fprintf(stderr, "mail: can't create proc for remote\n"); ! 468: return(0); ! 469: } ! 470: if (pid) { ! 471: while (wait(&sts) != pid) { ! 472: if (wait(&sts)==-1) ! 473: return(0); ! 474: } ! 475: return(!sts); ! 476: } ! 477: setuid(getuid()); ! 478: if (local) ! 479: sprintf(cmd, "%s %s", rcmd, rsys); ! 480: else { ! 481: if (index(name+1, '!')) ! 482: sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); ! 483: else ! 484: sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); ! 485: } ! 486: if ((rmf=popen(cmd, "w")) == NULL) ! 487: exit(1); ! 488: copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE); ! 489: pclose(rmf); ! 490: exit(0); ! 491: } ! 492: ! 493: send(n, name) /* send letter n to name */ ! 494: int n; ! 495: char *name; ! 496: { ! 497: char file[50]; ! 498: register char *p; ! 499: register mask; ! 500: struct passwd *pw, *getpwnam(); ! 501: ! 502: stripfx(netname, &name); ! 503: for(p=name; *p!=':' &&*p!='\0'; p++); ! 504: if(*p == ':') return(sendrmt(n, name, RMAIL)); ! 505: else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs")); ! 506: for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++) ! 507: ; ! 508: if (*p == '!'|| *p=='^') ! 509: return(sendrmt(n, name, 0)); ! 510: if ((pw = getpwnam(name)) == NULL) { ! 511: fprintf(stdout, "mail: can't send to %s\n", name); ! 512: return(0); ! 513: } ! 514: cat(file, maildir, name); ! 515: mask = umask(MAILMODE); ! 516: malf = fopen(file, "a"); ! 517: umask(mask); ! 518: if (malf == NULL) { ! 519: fprintf(stdout, "mail: cannot append to %s\n", file); ! 520: return(0); ! 521: } ! 522: lock(file); ! 523: chown(file, pw->pw_uid, pw->pw_gid); ! 524: copylet(n, malf, ORDINARY); ! 525: fclose(malf); ! 526: unlock(); ! 527: return(1); ! 528: } ! 529: ! 530: delete(i) ! 531: { ! 532: setsig(i, delete); ! 533: fprintf(stderr, "\n"); ! 534: if(delflg) ! 535: longjmp(sjbuf, 1); ! 536: done(); ! 537: } ! 538: ! 539: done() ! 540: { ! 541: if(!lockerror) ! 542: unlock(); ! 543: unlink(lettmp); ! 544: exit(error+lockerror); ! 545: } ! 546: ! 547: lock(file) ! 548: char *file; ! 549: { ! 550: struct stat stbuf; ! 551: ! 552: if (locked || flgf) ! 553: return; ! 554: if (stat(file, &stbuf)<0) ! 555: return; ! 556: if (stbuf.st_mode&01) { /* user x bit is the lock */ ! 557: if (stbuf.st_ctime+60 >= time((long *)0)) { ! 558: fprintf(stderr, "%s busy; try again in a minute\n", file); ! 559: lockerror++; ! 560: done(); ! 561: } ! 562: } ! 563: locked = stbuf.st_mode & ~01; ! 564: curlock = file; ! 565: chmod(file, stbuf.st_mode|01); ! 566: } ! 567: ! 568: unlock() ! 569: { ! 570: if (locked) ! 571: chmod(curlock, locked); ! 572: locked = 0; ! 573: } ! 574: ! 575: cat(to, from1, from2) ! 576: char *to, *from1, *from2; ! 577: { ! 578: int i, j; ! 579: ! 580: j = 0; ! 581: for (i=0; from1[i]; i++) ! 582: to[j++] = from1[i]; ! 583: for (i=0; from2[i]; i++) ! 584: to[j++] = from2[i]; ! 585: to[j] = 0; ! 586: } ! 587: ! 588: char *getarg(s, p) /* copy p... into s, update p */ ! 589: register char *s, *p; ! 590: { ! 591: while (*p == ' ' || *p == '\t') ! 592: p++; ! 593: if (*p == '\n' || *p == '\0') ! 594: return(NULL); ! 595: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') ! 596: *s++ = *p++; ! 597: *s = '\0'; ! 598: return(p); ! 599: } ! 600: stripfx(pfx, name) ! 601: char *pfx; ! 602: char **name; ! 603: { ! 604: register char *cp = *name; ! 605: ! 606: while (*pfx && (*cp == *pfx || *cp == toupper(*pfx))) ! 607: cp++, pfx++; ! 608: if (*cp++ != ':') ! 609: return; ! 610: *name = cp; ! 611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.