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