1: #include <stdio.h>
   2: #include <pwd.h>
   3: #include <utmp.h>
   4: #include <signal.h>
   5: #include <sys/types.h>
   6: #include <sys/stat.h>
   7: #include <setjmp.h>
   8: #include <whoami.h>
   9: 
  10: #define MSGS        /* pipe mail to "msgs" to /usr/ucb/msgs */
  11: /*copylet flags */
  12:     /*remote mail, add rmtmsg */
  13: #define REMOTE  1
  14:     /* zap header and trailing empty line */
  15: #define ZAP 3
  16: #define ORDINARY 2
  17: #define FORWARD 4
  18: #define LSIZE   256
  19: #define MAXLET  300 /* maximum number of letters */
  20: #define MAILMODE (~0600)        /* mode of created mail */
  21: 
  22: char    line[LSIZE];
  23: char    resp[LSIZE];
  24: struct let {
  25:     long    adr;
  26:     char    change;
  27: } let[MAXLET];
  28: int nlet    = 0;
  29: char    lfil[50];
  30: long    iop, time();
  31: char    lettmp[] = "/tmp/maXXXXX";
  32: char    maildir[] = "/usr/spool/mail/";
  33: char    mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx";
  34: char    dead[] = "dead.letter";
  35: char    forwmsg[] = " forwarded\n";
  36: char    *curlock;
  37: int lockerror;
  38: FILE    *tmpf;
  39: FILE    *malf;
  40: char    *my_name;
  41: struct  passwd  *getpwuid();
  42: int error;
  43: int locked;
  44: int changed;
  45: int forward;
  46: char    from[] = "From ";
  47: long    ftell();
  48: int delete();
  49: char    *ctime();
  50: int flgf;
  51: int flgp;
  52: int delflg = 1;
  53: jmp_buf sjbuf;
  54: char    hostname[32];
  55: 
  56: main(argc, argv)
  57: char **argv;
  58: {
  59:     register i;
  60:     char sobuf[BUFSIZ];
  61: 
  62:     setbuf(stdout, sobuf);
  63:     mktemp(lettmp);
  64:     unlink(lettmp);
  65:     if (my_name == NULL) {
  66:         struct passwd *pwent;
  67:         pwent = getpwuid(getuid());
  68:         if (pwent==NULL)
  69:             my_name = "???";
  70:         else
  71:             my_name = pwent->pw_name;
  72:     }
  73:     if(setjmp(sjbuf)) done();
  74:     for (i = SIGHUP; i <= SIGTERM; i++)
  75:         setsig(i, delete);
  76:     tmpf = fopen(lettmp, "w");
  77:     if (tmpf == NULL) {
  78:         fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
  79:         done();
  80:     }
  81:     if (argv[0][0] != 'r' &&    /* no favors for rmail*/
  82:        (argc == 1 || argv[1][0] == '-'))
  83:         printmail(argc, argv);
  84:     else
  85:         sendmail(argc, argv);
  86:     done();
  87: }
  88: 
  89: setsig(i, f)
  90: int i;
  91: int (*f)();
  92: {
  93:     if(signal(i, SIG_IGN) != SIG_IGN)
  94:         signal(i, f);
  95: }
  96: 
  97: printmail(argc, argv)
  98: char **argv;
  99: {
 100:     int flg, i, j, print;
 101:     char *p, *getarg();
 102: 
 103:     setuid(getuid());
 104:     cat(mailfile, maildir, my_name);
 105:     for (; argc>1; argv++, argc--) {
 106:         if (argv[1][0]=='-') {
 107:             if (argv[1][1]=='q')
 108:                 delflg = 0;
 109:             else if (argv[1][1]=='p') {
 110:                 flgp++;
 111:                 delflg = 0;
 112:             } else if (argv[1][1]=='f') {
 113:                 if (argc>=3) {
 114:                     strcpy(mailfile, argv[2]);
 115:                     argv++;
 116:                     argc--;
 117:                 }
 118:             } else if (argv[1][1]=='r') {
 119:                 forward = 1;
 120:             } else {
 121:                 fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
 122:                 done();
 123:             }
 124:         } else
 125:             break;
 126:     }
 127:     malf = fopen(mailfile, "r");
 128:     if (malf == NULL) {
 129:         fprintf(stdout, "No mail.\n");
 130:         return;
 131:     }
 132:     lock(mailfile);
 133:     copymt(malf, tmpf);
 134:     fclose(malf);
 135:     fclose(tmpf);
 136:     unlock();
 137:     tmpf = fopen(lettmp, "r");
 138: 
 139:     changed = 0;
 140:     print = 1;
 141:     for (i = 0; i < nlet; ) {
 142:         j = forward ? i : nlet - i - 1;
 143:         if(setjmp(sjbuf)) {
 144:             print=0;
 145:         } else {
 146:             if (print)
 147:                 copylet(j, stdout, ORDINARY);
 148:             print = 1;
 149:         }
 150:         if (flgp) {
 151:             i++;
 152:             continue;
 153:         }
 154:         setjmp(sjbuf);
 155:         fprintf(stdout, "? ");
 156:         fflush(stdout);
 157:         if (fgets(resp, LSIZE, stdin) == NULL)
 158:             break;
 159:         switch (resp[0]) {
 160: 
 161:         default:
 162:             fprintf(stderr, "usage\n");
 163:         case '?':
 164:             print = 0;
 165:             fprintf(stderr, "q\tquit\n");
 166:             fprintf(stderr, "x\texit without changing mail\n");
 167:             fprintf(stderr, "p\tprint\n");
 168:             fprintf(stderr, "s[file]\tsave (default mbox)\n");
 169:             fprintf(stderr, "w[file]\tsame without header\n");
 170:             fprintf(stderr, "-\tprint previous\n");
 171:             fprintf(stderr, "d\tdelete\n");
 172:             fprintf(stderr, "+\tnext (no delete)\n");
 173:             fprintf(stderr, "m user\tmail to user\n");
 174:             fprintf(stderr, "! cmd\texecute cmd\n");
 175:             break;
 176: 
 177:         case '+':
 178:         case 'n':
 179:         case '\n':
 180:             i++;
 181:             break;
 182:         case 'x':
 183:             changed = 0;
 184:         case 'q':
 185:             goto donep;
 186:         case 'p':
 187:             break;
 188:         case '^':
 189:         case '-':
 190:             if (--i < 0)
 191:                 i = 0;
 192:             break;
 193:         case 'y':
 194:         case 'w':
 195:         case 's':
 196:             flg = 0;
 197:             if (resp[1] != '\n' && resp[1] != ' ') {
 198:                 printf("illegal\n");
 199:                 flg++;
 200:                 print = 0;
 201:                 continue;
 202:             }
 203:             if (resp[1] == '\n' || resp[1] == '\0')
 204:                 cat(resp+1, "mbox", "");
 205:             for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
 206:                 malf = fopen(lfil, "a");
 207:                 if (malf == NULL) {
 208:                     fprintf(stdout, "mail: cannot append to %s\n", lfil);
 209:                     flg++;
 210:                     continue;
 211:                 }
 212:                 copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
 213:                 fclose(malf);
 214:             }
 215:             if (flg)
 216:                 print = 0;
 217:             else {
 218:                 let[j].change = 'd';
 219:                 changed++;
 220:                 i++;
 221:             }
 222:             break;
 223:         case 'm':
 224:             flg = 0;
 225:             if (resp[1] == '\n' || resp[1] == '\0') {
 226:                 i++;
 227:                 continue;
 228:             }
 229:             if (resp[1] != ' ') {
 230:                 printf("invalid command\n");
 231:                 flg++;
 232:                 print = 0;
 233:                 continue;
 234:             }
 235:             for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
 236:                 if (!sendrmt(j, lfil))  /* couldn't send it */
 237:                     flg++;
 238:             if (flg)
 239:                 print = 0;
 240:             else {
 241:                 let[j].change = 'd';
 242:                 changed++;
 243:                 i++;
 244:             }
 245:             break;
 246:         case '!':
 247:             system(resp+1);
 248:             printf("!\n");
 249:             print = 0;
 250:             break;
 251:         case 'd':
 252:             let[j].change = 'd';
 253:             changed++;
 254:             i++;
 255:             if (resp[1] == 'q')
 256:                 goto donep;
 257:             break;
 258:         }
 259:     }
 260:    donep:
 261:     if (changed)
 262:         copyback();
 263: }
 264: 
 265: copyback()  /* copy temp or whatever back to /usr/spool/mail */
 266: {
 267:     register i, n, c;
 268:     int new = 0;
 269:     struct stat stbuf;
 270: 
 271:     signal(SIGINT, SIG_IGN);
 272:     signal(SIGHUP, SIG_IGN);
 273:     signal(SIGQUIT, SIG_IGN);
 274:     lock(mailfile);
 275:     stat(mailfile, &stbuf);
 276:     if (stbuf.st_size != let[nlet].adr) {   /* new mail has arrived */
 277:         malf = fopen(mailfile, "r");
 278:         if (malf == NULL) {
 279:             fprintf(stdout, "mail: can't re-read %s\n", mailfile);
 280:             done();
 281:         }
 282:         fseek(malf, let[nlet].adr, 0);
 283:         fclose(tmpf);
 284:         tmpf = fopen(lettmp, "a");
 285:         fseek(tmpf, let[nlet].adr, 0);
 286:         while ((c = fgetc(malf)) != EOF)
 287:             fputc(c, tmpf);
 288:         fclose(malf);
 289:         fclose(tmpf);
 290:         tmpf = fopen(lettmp, "r");
 291:         let[++nlet].adr = stbuf.st_size;
 292:         new = 1;
 293:     }
 294:     malf = fopen(mailfile, "w");
 295:     if (malf == NULL) {
 296:         fprintf(stderr, "mail:  can't rewrite %s\n", lfil);
 297:         done();
 298:     }
 299:     n = 0;
 300:     for (i = 0; i < nlet; i++)
 301:         if (let[i].change != 'd') {
 302:             copylet(i, malf, ORDINARY);
 303:             n++;
 304:         }
 305:     fclose(malf);
 306:     if (new)
 307:         fprintf(stdout, "new mail arrived\n");
 308:     unlock();
 309: }
 310: 
 311: copymt(f1, f2)  /* copy mail (f1) to temp (f2) */
 312: FILE *f1, *f2;
 313: {
 314:     long nextadr;
 315: 
 316:     nlet = nextadr = 0;
 317:     let[0].adr = 0;
 318:     while (fgets(line, LSIZE, f1) != NULL) {
 319:         if (isfrom(line))
 320:             let[nlet++].adr = nextadr;
 321:         nextadr += strlen(line);
 322:         fputs(line, f2);
 323:     }
 324:     let[nlet].adr = nextadr;    /* last plus 1 */
 325: }
 326: 
 327: copylet(n, f, type) FILE *f;
 328: {   int ch;
 329:     long k;
 330:     fseek(tmpf, let[n].adr, 0);
 331:     k = let[n+1].adr - let[n].adr;
 332:     while(k-- > 1L && (ch=fgetc(tmpf))!='\n')
 333:         if(type!=ZAP) fputc(ch,f);
 334:     if(type==REMOTE) {
 335:         gethostname(hostname, sizeof (hostname));
 336:         fprintf(f, " remote from %s\n", hostname);
 337:     }
 338:     else if (type==FORWARD)
 339:         fprintf(f, forwmsg);
 340:     else if(type==ORDINARY)
 341:         fputc(ch,f);
 342:     while(k-->1L)
 343:         fputc(ch=fgetc(tmpf), f);
 344:     if(type!=ZAP || ch!= '\n')
 345:         fputc(fgetc(tmpf), f);
 346: }
 347: 
 348: isfrom(lp)
 349: register char *lp;
 350: {
 351:     register char *p;
 352: 
 353:     for (p = from; *p; )
 354:         if (*lp++ != *p++)
 355:             return(0);
 356:     return(1);
 357: }
 358: 
 359: sendmail(argc, argv)
 360: char **argv;
 361: {
 362: 
 363:     time(&iop);
 364:     fprintf(tmpf, "%s%s %s", from, my_name, ctime(&iop));
 365:     iop = ftell(tmpf);
 366:     flgf = 1;
 367:     while (fgets(line, LSIZE, stdin) != NULL) {
 368:         if (line[0] == '.' && line[1] == '\n')
 369:             break;
 370:         if (isfrom(line))
 371:             fputs(">", tmpf);
 372:         fputs(line, tmpf);
 373:         flgf = 0;
 374:     }
 375:     fputs("\n", tmpf);
 376:     nlet = 1;
 377:     let[0].adr = 0;
 378:     let[1].adr = ftell(tmpf);
 379:     fclose(tmpf);
 380:     if (flgf)
 381:         return;
 382:     tmpf = fopen(lettmp, "r");
 383:     if (tmpf == NULL) {
 384:         fprintf(stderr, "mail:  cannot reopen %s for reading\n", lettmp);
 385:         return;
 386:     }
 387:     while (--argc > 0)
 388:         if (!send(0, *++argv))  /* couldn't send to him */
 389:             error++;
 390:     if (error && safefile(dead)) {
 391:         setuid(getuid());
 392:         malf = fopen(dead, "w");
 393:         if (malf == NULL) {
 394:             fprintf(stdout, "mail:  cannot open %s\n", dead);
 395:             fclose(tmpf);
 396:             return;
 397:         }
 398:         copylet(0, malf, ZAP);
 399:         fclose(malf);
 400:         fprintf(stdout, "Mail saved in %s\n", dead);
 401:     }
 402:     fclose(tmpf);
 403: }
 404: 
 405: sendrmt(n, name)
 406: char *name;
 407: {
 408:     FILE *rmf, *popen();
 409:     register char *p;
 410:     char rsys[64], cmd[64];
 411:     register local, pid;
 412:     int ret, sts;
 413: 
 414:     local = 0;
 415:     if (*name=='!')
 416:         name++;
 417:     for(p=rsys; *name!='!'; *p++ = *name++)
 418:         if (*name=='\0') {
 419:             local++;
 420:             break;
 421:         }
 422:     *p = '\0';
 423:     if ((!local && *name=='\0') || (local && *rsys=='\0')) {
 424:         fprintf(stdout, "null name\n");
 425:         return(0);
 426:     }
 427:     if ((pid = fork()) == -1) {
 428:         fprintf(stderr, "mail:  can't create proc for remote\n");
 429:         return(0);
 430:     }
 431:     if (pid) {
 432:         while ((ret = wait(&sts)) != pid) {
 433:             if (ret == -1)
 434:                 return(0);
 435:         }
 436:         return(!sts);
 437:     }
 438:     setuid(getuid());
 439:     if (local)
 440:         sprintf(cmd, "mail %s", rsys);
 441:     else {
 442:         if (index(name+1, '!'))
 443:             sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
 444:         else
 445:             sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
 446:     }
 447:     if ((rmf=popen(cmd, "w")) == NULL)
 448:         exit(1);
 449:     copylet(n, rmf, local?  FORWARD : REMOTE);
 450:     exit(pclose(rmf) != 0);
 451: }
 452: 
 453: send(n, name)   /* send letter n to name */
 454: int n;
 455: char *name;
 456: {
 457:     char file[50];
 458:     register char *p;
 459:     register mask;
 460:     struct passwd *pw, *getpwnam();
 461:     struct stat statb;
 462: #ifdef MSGS
 463:     FILE *pip;
 464:     char line[256];
 465:     int count;
 466: #endif
 467: 
 468:     for (p = name; *p != '!' && *p != '^' && *p != '\0'; p++)
 469:         ;
 470:     if (*p == '!' || *p == '^')
 471:         return(sendrmt(n, name));
 472: #ifdef MSGS
 473: /*
 474:  * modification to call Berkeley 'msgs' program when the 'recipient'
 475:  * is "msgs".  Assumption is that 'n' is 0, no REMOTE, FORWARD, etc.
 476:  * pipe the letter to "msgs -s"  -- pag 11/10/79
 477:  */
 478:     if(!strcmp(name,"msgs"))    /* this letter is really a mesg */
 479:     {
 480:         pip = popen("/usr/ucb/msgs -s", "w");
 481:         if (pip == NULL)
 482:         return(0);
 483:         fseek(tmpf,0L,0);
 484:         count = 0;
 485:         while(fgets(line,256,tmpf) != NULL)
 486:         {
 487:         count++;
 488:         if(count == 2)
 489:         {
 490:             fprintf(pip,"To: msgs\n");
 491:  /*
 492:   * check 2nd line for a Berkeley 'Mail'-added "To:" line....
 493:   * we don't want to add 2 "To:"'s
 494:   */
 495:             if(!strncmp(line,"To: msgs",8))
 496:             continue;
 497:         }
 498:         fputs(line,pip);
 499:         }
 500:         pclose(pip);
 501:         return(1);
 502:     }
 503: #endif
 504:     if ((pw = getpwnam(name)) == NULL) {
 505:         fprintf(stdout, "mail:  can't send to %s\n", name);
 506:         return(0);
 507:     }
 508:     cat(file, maildir, name);
 509:     if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
 510:         strcat(file, "/");
 511:         strcat(file, name);
 512:     }
 513:     mask = umask(MAILMODE);
 514:     if (!safefile(file))
 515:         return(0);
 516:     lock(file);
 517:     malf = fopen(file, "a");
 518:     umask(mask);
 519:     if (malf == NULL) {
 520:         unlock();
 521:         fprintf(stdout, "mail:  cannot append to %s\n", file);
 522:         return(0);
 523:     }
 524:     chown(file, pw->pw_uid, pw->pw_gid);
 525:     copylet(n, malf, ORDINARY);
 526:     fclose(malf);
 527:     unlock();
 528:     return(1);
 529: }
 530: 
 531: delete(i)
 532: {
 533:     setsig(i, delete);
 534:     fprintf(stderr, "\n");
 535:     if(delflg)
 536:         longjmp(sjbuf, 1);
 537:     done();
 538: }
 539: 
 540: done()
 541: {
 542:     if(!lockerror)
 543:         unlock();
 544:     unlink(lettmp);
 545:     exit(error+lockerror);
 546: }
 547: 
 548: lock(file)
 549: char *file;
 550: {
 551:     struct stat stbuf;
 552: 
 553:     if (locked || flgf)
 554:         return;
 555:     if (stat(file, &stbuf)<0)
 556:         return;
 557:     if (stbuf.st_mode&01) {     /* user x bit is the lock */
 558:         if (stbuf.st_ctime+60 >= time((long *)0)) {
 559:             fprintf(stderr, "%s busy; try again in a minute\n", file);
 560:             lockerror++;
 561:             done();
 562:         }
 563:     }
 564:     locked = stbuf.st_mode & ~01;
 565:     curlock = file;
 566:     chmod(file, stbuf.st_mode|01);
 567: }
 568: 
 569: unlock()
 570: {
 571:     if (locked)
 572:         chmod(curlock, locked);
 573:     locked = 0;
 574: }
 575: 
 576: cat(to, from1, from2)
 577: char *to, *from1, *from2;
 578: {
 579:     int i, j;
 580: 
 581:     j = 0;
 582:     for (i=0; from1[i]; i++)
 583:         to[j++] = from1[i];
 584:     for (i=0; from2[i]; i++)
 585:         to[j++] = from2[i];
 586:     to[j] = 0;
 587: }
 588: 
 589: char *getarg(s, p)  /* copy p... into s, update p */
 590: register char *s, *p;
 591: {
 592:     while (*p == ' ' || *p == '\t')
 593:         p++;
 594:     if (*p == '\n' || *p == '\0')
 595:         return(NULL);
 596:     while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
 597:         *s++ = *p++;
 598:     *s = '\0';
 599:     return(p);
 600: }
 601: 
 602: safefile(f)
 603:     char *f;
 604: {
 605:     struct stat statb;
 606: 
 607: #ifdef  UCB_SYMLINKS
 608:     if (lstat(f, &statb) < 0)
 609: #else
 610:     if (stat(f, &statb) < 0)
 611: #endif
 612:         return(1);
 613:     if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
 614:         fprintf(stderr, "mail:  %s has more than one link or is a symbolic link\n", f);
 615:         return(0);
 616:     }
 617:     return(1);
 618: }

