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: }

Defined functions

append defined in line 303; used 4 times
bulkmail defined in line 178; used 1 times
delexit defined in line 353; used 9 times
getdate defined in line 239; used 2 times
getput defined in line 362; used 3 times
lock defined in line 409; used 2 times
lock1 defined in line 451; used 1 times
main defined in line 38; never used
printfromline defined in line 225; used 3 times
printmail defined in line 117; used 1 times
  • in line 75
remove defined in line 468; used 2 times
sendto defined in line 261; used 1 times
unlock defined in line 439; used 2 times
writeable defined in line 378; used 3 times

Defined variables

biffaddr defined in line 301; used 5 times
chew defined in line 31; used 2 times
curlock defined in line 398; used 5 times
deleteonly defined in line 35; used 2 times
dflag defined in line 32; used 2 times
errno defined in line 21; used 2 times
errs defined in line 34; used 3 times
lettmp defined in line 29; used 8 times
locked defined in line 399; used 4 times
locktmp defined in line 397; used 4 times
preptmp defined in line 30; used 3 times
remname defined in line 36; used 3 times
saved defined in line 259; used 2 times
shopcnt defined in line 33; used 1 times
  • in line 97

Defined macros

MAILDIR defined in line 27; used 3 times
MAILMODE defined in line 25; used 2 times
MSGSCMD defined in line 26; never used
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2198
Valid CSS Valid XHTML 1.0 Strict