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

Defined functions

accesss defined in line 403; used 2 times
any defined in line 410; used 2 times
bulkmail defined in line 156; used 1 times
cat defined in line 373; used 2 times
delexit defined in line 353; used 12 times
equal defined in line 361; used 4 times
getput defined in line 388; used 5 times
lock defined in line 437; used 1 times
lock1 defined in line 492; used 1 times
main defined in line 45; never used
prepend defined in line 284; used 3 times
printmail defined in line 118; used 1 times
  • in line 72
sendto defined in line 203; used 1 times
unlock defined in line 479; used 2 times

Defined variables

chew defined in line 41; used 2 times
curlock defined in line 425; used 6 times
errs defined in line 42; used 3 times
inode defined in line 36; used 5 times
lettmp defined in line 38; used 10 times
locked defined in line 426; used 5 times
lockname defined in line 423; used 1 times
locktmp defined in line 424; used 4 times
maillock defined in line 422; used 1 times
preptmp defined in line 39; used 10 times
pwfil defined in line 40; never used

Defined struct's

inode defined in line 23; used 2 times
  • in line 442(2)

Defined macros

DIRECT defined in line 17; never used
GETUID defined in line 19; used 3 times
NOTROOT defined in line 21; used 2 times
RMAILCMD defined in line 18; used 1 times
SIGINT defined in line 16; used 7 times
SPOOLDIR defined in line 20; used 2 times
Last modified: 1981-02-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: ?E00
Valid CSS Valid XHTML 1.0 Strict