|
|
1.1 ! root 1: /* ! 2: * v6mail ! 3: */ ! 4: #include <sysexits.h> ! 5: ! 6: #include <sys/param.h> ! 7: #include <sys/stat.h> ! 8: #include <sys/dir.h> ! 9: #include <sys/times.h> ! 10: #include <ctype.h> ! 11: #include <errno.h> ! 12: #include <pwd.h> ! 13: #include <signal.h> ! 14: ! 15: char *ctime(), *index(), *rindex(), *ctime(), *strcpy(), *getlogin(); ! 16: char *mktemp(), *sprintf(); ! 17: struct passwd *getpwnam(), *getpwuid(); ! 18: time_t time(); ! 19: struct utmp *getutmp(); ! 20: char *getdate(); ! 21: int errno; ! 22: ! 23: #include <stdio.h> ! 24: ! 25: #define MAILMODE 0644 ! 26: #define MSGSCMD "/usr/ucb/msgs" ! 27: #define MAILDIR "/usr/spool/mail" ! 28: ! 29: char lettmp[] = "/tmp/MaXXXXX"; /* keep letter before sending it */ ! 30: char preptmp[] = "/tmp/mbXXXXX"; /* if prepending msg, use this file */ ! 31: int chew; /* if true, strip extra from lines */ ! 32: int dflag; /* if true, don't call sendmail */ ! 33: char shopcnt[30] = "0"; /* hop count parameter for rmt mail */ ! 34: int errs; /* no of errs in sending */ ! 35: char deleteonly; /* if true, just delete mailbox */ ! 36: char remname[50]; /* if non-empty, from line extra */ ! 37: ! 38: main(argc, argv) ! 39: int argc; ! 40: char **argv; ! 41: { ! 42: register int myuid; ! 43: int delexit(); ! 44: char namebuf[128], *sn = NULL, logindir[60]; ! 45: struct passwd *pwd; ! 46: ! 47: (void) mktemp(lettmp); ! 48: (void) mktemp(preptmp); ! 49: (void) unlink(lettmp); ! 50: (void) unlink(preptmp); ! 51: myuid = getuid(); ! 52: logindir[0] = 0; ! 53: sn = getlogin(); ! 54: if (sn == NULL || *sn == 0 || *sn == ' ') { ! 55: pwd = getpwuid(myuid); /* will read passwd file */ ! 56: if (pwd != NULL){ ! 57: sn = pwd->pw_name; ! 58: (void) strcpy(logindir, pwd->pw_dir); ! 59: } ! 60: if (sn == NULL) { ! 61: fprintf(stderr, "Who are you?\n"); ! 62: delexit(EX_OSFILE); ! 63: } ! 64: } ! 65: (void) strcpy(namebuf, sn); ! 66: if (argc < 2) ! 67: goto hitit; ! 68: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) ! 69: switch (argv[0][1]) { ! 70: ! 71: case 'y': ! 72: case 'n': ! 73: argc++, argv--; ! 74: hitit: ! 75: printmail(argc, argv, namebuf, logindir); ! 76: delexit(EX_OK); ! 77: ! 78: case 'r': /* one-arg -r-- -r addr */ ! 79: if (argc < 2) ! 80: continue; ! 81: /* ignore -r if not network or root */ ! 82: if (strcmp("network", namebuf) == 0 || myuid == 0 || ! 83: /*###86 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/ ! 84: /*###86 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/ ! 85: strcmp("uucp", namebuf) == 0 || index('!', argv[1])) { ! 86: (void) strcpy(namebuf, argv[1]); ! 87: chew++; /* eat From lines */ ! 88: } ! 89: else ! 90: (void) strcpy(remname, argv[1]); ! 91: argc--, argv++; ! 92: continue; ! 93: ! 94: case 'h': /* hop count - used by network */ ! 95: if (argc < 2) ! 96: continue; ! 97: (void) strcpy(shopcnt, argv[1]); ! 98: argc--, argv++; ! 99: continue; ! 100: ! 101: case 'd': /* really deliver this message */ ! 102: dflag++; ! 103: continue; ! 104: ! 105: case 'D': /* only delete the invokers mailbox */ ! 106: deleteonly++; ! 107: goto hitit; /* delete mail box, thats all */ ! 108: } ! 109: /* if we are already ignoring signals, catch sigint */ ! 110: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 111: (void) signal(SIGINT, delexit); ! 112: argc++, argv--; ! 113: bulkmail(argc, argv, namebuf); ! 114: delexit(EX_OK); ! 115: } ! 116: ! 117: printmail(argc, argv, name, logindir) ! 118: int argc; ! 119: char **argv; ! 120: char *name, *logindir; ! 121: { ! 122: register int c; ! 123: FILE *fdin; ! 124: char sfnmail[60], mbox[120]; ! 125: struct stat stb; ! 126: ! 127: (void) sprintf(sfnmail, "%s/%s", MAILDIR, name); ! 128: if (deleteonly) { ! 129: remove(sfnmail); ! 130: return; ! 131: } ! 132: fdin = fopen(sfnmail, "r"); ! 133: if (fdin < 0 || fstat(fileno(fdin), &stb) < 0 || stb.st_size == 0) { ! 134: printf("No mail.\n"); ! 135: return; ! 136: } ! 137: if (stb.st_nlink > 1) { ! 138: printf("%s: Too many links.\n", sfnmail); ! 139: return; ! 140: } ! 141: (void) getput(fdin, stdout); ! 142: (void) fclose(fdin); ! 143: (void) fflush(stdout); ! 144: c = 'y'; ! 145: if (argc < 2) { ! 146: if (isatty(0)) { ! 147: printf("Save (y or n) ?"); (void) fflush(stdout); ! 148: c = getchar(); ! 149: } ! 150: } else ! 151: c = argv[1][1]; ! 152: switch (c) { ! 153: ! 154: default: ! 155: delexit(EX_OK); ! 156: /*NOTREACHED*/ ! 157: ! 158: case 'x': ! 159: return; ! 160: ! 161: case 'y': ! 162: (void) sprintf(mbox, "%s/mbox", logindir); ! 163: if (writeable(mbox)) { ! 164: perror(mbox); ! 165: return; ! 166: } ! 167: printf("Saving mail in %s.\n", mbox); ! 168: if (append(sfnmail, mbox, getuid(), getgid()) == 0) ! 169: return; ! 170: /* fall into... */ ! 171: ! 172: case 'n': ! 173: remove(sfnmail); ! 174: return; ! 175: } ! 176: } ! 177: ! 178: bulkmail(argc, argv, from) ! 179: char **argv, *from; ! 180: { ! 181: char linebuf[BUFSIZ]; ! 182: FILE *fdout; ! 183: ! 184: if (dflag == 0) { ! 185: argv[0] = "sendmail"; ! 186: argv[argc] = 0; ! 187: execv("/usr/lib/sendmail", argv); ! 188: perror("/usr/lib/sendmail"); ! 189: _exit(1); ! 190: } ! 191: fdout = fopen(lettmp, "w"); ! 192: if (fdout == NULL) { ! 193: perror(lettmp); ! 194: delexit(EX_OSFILE); ! 195: } ! 196: ! 197: /* ! 198: * If delivering mail from the network via mail -r, ! 199: * Strip the leading line and throw it away, as long ! 200: * as it begins with "From ..." (and preserve the date if poss.) ! 201: */ ! 202: if (chew) { ! 203: if (fgets(linebuf, BUFSIZ, stdin) == 0) ! 204: goto skip; ! 205: if (!strncmp(linebuf, "From ", 5) != 0) ! 206: printfromline(fdout, getdate(linebuf), from); ! 207: else { ! 208: printfromline(fdout, (char *)0, from); ! 209: fprintf(fdout, "%s", linebuf); ! 210: } ! 211: } else ! 212: printfromline(fdout, (char *)0, from); ! 213: skip: ! 214: if (remname[0]) ! 215: fprintf(fdout, "(from %s)\n", remname); ! 216: if (getput(stdin, fdout) == 0) ! 217: delexit(EX_OSERR); ! 218: putc('\n', fdout); ! 219: (void) fclose(fdout); ! 220: while (--argc > 0) ! 221: sendto(*++argv); ! 222: delexit(errs); ! 223: } ! 224: ! 225: printfromline(fdout, date, from) ! 226: FILE *fdout; ! 227: char *date, *from; ! 228: { ! 229: time_t t; ! 230: ! 231: if (date == NULL) { ! 232: t = time((time_t *)0); ! 233: date = ctime(&t); ! 234: } ! 235: fprintf(fdout, "From %s %s", from, date); ! 236: } ! 237: ! 238: /* look over linebuf and return ptr to date, NULL if error */ ! 239: char * ! 240: getdate(linebuf) ! 241: char *linebuf; ! 242: { ! 243: register char *s = linebuf; ! 244: ! 245: /*###244 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/ ! 246: /*###244 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/ ! 247: while (s = index(' ', s)) ! 248: if (!strncmp(s, " Sun ", 5) || ! 249: !strncmp(s, " Mon ", 5) || ! 250: !strncmp(s, " Tue ", 5) || ! 251: !strncmp(s, " Wed ", 5) || ! 252: !strncmp(s, " Thu ", 5) || ! 253: !strncmp(s, " Fri ", 5) || ! 254: !strncmp(s, " Sat ", 5)) ! 255: return (s + 1); ! 256: return (0); ! 257: } ! 258: ! 259: int saved = 0; ! 260: ! 261: sendto(person) ! 262: char *person; ! 263: { ! 264: char mailboxname[BUFSIZ]; ! 265: struct passwd *pwd; ! 266: ! 267: if (index('/', person)) { ! 268: if (!writeable(person)) { ! 269: perror(person); ! 270: return; ! 271: } ! 272: lock(person); ! 273: (void) append(lettmp, person, -1, -1); ! 274: unlock(); ! 275: return; ! 276: } ! 277: pwd = getpwnam(person); ! 278: if (pwd) { ! 279: (void) sprintf(mailboxname, "%s/%s", MAILDIR, person); ! 280: lock(mailboxname); ! 281: (void) append(lettmp, mailboxname, pwd->pw_uid, pwd->pw_gid); ! 282: unlock(); ! 283: return; ! 284: } ! 285: fprintf(stderr, "Can't send to %s.\n", person); ! 286: errs++; ! 287: if (!isatty(0) || saved) ! 288: return; ! 289: saved++; ! 290: if (!writeable("dead.letter")) { ! 291: perror("dead.letter"); ! 292: return; ! 293: } ! 294: printf("Letter saved in 'dead.letter'\n"); ! 295: (void) append(lettmp, "dead.letter", getuid(), getgid()); ! 296: } ! 297: ! 298: #include <sys/socket.h> ! 299: #include <net/in.h> ! 300: ! 301: struct sockaddr_in biffaddr = { AF_INET, IPPORT_BIFFUDP }; ! 302: ! 303: append(from, to, uid, gid) ! 304: char *from, *to; ! 305: int uid, gid; ! 306: { ! 307: register FILE *fdin, *fdout; ! 308: int ret; ! 309: struct stat stb; ! 310: char *cp, buf[100]; int f; ! 311: ! 312: if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) != S_IFREG) { ! 313: fprintf(stderr, "Not a plain file: %s\n", to); ! 314: goto fail; ! 315: } ! 316: fdout = fopen(to, "a"); ! 317: if (fdout == NULL) { ! 318: perror(to); ! 319: goto fail; ! 320: } ! 321: if (uid != -1) { ! 322: (void) chown(to, uid, gid); ! 323: (void) chmod(to, MAILMODE); ! 324: } ! 325: if ((fdin = fopen(from, "r")) == NULL) { ! 326: perror(from); ! 327: return (0); ! 328: } ! 329: cp = rindex(to, '/'); ! 330: if (cp) { ! 331: char *host = "localhost"; ! 332: biffaddr.sin_addr.s_addr = rhost(&host); ! 333: #if vax || pdp11 ! 334: biffaddr.sin_port = ! 335: (biffaddr.sin_port<<8) | ((biffaddr.sin_port>>8) & 0xff); ! 336: #endif ! 337: f = socket(SOCK_DGRAM, 0, 0, 0); ! 338: (void) sprintf(buf, "%s@%d\n", cp+1, ftell(fdout)); ! 339: } ! 340: ret = getput(fdin, fdout); ! 341: (void) fclose(fdin); ! 342: (void) fclose(fdout); ! 343: if (cp && f >= 0) { ! 344: send(f, &biffaddr, buf, strlen(buf)+1); ! 345: (void) close(f); ! 346: } ! 347: return (ret); ! 348: fail: ! 349: errs++; ! 350: return (0); ! 351: } ! 352: ! 353: delexit(status) ! 354: int status; ! 355: { ! 356: ! 357: (void) unlink(lettmp); ! 358: (void) unlink(preptmp); ! 359: exit(status); ! 360: } ! 361: ! 362: getput(fdin, fdout) ! 363: register FILE *fdin, *fdout; ! 364: { ! 365: register int c; ! 366: ! 367: while ((c = getc(fdin)) != EOF) { ! 368: errno = 0; ! 369: putc(c, fdout); ! 370: if (errno) { ! 371: perror("mail"); ! 372: return (0); ! 373: } ! 374: } ! 375: return (1); ! 376: } ! 377: ! 378: writeable(name) ! 379: char *name; ! 380: { ! 381: struct stat stb; ! 382: char *cp; ! 383: int ok; ! 384: ! 385: if (stat(name, &stb) < 0) { ! 386: cp = rindex(name, '/'); ! 387: if (cp) ! 388: *cp = 0; ! 389: ok = access(cp ? "." : name, 2) == 0; ! 390: if (cp) ! 391: *cp = '/'; ! 392: return (ok); ! 393: } ! 394: return (access(name, 2) == 0); ! 395: } ! 396: ! 397: char locktmp[30]; /* Usable lock temporary */ ! 398: char curlock[50]; /* Last used name of lock */ ! 399: int locked; /* To note that we locked it */ ! 400: ! 401: /* ! 402: * Lock the specified mail file by setting the file mailfile.lock. ! 403: * We must, of course, be careful to unlink the lock file by a call ! 404: * to unlock before we stop. The algorithm used here is to see if ! 405: * the lock exists, and if it does, to check its modify time. If it ! 406: * is older than 30 seconds, we assume error and set our own file. ! 407: * Otherwise, we wait for 5 seconds and try again. ! 408: */ ! 409: lock(file) ! 410: char *file; ! 411: { ! 412: register int f; ! 413: struct stat statbuf; ! 414: time_t curtime; ! 415: ! 416: if (locked) ! 417: return; ! 418: (void) sprintf(curlock, "%s%s", file, ".lock"); ! 419: (void) sprintf(locktmp, "%s/tmXXXXXX", MAILDIR); ! 420: (void) mktemp(locktmp); ! 421: (void) unlink(locktmp); ! 422: for (;;) { ! 423: f = lock1(locktmp, curlock); ! 424: if (f == 0) { ! 425: locked = 1; ! 426: return; ! 427: } ! 428: if (stat(curlock, &statbuf) < 0) ! 429: return; ! 430: (void) time(&curtime); ! 431: if (curtime < statbuf.st_mtime + 30) { ! 432: sleep(5); ! 433: continue; ! 434: } ! 435: (void) unlink(curlock); ! 436: } ! 437: } ! 438: ! 439: unlock() ! 440: { ! 441: ! 442: if (locked) ! 443: (void) unlink(curlock); ! 444: locked = 0; ! 445: } ! 446: ! 447: /* ! 448: * Attempt to set the lock by creating the temporary file, ! 449: * then doing a link/unlink. If it fails, return -1 else 0 ! 450: */ ! 451: lock1(tempfile, name) ! 452: char tempfile[], name[]; ! 453: { ! 454: int fno; ! 455: ! 456: fno = creat(tempfile, 0400); ! 457: if (fno < 0) ! 458: return (-1); ! 459: (void) close(fno); ! 460: if (link(tempfile, name) < 0) { ! 461: (void) unlink(tempfile); ! 462: return (-1); ! 463: } ! 464: (void) unlink(tempfile); ! 465: return (0); ! 466: } ! 467: ! 468: remove(sfn) ! 469: char *sfn; ! 470: { ! 471: int i; ! 472: ! 473: if (unlink(sfn) < 0) { ! 474: i = creat(sfn, MAILMODE); ! 475: if (i >= 0) ! 476: (void) close(i); ! 477: } ! 478: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.