|
|
1.1 ! root 1: # ! 2: ! 3: /* ! 4: * mail command usage ! 5: * mail [-yn] ! 6: * prints your mail ! 7: * mail people ! 8: * sends standard input to people ! 9: * ! 10: * mail -r machine user people ! 11: * sends mail from the network ! 12: * ! 13: * if NOTROOT is defined, don't run as root. ! 14: */ ! 15: ! 16: #define SIGINT 2 ! 17: #define DIRECT 040000 ! 18: #define RMAILCMD "/usr/net/bin/sendmail" ! 19: #define GETUID() (getuid() & 0377) ! 20: #define SPOOLDIR "/usr/spool/mail/" ! 21: #define NOTROOT $ ! 22: ! 23: struct inode { ! 24: char minor; ! 25: char major; ! 26: int inumber; ! 27: int flags; ! 28: char nlinks; ! 29: char uid; ! 30: char gid; ! 31: char size0; ! 32: int size1; ! 33: int addr[8]; ! 34: int actime[2]; ! 35: int modtime[2]; ! 36: } inode; ! 37: ! 38: char lettmp[] "/tmp/maXXXXX"; ! 39: char preptmp[] "/tmp/mbXXXXX"; ! 40: int pwfil; ! 41: int chew; ! 42: int errs; ! 43: char *strcat(), *strcpy(); ! 44: ! 45: main(argc, argv) ! 46: char **argv; ! 47: { ! 48: register int me; ! 49: extern int fout; ! 50: int uf, delexit(); ! 51: char namebuf[20]; ! 52: ! 53: mktemp(lettmp); ! 54: mktemp(preptmp); ! 55: unlink(lettmp); ! 56: unlink(preptmp); ! 57: me = GETUID(); ! 58: if (getname(me, namebuf) < 0) { ! 59: printf("Who are you?\n"); ! 60: delexit(1); ! 61: } ! 62: if (argc < 2) ! 63: goto hitit; ! 64: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) ! 65: switch(argv[0][1]) { ! 66: register char *cp, *np; ! 67: ! 68: case 'y': ! 69: case 'n': ! 70: argc++, argv--; ! 71: hitit: ! 72: printmail(argc, argv, namebuf); ! 73: delexit(0); ! 74: ! 75: case 'r': ! 76: if (argc < 2) ! 77: continue; ! 78: case 'f': ! 79: if (argc < 1) ! 80: continue; ! 81: if (!equal("network", namebuf) && me != 0) { ! 82: printf("Nice try!\n"); ! 83: delexit(1); ! 84: } ! 85: chew++; ! 86: np = namebuf; ! 87: for (cp = argv[1]; *cp; cp++) ! 88: *np++ = *cp; ! 89: if (argv[0][1] == 'r') ! 90: { ! 91: argc--, argv++; ! 92: *np++ = ':'; ! 93: for (cp = argv[1]; *cp; cp++) ! 94: *np++ = *cp; ! 95: } ! 96: *np++ = 0; ! 97: argc--, argv++; ! 98: continue; ! 99: } ! 100: if ((signal(SIGINT, 01) & 01) == 0) ! 101: signal(SIGINT, delexit); ! 102: unlink(lettmp); ! 103: # ifdef NOTROOT ! 104: fout = creat(lettmp, 0666); ! 105: # else ! 106: fout = creat(lettmp, 0600); ! 107: # endif ! 108: if (fout < 0) { ! 109: fout = 1; ! 110: perror(lettmp); ! 111: delexit(1); ! 112: } ! 113: argc++, argv--; ! 114: bulkmail(argc, argv, namebuf); ! 115: delexit(0); ! 116: } ! 117: ! 118: printmail(argc, argv, name) ! 119: char **argv; ! 120: char *name; ! 121: { ! 122: extern int fin, fout; ! 123: register n, c, f; ! 124: char *mname; ! 125: ! 126: mname = cat(SPOOLDIR, name); ! 127: if (stat(mname, &inode)>=0 && inode.nlinks==1 && ! 128: fopen(mname, &fin)>=0 && (c = getchar())) { ! 129: putchar(c); ! 130: getput(); ! 131: close(fin); ! 132: c = 'x'; ! 133: if (argc<2) { ! 134: if (ttyn(0)!='x') { ! 135: printf("Save?"); ! 136: fin = 0; ! 137: c = getchar(); ! 138: } ! 139: } else ! 140: c = argv[1][1]; ! 141: if (!any(c, "yn")) ! 142: delexit(0); ! 143: if (c == 'y') { ! 144: if (accesss("mbox")) { ! 145: printf("Saved mail in 'mbox'\n"); ! 146: prepend(mname, "mbox", GETUID()); ! 147: unlink(mname); ! 148: } else ! 149: printf("In wrong directory\n"); ! 150: } else ! 151: unlink(mname); ! 152: } else ! 153: printf("No mail.\n"); ! 154: } ! 155: ! 156: bulkmail(argc, argv, from) ! 157: char **argv, *from; ! 158: { ! 159: extern int fin, fout; ! 160: register int c; ! 161: register char *cp; ! 162: char linebuf[128]; ! 163: int tbuf[2], ttyn1; ! 164: ! 165: fin = 0; ! 166: (&fin)[1] = 0; ! 167: time(tbuf); ! 168: ttyn1 = ttyn(1); ! 169: if (ttyn1 < 033) { ! 170: ttyn1 =+ 'a' - 1; ! 171: ttyn1 =<< 8; ! 172: ttyn1 =| '^'; ! 173: } ! 174: printf("From %s tty%c %s", from, ttyn1, ctime(tbuf)); ! 175: ! 176: /* ! 177: * If delivering mail from the network via mail -r, ! 178: * Strip the leading line and throw it away, as long ! 179: * as it begins with "From ..." ! 180: */ ! 181: ! 182: if (chew) { ! 183: cp = linebuf; ! 184: do { ! 185: c = getchar(); ! 186: if (cp - linebuf < 120) ! 187: *cp++ = c; ! 188: } while (c != '\n' && c != 0); ! 189: *cp = '\0'; ! 190: if (linebuf[0] != 'F' || linebuf[1] != 'r' || ! 191: linebuf[2] != 'o' || linebuf[3] != 'm') ! 192: printf("%s", linebuf); ! 193: } ! 194: getput(); ! 195: putchar('\n'); ! 196: flush(); ! 197: close(fout); ! 198: while (--argc > 0) ! 199: sendto(*++argv); ! 200: delexit(errs); ! 201: } ! 202: ! 203: sendto(person) ! 204: char *person; ! 205: { ! 206: static int saved; ! 207: extern int fout, fin; ! 208: register char *filep; ! 209: register int him; ! 210: int i; ! 211: ! 212: if ((person[0] == 'i' || person[0] == 'I') && person[1] == ':') ! 213: person += 2; ! 214: for (i = 0; person[i] != '\0'; i++) ! 215: { ! 216: if (person[i] == ':') ! 217: { ! 218: person[i] = '\0'; ! 219: if (equal(person, "ing70") || equal(person, "ingres")) ! 220: person += i + 1; ! 221: else ! 222: person[i] = ':'; ! 223: break; ! 224: } ! 225: } ! 226: if (person[i] == ':' || equal(person, "msgs")) ! 227: { ! 228: int i = fork(); ! 229: int s; ! 230: ! 231: if (i < 0) { ! 232: perror("fork"); ! 233: goto assback; ! 234: } ! 235: if (i == 0) { ! 236: close(0); ! 237: open(lettmp, 0); ! 238: if (any(':', person)) { ! 239: execl(RMAILCMD, "sendmail", person, 0); ! 240: execl("/usr/bin/sendmail", "sendmail", person, 0); ! 241: execl("/bin/sendmail", "sendmail", person, 0); ! 242: perror("sendmail"); ! 243: } else { ! 244: execl("/usr/new/msgs", "msgs", "-s", 0); ! 245: execl("/usr/ucb/msgs", "msgs", "-s", 0); ! 246: execl("/usr/bin/msgs", "msgs", "-s", 0); ! 247: } ! 248: exit(12); ! 249: } ! 250: for (;;) { ! 251: register int j = wait(&s); ! 252: if (j == -1) ! 253: goto assback; ! 254: if (j == i) ! 255: break; ! 256: } ! 257: if ((s & 0377) != 0 || (s >> 8) == 12) ! 258: goto assback; ! 259: return; ! 260: } ! 261: ! 262: if ((him = getuserid(person)) == -1) { ! 263: assback: ! 264: fout = 1; ! 265: flush(); ! 266: printf("Can't send to %s.\n", person); ! 267: errs++; ! 268: if (ttyn(0)!='x' && saved==0) { ! 269: saved++; ! 270: if (accesss("dead.letter")) { ! 271: printf("Letter saved in 'dead.letter'\n"); ! 272: prepend(lettmp, "dead.letter", GETUID()); ! 273: } else ! 274: printf("In wrong directory\n"); ! 275: } ! 276: return; ! 277: } ! 278: filep = cat(SPOOLDIR, person); ! 279: lock(filep); ! 280: prepend(lettmp, filep, him); ! 281: unlock(); ! 282: } ! 283: ! 284: prepend(from, to, own) ! 285: char *from, *to; ! 286: { ! 287: extern int fin, fout; ! 288: register int sig; ! 289: int statb[18]; ! 290: ! 291: if (stat(to, statb) >= 0 && (statb[2] & 060000) != 0) { ! 292: write(2, "Exotic destination\n", 19); ! 293: delexit(1); ! 294: } ! 295: unlink(preptmp); ! 296: if (fcreat(preptmp, &fout) < 0) { ! 297: fout = 1; ! 298: perror("mail"); ! 299: delexit(1); ! 300: } ! 301: chmod(preptmp, 0600); ! 302: if (fopen(from, &fin) < 0) { ! 303: close(fout); ! 304: fout = 1; ! 305: perror("mail"); ! 306: unlink(preptmp); ! 307: return(0); ! 308: } ! 309: getput(); ! 310: close(fin); ! 311: fopen(to, &fin); ! 312: getput(); ! 313: close(fin); ! 314: flush(); ! 315: close(fout); ! 316: sig = signal(SIGINT, 01); ! 317: unlink(to); ! 318: if (fcreat(to, &fout) < 0) { ! 319: unlink(preptmp); ! 320: fout = 1; ! 321: signal(SIGINT, sig); ! 322: return(0); ! 323: } ! 324: # ifdef NOTROOT ! 325: chmod(to, 0666); ! 326: # else ! 327: chmod(to, 0600); ! 328: chown(to, own); ! 329: # endif ! 330: if(stat(to, &inode) < 0 || inode.nlinks != 1) { ! 331: close(fout); ! 332: fout = 1; ! 333: unlink(preptmp); ! 334: signal(SIGINT, sig); ! 335: return(0); ! 336: } ! 337: if (fopen(preptmp, &fin) < 0) { ! 338: fout = 1; ! 339: perror("mail"); ! 340: signal(SIGINT, sig); ! 341: errs++; ! 342: return(0); ! 343: } ! 344: getput(); ! 345: flush(); ! 346: close(fout); ! 347: close(fin); ! 348: fout = 1; ! 349: signal(SIGINT, sig); ! 350: return(1); ! 351: } ! 352: ! 353: delexit(ex) ! 354: { ! 355: unlock(); ! 356: unlink(lettmp); ! 357: unlink(preptmp); ! 358: exit(ex); ! 359: } ! 360: ! 361: equal(as1, as2) ! 362: { ! 363: register char *s1, *s2; ! 364: ! 365: s1 = as1; ! 366: s2 = as2; ! 367: while (*s1++ == *s2) ! 368: if (*s2++ == 0) ! 369: return(1); ! 370: return(0); ! 371: } ! 372: ! 373: cat(ap1, ap2) ! 374: char *ap1, *ap2; ! 375: { ! 376: register char *p1, *p2; ! 377: static char fn[32]; ! 378: ! 379: p1 = ap1; ! 380: p2 = fn; ! 381: while (*p2++ = *p1++); ! 382: p2--; ! 383: p1 = ap2; ! 384: while (*p2++ = *p1++); ! 385: return(fn); ! 386: } ! 387: ! 388: getput() ! 389: { ! 390: extern int errno; ! 391: register c; ! 392: ! 393: while(c = getchar()) { ! 394: errno = 0; ! 395: putchar(c); ! 396: if(errno) { ! 397: perror("mail"); ! 398: delexit(1); ! 399: } ! 400: } ! 401: } ! 402: ! 403: accesss(s1) ! 404: { ! 405: if (access(".", 2) != -1 && (stat(s1, &inode)<0 || access(s1, 2)==0)) ! 406: return(1); ! 407: return(0); ! 408: } ! 409: ! 410: any(c, str) ! 411: char *str; ! 412: { ! 413: register char *f; ! 414: ! 415: f = str; ! 416: while (*f) ! 417: if (c == *f++) ! 418: return(1); ! 419: return(0); ! 420: } ! 421: ! 422: char *maillock = ".lock"; /* Lock suffix for mailname */ ! 423: char *lockname = "/usr/spool/mail/tmXXXXXX"; ! 424: char locktmp[30]; /* Usable lock temporary */ ! 425: char curlock[50]; /* Last used name of lock */ ! 426: int locked; /* To note that we locked it */ ! 427: ! 428: /* ! 429: * Lock the specified mail file by setting the file mailfile.lock. ! 430: * We must, of course, be careful to unlink the lock file by a call ! 431: * to unlock before we stop. The algorithm used here is to see if ! 432: * the lock exists, and if it does, to check its modify time. If it ! 433: * is older than 30 seconds, we assume error and set our own file. ! 434: * Otherwise, we wait for 5 seconds and try again. ! 435: */ ! 436: ! 437: lock(file) ! 438: char *file; ! 439: { ! 440: register int f; ! 441: long age; ! 442: struct inode sbuf; ! 443: long curtime; ! 444: ! 445: if (file == (char *) 0) { ! 446: printf("Locked = %d\n", locked); ! 447: return(0); ! 448: } ! 449: if (locked) ! 450: return(0); ! 451: strcpy(curlock, file); ! 452: strcat(curlock, maillock); ! 453: strcpy(locktmp, lockname); ! 454: mktemp(locktmp); ! 455: unlink(locktmp); ! 456: for (;;) { ! 457: f = lock1(locktmp, curlock); ! 458: if (f == 0) { ! 459: locked = 1; ! 460: return(0); ! 461: } ! 462: if (stat(curlock, &sbuf) < 0) ! 463: return(0); ! 464: time(&curtime); ! 465: age = * ((long *) sbuf.modtime); ! 466: if (curtime < age + 30) { ! 467: sleep(5); ! 468: continue; ! 469: } ! 470: unlink(curlock); ! 471: } ! 472: } ! 473: ! 474: /* ! 475: * Remove the mail lock, and note that we no longer ! 476: * have it locked. ! 477: */ ! 478: ! 479: unlock() ! 480: { ! 481: ! 482: if (locked) ! 483: unlink(curlock); ! 484: locked = 0; ! 485: } ! 486: ! 487: /* ! 488: * Attempt to set the lock by creating the temporary file, ! 489: * then doing a link/unlink. If it fails, return -1 else 0 ! 490: */ ! 491: ! 492: lock1(tempfile, name) ! 493: char tempfile[], name[]; ! 494: { ! 495: register int fd; ! 496: ! 497: fd = creat(tempfile, 0); ! 498: if (fd < 0) ! 499: return(-1); ! 500: close(fd); ! 501: if (link(tempfile, name) < 0) { ! 502: unlink(tempfile); ! 503: return(-1); ! 504: } ! 505: unlink(tempfile); ! 506: return(0); ! 507: } ! 508: ! 509: /* ! 510: * Concatenate s2 on the end of s1. S1's space must be large enough. ! 511: * Return s1. ! 512: */ ! 513: ! 514: char * ! 515: strcat(s1, s2) ! 516: register char *s1, *s2; ! 517: { ! 518: register os1; ! 519: ! 520: os1 = s1; ! 521: while (*s1++) ! 522: ; ! 523: *--s1; ! 524: while (*s1++ = *s2++) ! 525: ; ! 526: return(os1); ! 527: } ! 528: ! 529: /* ! 530: * Copy string s2 to s1. s1 must be large enough. ! 531: * return s1 ! 532: */ ! 533: ! 534: char * ! 535: strcpy(s1, s2) ! 536: register char *s1, *s2; ! 537: { ! 538: register os1; ! 539: ! 540: os1 = s1; ! 541: while (*s1++ = *s2++) ! 542: ; ! 543: return(os1); ! 544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.