Defined functions

cat defined in line 576; used 3 times
copyback defined in line 265; used 1 times
copylet defined in line 327; used 6 times
copymt defined in line 311; used 1 times
delete defined in line 531; used 3 times
done defined in line 540; used 8 times
getarg defined in line 589; used 3 times
isfrom defined in line 348; used 2 times
lock defined in line 548; used 3 times
main defined in line 56; never used
printmail defined in line 97; used 1 times
  • in line 83
safefile defined in line 602; used 2 times
send defined in line 453; used 1 times
sendmail defined in line 359; used 1 times
  • in line 85
sendrmt defined in line 405; used 2 times
setsig defined in line 89; used 2 times
unlock defined in line 569; used 5 times

Defined variables

changed defined in line 44; used 6 times
curlock defined in line 36; used 2 times
dead defined in line 34; used 4 times
delflg defined in line 52; used 3 times
error defined in line 42; used 3 times
flgf defined in line 50; used 4 times
flgp defined in line 51; used 2 times
forward defined in line 45; used 2 times
forwmsg defined in line 35; used 1 times
from defined in line 46; used 2 times
hostname defined in line 54; used 3 times
iop defined in line 30; used 3 times
let defined in line 27; used 16 times
lettmp defined in line 31; used 10 times
lfil defined in line 29; used 6 times
line defined in line 22; used 13 times
locked defined in line 43; used 5 times
lockerror defined in line 37; used 3 times
maildir defined in line 32; used 2 times
mailfile defined in line 33; used 9 times
my_name defined in line 40; used 5 times
nlet defined in line 28; used 11 times
resp defined in line 23; used 15 times
sjbuf defined in line 53; used 4 times

Defined struct's

let defined in line 24; never used

Defined macros

FORWARD defined in line 17; used 2 times
LSIZE defined in line 18; used 5 times
MAILMODE defined in line 20; used 1 times
MAXLET defined in line 19; used 1 times
  • in line 27
MSGS defined in line 10; used 2 times
ORDINARY defined in line 16; used 5 times
REMOTE defined in line 13; used 2 times
ZAP defined in line 15; used 4 times
Last modified: 1983-09-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2525
Valid CSS Valid XHTML 1.0 Strict