Annotation of researchv8dc/cmd/mail/mail.c, revision 1.1.1.1

1.1       root        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 <time.h>
                      8: #include <sys/timeb.h>
                      9: #include <setjmp.h>
                     10: #include <ctype.h>
                     11: #include <dir.h>
                     12: 
                     13: 
                     14: #define SMTP "/usr/lib/uucp/smtp"
                     15: 
                     16: /*copylet flags */
                     17:        /*remote mail, add rmtmsg */
                     18: #define REMOTE  1
                     19: #define INTERNET  4
                     20:        /* zap header and trailing empty line */
                     21: #define ZAP    3
                     22: #define ORDINARY 2
                     23: #define SENDING 5
                     24: #define LSIZE   256
                     25: #define MAXLET  1000     /* maximum number of letters */
                     26: #define MAILMODE (~0644)               /* mode of created mail */
                     27: #define FLIST "/etc/forwardlist"
                     28: #define TMPNAME "/tmp/maXXXXX"
                     29: 
                     30: /* definitions for inet gateways */
                     31: struct igateway {
                     32:        char    *id;            /* network identifier */
                     33:        char    *addr;          /* address translation */
                     34:        char    *via;           /* machine that talks to gateway */
                     35:        char    *cmd;           /* command for gateway */
                     36: };
                     37: struct igateway igates[] = {
                     38:        "arpa_or_csnet", ".csnet-relay", "research", "/usr/mmdf/lib/mail",
                     39:        "csnet", ".csnet.csnet-relay", "research", "/usr/mmdf/lib/mail",
                     40:        "arpa", ".arpa.csnet-relay", "research", "/usr/mmdf/lib/mail",
                     41:        "acsnet", "", "research", "/usr/ACSnet/bin/inject",
                     42: };
                     43: #define NIGATES 4
                     44: unsigned int igate;            /* offset into igates (csnet by default) */
                     45: 
                     46: 
                     47: char    line[LSIZE];
                     48: char   resp[LSIZE];
                     49: struct let {
                     50:        long    adr;
                     51:        char    change;
                     52: } let[MAXLET];
                     53: int    nlet    = 0;
                     54: char   lfil[50];
                     55: char   *stringin();
                     56: FILE   *popen();
                     57: char   *getenv();
                     58: char    tmpname[] = TMPNAME;
                     59: char   lettmp[sizeof(TMPNAME)];
                     60: char   maildir[] = "/usr/spool/mail/";
                     61: char   mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx";
                     62: char   dead[] = "dead.letter";
                     63: char   whoami[] = "/etc/whoami";
                     64: #define FRWRD  "Forward to "
                     65: char   *thissys = "";
                     66: FILE   *tmpf;
                     67: FILE   *malf;
                     68: char   *my_name;
                     69: char   real_name[512];
                     70: char   *getlogin();
                     71: struct passwd  *getpwuid();
                     72: char   *strchr();
                     73: int    error;
                     74: int    changed;
                     75: int    forward;
                     76: int    onatty;
                     77: char   from[] = "From ";
                     78: long   ftell();
                     79: int    delete();
                     80: int    savdead();
                     81: int    (*saveint)();
                     82: int    (*setsig())();
                     83: char   *strcpy();
                     84: char   *strcat();
                     85: char   *mktemp();
                     86: char   *ctime();
                     87: long   time();
                     88: int    flgf;
                     89: int    flgp;
                     90: int    delflg = 1;
                     91: int    rflg;
                     92: int    frominet;
                     93: int    normtf;
                     94: jmp_buf        sjbuf;
                     95: char   dev[] = "/dev/";
                     96: 
                     97: void lock(), unlock();
                     98: 
                     99: main(argc, argv)
                    100: char **argv;
                    101: {
                    102:        static char sobuf[BUFSIZ];
                    103:        char wsysname[32];
                    104:        int f;
                    105:        char *prog;
                    106:        char *basename();
                    107: 
                    108:        if (argc == 2 && (argv[1][0] == '-' && argv[1][1]=='n')) {
                    109:                struct stat s;
                    110:                char *ttyname();
                    111:                char *p;
                    112: 
                    113:                fstat(2,&s);
                    114:                setgid(getgid());
                    115:                setuid(getuid());
                    116:                if ((p = ttyname(2)) && *p)
                    117:                        chmod(p, s.st_mode ^ S_IEXEC);
                    118:                exit(0);
                    119:        }
                    120:        prog = basename(argv[0]);
                    121:        normtf = prog[0]=='r';
                    122:        frominet = prog[0]=='c';
                    123:        rflg =  prog[0]=='r' || frominet;
                    124:        setbuf(stdout, sobuf);
                    125:        strcpy(lettmp, tmpname);
                    126:        mktemp(lettmp);
                    127:        unlink(lettmp);
                    128:        my_name = getlogin();
                    129:        if (my_name==NULL)
                    130:                my_name = "daemon";
                    131:        f = open(whoami, 0);
                    132:        if (f>=0) {
                    133:                wsysname[0] = '\0';
                    134:                read(f, wsysname, 32);
                    135:                if (strchr(wsysname, '\n')) {
                    136:                        *strchr(wsysname, '\n') = '\0';
                    137:                        thissys = wsysname;
                    138:                }
                    139:                close(f);
                    140:        }
                    141:        if(*thissys == 0)
                    142:                fprintf(stderr, "mail: bad data from %s\n", whoami);
                    143:        if(setjmp(sjbuf))
                    144:                done();
                    145:        setsig(SIGINT, delete);
                    146:        setsig(SIGHUP, delete);
                    147:        setsig(SIGKILL, delete);
                    148:        tmpf = fopen(lettmp, "w");
                    149:        if (tmpf == NULL) {
                    150:                fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
                    151:                done();
                    152:        }
                    153:        chmod(lettmp, 0600);
                    154:        chown(lettmp, getuid(), getgid());
                    155:        if( !rflg &&                    /* no favors for rmail*/
                    156:           (argc == 1 || (argv[1][0] == '-' && argv[1][1]!='R')))
                    157:                printmail(argc, argv);
                    158:        else
                    159:                sendmail(argc, argv);
                    160:        done();
                    161: }
                    162: 
                    163: char *
                    164: basename(file)
                    165: char *file;
                    166: {
                    167:        char *base;
                    168:        char *strrchr();
                    169: 
                    170:        if ((base = strrchr(file, '/')) != NULL)
                    171:                base++;         /* past '/' */
                    172:        else
                    173:                base = file;
                    174:        return (base);
                    175: }
                    176: 
                    177: int (*setsig(i, f))()
                    178: int i;
                    179: int (*f)();
                    180: {
                    181:        register int (*rc)();
                    182: 
                    183:        if ((rc = signal(i, SIG_IGN))!=SIG_IGN)
                    184:                signal(i, f);
                    185:        return(rc);
                    186: }
                    187: 
                    188: sig_ign()
                    189: {
                    190:        signal(SIGHUP, SIG_IGN);
                    191:        signal(SIGINT, SIG_IGN);
                    192:        signal(SIGQUIT, SIG_IGN);
                    193:        signal(SIGTERM, SIG_IGN);
                    194: }
                    195: 
                    196: printmail(argc, argv)
                    197: char **argv;
                    198: {
                    199:        int flg, i, j, print;
                    200:        struct stat stbuf;
                    201:        char *p, *getarg();
                    202:        char fbuf[256];
                    203:        FILE *pipf;
                    204: 
                    205:        setgid(getgid());
                    206:        setuid(getuid());
                    207:        cat(mailfile, maildir, my_name);
                    208:        for (; argc>1; argv++, argc--) {
                    209:                if (argv[1][0]=='-') {
                    210:                        if (argv[1][1]=='p') {
                    211:                                flgp++;
                    212:                                delflg = 0;
                    213:                        } else if (argv[1][1]=='f') {
                    214:                                if (argc>=3) {
                    215:                                        strcpy(mailfile, argv[2]);
                    216:                                        argv++;
                    217:                                        argc--;
                    218:                                }
                    219:                        } else if (argv[1][1]=='r') {
                    220:                                forward = 1;
                    221:                        } else {
                    222:                                fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
                    223:                                done();
                    224:                        }
                    225:                } else
                    226:                        break;
                    227:        }
                    228:        if (stat(mailfile, &stbuf) < 0 || stbuf.st_size == 0L) {
                    229:                printf("No mail.\n");
                    230:                return;
                    231:        }
                    232:        malf = fopen(mailfile, "r");
                    233:        if (malf == NULL) {
                    234:                fprintf(stderr, "mail: cannot read %s.\n", mailfile);
                    235:                return;
                    236:        }
                    237:        lock(mailfile);
                    238:        if(areforwarding(mailfile, fbuf)) {
                    239:                printf("Your mail is being forwarded to ");
                    240:                fseek(malf, (long)(sizeof(FRWRD) - 1), 0);
                    241:                fgets(fbuf, sizeof(fbuf), malf);
                    242:                printf("%s", fbuf);
                    243:                if(getc(malf) != EOF)
                    244:                        printf("and your mailbox contains extra stuff\n");
                    245:                unlock();
                    246:                return;
                    247:        }
                    248:        copymt(malf, tmpf);
                    249:        fclose(malf);
                    250:        fclose(tmpf);
                    251:        unlock();
                    252:        tmpf = fopen(lettmp, "r");
                    253: 
                    254:        changed = 0;
                    255:        print = 1;
                    256:        for (i = 0; i < nlet; ) {
                    257:                j = forward ? i : nlet - i - 1;
                    258:                if(setjmp(sjbuf) == 0) {
                    259:                        if (print)
                    260:                                copylet(j, stdout, ORDINARY, (char *)NULL);
                    261:                        print = 1;
                    262:                }
                    263:                if (flgp) {
                    264:                        i++;
                    265:                        continue;
                    266:                }
                    267:                setjmp(sjbuf);
                    268:                printf("? ");
                    269:                fflush(stdout);
                    270:                if (fgets(resp, LSIZE, stdin) == NULL)
                    271:                        break;
                    272:                switch (resp[0]) {
                    273: 
                    274:                default:
                    275:                        printf("usage\n");
                    276:                case '?':
                    277:                        print = 0;
                    278:                        printf("q\tquit\n");
                    279:                        printf("x\texit without changing mail\n");
                    280:                        printf("p\tprint\n");
                    281:                        printf("s[file]\tsave (default mbox)\n");
                    282:                        printf("-\tprint previous\n");
                    283:                        printf("d\tdelete\n");
                    284:                        printf("+\tnext (no delete)\n");
                    285:                        printf("m user\tmail to user\n");
                    286:                        printf("! cmd\texecute cmd\n");
                    287:                        break;
                    288: 
                    289:                case '+':
                    290:                case 'n':
                    291:                case '\n':
                    292:                        i++;
                    293:                        break;
                    294:                case 'x':
                    295:                        changed = 0;
                    296:                case 'q':
                    297:                        goto donep;
                    298:                case 'p':
                    299:                        break;
                    300:                case '^':
                    301:                case '-':
                    302:                        if (--i < 0)
                    303:                                i = 0;
                    304:                        break;
                    305:                case 'y':
                    306:                case 'w':
                    307:                case 's':
                    308:                        flg = 0;
                    309:                        if (resp[1] != '\n' && resp[1] != ' ') {
                    310:                                printf("invalid\n");
                    311:                                flg++;
                    312:                                print = 0;
                    313:                                continue;
                    314:                        }
                    315:                        if (resp[1] == '\n' || resp[1] == '\0') {
                    316:                                p = getenv("HOME");
                    317:                                if(p != 0)
                    318:                                        cat(resp+1, p, "/mbox");
                    319:                                else
                    320:                                        cat(resp+1, "", "mbox");
                    321:                        }
                    322:                        for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
                    323:                                malf = fopen(lfil, "a");
                    324:                                if (malf == NULL) {
                    325:                                        fprintf(stderr, "mail: cannot append to %s\n", lfil);
                    326:                                        flg++;
                    327:                                        continue;
                    328:                                }
                    329:                                copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY,
                    330:                                    (char *)NULL);
                    331:                                fclose(malf);
                    332:                        }
                    333:                        if (flg)
                    334:                                print = 0;
                    335:                        else {
                    336:                                let[j].change = 'd';
                    337:                                changed++;
                    338:                                i++;
                    339:                        }
                    340:                        break;
                    341:                case 'm':
                    342:                        flg = 0;
                    343:                        if (resp[1] == '\n' || resp[1] == '\0') {
                    344:                                i++;
                    345:                                continue;
                    346:                        }
                    347:                        if (resp[1] != ' ') {
                    348:                                printf("invalid\n");
                    349:                                flg++;
                    350:                                print = 0;
                    351:                                continue;
                    352:                        }
                    353:                        strcpy(fbuf, "mail ");
                    354:                        strcat(fbuf, resp+1);
                    355:                        /* fork so that mail becomes super-user again */
                    356:                        pipf = popen(fbuf, "w");
                    357:                        if(pipf == NULL) {
                    358:                                fprintf(stderr, "mail: can't fork to remail\n");
                    359:                                flg++;
                    360:                                continue;
                    361:                        }
                    362:                        copylet(j, pipf, SENDING, (char *)NULL);
                    363:                        flg |= pclose(pipf);
                    364:                        if (flg)
                    365:                                print = 0;
                    366:                        else {
                    367:                                let[j].change = 'd';
                    368:                                changed++;
                    369:                                i++;
                    370:                        }
                    371:                        break;
                    372:                case '!':
                    373:                        system(resp+1);
                    374:                        printf("!\n");
                    375:                        print = 0;
                    376:                        break;
                    377:                case 'd':
                    378:                        let[j].change = 'd';
                    379:                        changed++;
                    380:                        i++;
                    381:                        if (resp[1] == 'q')
                    382:                                goto donep;
                    383:                        break;
                    384:                }
                    385:        }
                    386:    donep:
                    387:        if (changed)
                    388:                copyback();
                    389: }
                    390: 
                    391: copyback()      /* copy temp or whatever back to /usr/spool/mail */
                    392: {
                    393:        register i, c;
                    394:        register int new = 0;
                    395:        struct stat stbuf;
                    396: 
                    397:        sig_ign();
                    398:        lock(mailfile);
                    399:        stat(mailfile, &stbuf);
                    400:        if (stbuf.st_size != let[nlet].adr) {   /* new mail has arrived */
                    401:                malf = fopen(mailfile, "r");
                    402:                if (malf == NULL) {
                    403:                        fprintf(stderr, "mail: can't re-read %s\n", mailfile);
                    404:                        done();
                    405:                }
                    406:                fseek(malf, let[nlet].adr, 0);
                    407:                fclose(tmpf);
                    408:                tmpf = fopen(lettmp, "a");
                    409:                fseek(tmpf, let[nlet].adr, 0);
                    410:                while ((c = fgetc(malf)) != EOF)
                    411:                        fputc(c, tmpf);
                    412:                fclose(malf);
                    413:                fclose(tmpf);
                    414:                tmpf = fopen(lettmp, "r");
                    415:                let[++nlet].adr = stbuf.st_size;
                    416:                new = 1;
                    417:        }
                    418:        malf = fopen(mailfile, "w");
                    419:        if (malf == NULL) {
                    420:                fprintf(stderr, "mail: can't rewrite %s\n", mailfile);
                    421:                done();
                    422:        }
                    423:        for (i = 0; i < nlet; i++)
                    424:                if (let[i].change != 'd') {
                    425:                        copylet(i, malf, ORDINARY, (char *)NULL);
                    426:                }
                    427:        fclose(malf);
                    428:        if (new)
                    429:                printf("new mail arrived\n");
                    430:        unlock();
                    431: }
                    432: 
                    433: copymt(f1, f2)  /* copy mail (f1) to temp (f2) */
                    434: FILE *f1, *f2;
                    435: {
                    436:        long nextadr;
                    437: 
                    438:        nlet = nextadr = 0;
                    439:        let[0].adr = 0;
                    440:        while (fgets(line, LSIZE, f1) != NULL) {
                    441:                if (isfrom(line)) {
                    442:                        let[nlet++].adr = nextadr;
                    443:                        if (nlet > MAXLET) {
                    444:                                fprintf (stderr, "mail: too many letters\n");
                    445:                                unlock();
                    446:                                exit(1);
                    447:                        }
                    448:                }
                    449:                nextadr += strlen(line);
                    450:                fputs(line, f2);
                    451:        }
                    452:        let[nlet].adr = nextadr;        /* last plus 1 */
                    453: }
                    454: 
                    455: copylet(n, f, type, postmark)
                    456: FILE *f;
                    457: char *postmark;
                    458: {
                    459:        long k;
                    460:        register ch;
                    461:        char *inetheader();
                    462: 
                    463:        fseek(tmpf, let[n].adr, 0);
                    464:        k = let[n+1].adr - let[n].adr;
                    465:        if (postmark && type != ZAP) {
                    466:                if (type == INTERNET)
                    467:                        postmark = inetheader (postmark);
                    468:                fputs(postmark, f);
                    469:                if (type==REMOTE)
                    470:                        fprintf(f, " remote from %s", thissys);
                    471:                fputc('\n', f);
                    472:        }
                    473:        while (k>0) {
                    474:                ch = fgetc(tmpf);
                    475:                if (ch == EOF)
                    476:                        break;
                    477:                fputc(ch, f);
                    478:                k--;
                    479:        }
                    480: }
                    481: 
                    482: areforwarding(s, sendto)
                    483: char *s, *sendto;
                    484: {
                    485:        FILE *fd;
                    486:        char fbuf[64], *p, *sp;
                    487: 
                    488:        fd = fopen(s, "r");
                    489:        if(fd == NULL)
                    490:                return(0);
                    491:        fbuf[0] = '\0';
                    492:        fgets(fbuf, sizeof(fbuf), fd);
                    493:        if (p = stringin(FRWRD, fbuf)) {
                    494:                while (*p == ' ')
                    495:                        p++;
                    496:                sp = sendto;
                    497:                while (*p && *p!='\n')
                    498:                        *sp++ = *p++;
                    499:                *sp = '\0';
                    500:                fclose(fd);
                    501:                return(*sendto != 0);
                    502:        }
                    503:        fclose(fd);
                    504:        return(0);
                    505: }
                    506: 
                    507: isfrom(lp)
                    508: register char *lp;
                    509: {
                    510:        return(strncmp(lp, from, 5)==0);
                    511: }
                    512: 
                    513: sendmail(argc, argv)
                    514: char **argv;
                    515: {
                    516:        char *asctime();
                    517:        struct timeb timbuf;
                    518:        struct tm *bp, *localtime();
                    519:        char *tp, *zp, postmark[512];
                    520:        char *timezone();
                    521:        int rrrflg=0;
                    522:        long newpost();
                    523: 
                    524:        while (argv[1][0]=='-') {
                    525:                switch(argv[1][1]) {
                    526:                case 'R': /* return receipt */
                    527:                        rrrflg = 1;
                    528:                }
                    529:                argc--; argv++;
                    530:        }
                    531:        ftime(&timbuf);
                    532:        bp = localtime(&timbuf.time);
                    533:        tp = asctime(bp);
                    534:        zp = timezone(timbuf.timezone, bp->tm_isdst);
                    535:        onatty = isatty(0);
                    536:        sprintf(postmark, "%s%s %.16s %.3s %.4s%s",from, my_name, tp, zp, tp+20,
                    537:            rrrflg?" (RRR)":"");
                    538:        flgf = 1;
                    539:        saveint = setsig(SIGINT, savdead);
                    540:        while (fgets(line, LSIZE, stdin) != NULL) {
                    541:                if (line[0] == '.' && line[1] == '\n' && onatty)
                    542:                        break;
                    543:                if (isfrom(line))
                    544:                        fputs(">", tmpf);
                    545:                fputs(line, tmpf);
                    546:                flgf = 0;
                    547:        }
                    548:        setsig(SIGINT, saveint);
                    549:        if (line[0]!='\n' && error==0)
                    550:                fputs("\n", tmpf);
                    551:        nlet = 1;
                    552:        let[0].adr = 0;
                    553:        let[1].adr = ftell(tmpf);
                    554:        fclose(tmpf);
                    555:        if (flgf)
                    556:                return;
                    557:        tmpf = fopen(lettmp, "r");
                    558:        if (tmpf == NULL) {
                    559:                fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
                    560:                return;
                    561:        }
                    562:        let[0].adr = newpost(postmark);
                    563:        if (error == 0)
                    564:                while (--argc > 0) {
                    565:                        if (!send(0, *++argv, 0, postmark))
                    566:                                error++;
                    567:                }
                    568:        if (error && onatty) {
                    569:                setgid(getgid());
                    570:                setuid(getuid());
                    571:                malf = fopen(dead, "w");
                    572:                if (malf == NULL) {
                    573:                        fprintf(stderr, "mail: cannot open %s\n", dead);
                    574:                        fclose(tmpf);
                    575:                        return;
                    576:                }
                    577:                copylet(0, malf, ZAP, (char *)NULL);
                    578:                fclose(malf);
                    579:                printf("Mail saved in %s\n", dead);
                    580:        }
                    581:        fclose(tmpf);
                    582: }
                    583: 
                    584: long
                    585: newpost(pm)
                    586: char *pm;
                    587: {
                    588:        long inetpost(), unixpost();
                    589:        if (frominet)
                    590:                return inetpost(pm);
                    591:        else
                    592:                return unixpost(pm);
                    593: }
                    594: 
                    595: long
                    596: inetpost(pm)
                    597: char *pm;
                    598: {
                    599:        char line[512], date[64], *lp;
                    600: 
                    601:        /* get default source  and date */
                    602:        lp = strchr(pm+5, ' ');
                    603:        strcpy(date, lp);
                    604: 
                    605:        /* RFC 822 (or similar) */
                    606:        /* construct the "From " line from the "From: " line */
                    607:        while (fgets(line, sizeof(line), tmpf) != NULL) {
                    608:                line[strlen(line)-1] = '\0';
                    609: 
                    610:                /* pick up from field */
                    611:                if (strncmp("From: ", line, 6) == 0) {
                    612:                        lp = strchr(line+6, ' ');
                    613:                        if (lp)
                    614:                                *lp = '\0'; 
                    615:                        sprintf(pm, "From %s", line+6);
                    616:                }
                    617: 
                    618:                /* pick up date field */
                    619:                if (strncmp("Date: ", line, 6) == 0)
                    620:                        strcpy(date, line+5);
                    621: 
                    622:                /* stop if we're out of header */
                    623:                if (strchr(line, ':') == NULL && line[0] != ' '
                    624:                    && line[0] != '\t')
                    625:                        break;
                    626:        }
                    627:        strcpy(real_name, pm+5);
                    628:        strcat(pm, date);
                    629:        return(0);
                    630: }
                    631: 
                    632: long
                    633: unixpost(pm)
                    634: char *pm;
                    635: {
                    636:        long n = 0;
                    637:        char line[512], *cp, *lp;
                    638:        char rmtlist[512];
                    639: 
                    640:        /* UNIX mail */
                    641:        /* construct the "From " line from the existing ones */
                    642:        rmtlist[0] = '\0';
                    643:        while (fgets(line, sizeof(line), tmpf) != NULL) {
                    644: 
                    645:                /* stop if we run out of header */
                    646:                if (stringin("From ", line)==NULL
                    647:                    && stringin(">From ", line)==NULL)
                    648:                        break;
                    649:                if ((cp = stringin(" remote from ", line))==NULL)
                    650:                        break;
                    651: 
                    652:                /* get name of remote system and add to rmtlist */
                    653:                line[strlen(line)-1] = '\0';
                    654:                if (okrmt(cp) && n==0)
                    655:                        normtf = 0;
                    656:                *(cp - sizeof(" remote from ") + 1) = '\0';
                    657:                strcpy(pm, line[0] == '>' ? line + 1 : line);
                    658:                strcat(rmtlist, cp);
                    659:                strcat(rmtlist, "!");
                    660:                n = ftell(tmpf);
                    661:        }
                    662: 
                    663:        /* tack sender's name and date onto the list of remote machines */
                    664:        strcpy(line, pm);
                    665:        sprintf(pm, "From %s%s", rmtlist, line+5);
                    666:        if ((cp = strchr(line+5, ' ')) != NULL)
                    667:                *cp = '\0';
                    668:        sprintf(real_name, "%s%s", rmtlist, line+5);
                    669:        return(n);
                    670: }
                    671: 
                    672: char *
                    673: stringin(str, line)
                    674: char *str, *line;
                    675: {
                    676:        register char *sp, *lp;
                    677: 
                    678:        while (*line) {
                    679:                sp = str;
                    680:                lp = line++;
                    681:                for (;;) {
                    682:                        if (*sp != *lp) {
                    683:                                if (*sp=='\0')
                    684:                                        return(lp);
                    685:                                break;
                    686:                        }
                    687:                        sp++;
                    688:                        lp++;
                    689:                }
                    690:        }
                    691:        return(NULL);
                    692: }
                    693: 
                    694: /*
                    695:  *     Return nonzero if forwarding is allowed to the system
                    696:  *     named in the string at "cp".  If we can't read the file
                    697:  *     which contains the systems, assume blanket forwarding.
                    698:  */
                    699: okrmt(cp)
                    700: char *cp;
                    701: {
                    702:        register FILE *fp;
                    703:        char buf[20];
                    704: 
                    705:        /* try to open the file; allow forwarding on failure */
                    706:        fp = fopen (FLIST, "r");
                    707:        if (fp == NULL)
                    708:                return 1;
                    709: 
                    710:        /* one iteration per system name in the file */
                    711:        while (fgets (buf, sizeof buf, fp) != NULL) {
                    712:                buf[strlen(buf)-1] = '\0';
                    713:                if (strcmp (buf, cp) == 0) {
                    714:                        /* found it, allow forwarding */
                    715:                        fclose (fp);
                    716:                        return 1;
                    717:                }
                    718:        }
                    719: 
                    720:        /* didn't find it, prohibit forwarding */
                    721:        fclose (fp);
                    722:        return 0;
                    723: }
                    724: 
                    725: savdead()
                    726: {
                    727:        setsig(SIGINT, saveint);
                    728:        error++;
                    729: }
                    730: 
                    731: sendrmt(n, name, postmark)
                    732: char *name, *postmark;
                    733: {
                    734:        FILE *rmf;
                    735:        register char *p, *q, *rmtid;
                    736:        char cmd[512], buf[512];
                    737:        static forked;
                    738: 
                    739:        strcpy(buf, name);
                    740:        rmtid = strchr(name, '!');
                    741:        if (rmtid == NULL || rmtid[1]=='\0') {
                    742:                fprintf(stderr, "mail: bad remote name\n");
                    743:                return(0);
                    744:        }
                    745:        *rmtid++ = '\0';
                    746:        if (normtf)
                    747:                for (p = q = &buf[0]; (p = strchr(q, '!')) && p[1] != '\0';
                    748:                    q = p + 1) {
                    749:                        *p = '\0';
                    750:                        if (!okrmt(q)) {
                    751:                                *--rmtid = '!';
                    752:                                refuse(n, name, postmark,
                    753:                                   "forwarding to this system disallowed");
                    754:                                return(1);
                    755:                        }
                    756:                }
                    757:        if(onatty & !forked) {  /* fork off remote send to avoid user tedium */
                    758:                int p = fork();
                    759:                if(p == 0) {
                    760:                        sig_ign();
                    761:                        forked = 1;
                    762:                } else if(p != -1)
                    763:                        exit(0);
                    764:        }
                    765:        if(access(SMTP, 0) != -1){
                    766:                sprintf(cmd, "exec %s %s %s", SMTP, name, rmtid);
                    767:                if((rmf = popen(cmd, "w")) != NULL){
                    768:                        copylet(n, rmf, REMOTE, postmark);
                    769:                        if(pclose(rmf) == 0) return(1);
                    770:                }
                    771:        }
                    772:        sprintf(cmd, "exec /usr/bin/uux - -a %s %s!rmail \\(%s\\)",
                    773:                        real_name, name, rmtid);
                    774:        if ((rmf=popen(cmd, "w")) == NULL) {
                    775:                fprintf(stderr, "mail: can't pipe to uux\n");
                    776:                exit(1);
                    777:        }
                    778:        copylet(n, rmf, REMOTE, postmark);
                    779:        *--rmtid = '!';
                    780:        logsend(name, postmark, "remote");
                    781:        return(pclose(rmf)==0);
                    782: }
                    783: 
                    784: 
                    785: 
                    786: send(n, name, level, postmark) /* send letter n to name */
                    787: int n;
                    788: char *name, *postmark;
                    789: {
                    790:        char file[512];
                    791:        register mask;
                    792:        struct passwd *pw, *getpwnam();
                    793:        struct stat stbuf;
                    794:        char sendto[256];
                    795:        char inetaddr[256];
                    796:        int exists;
                    797: 
                    798: 
                    799:        if(level > 20) {
                    800:                fprintf(stderr, "mail: unbounded forwarding\n");
                    801:                return(0);
                    802:        }
                    803:        if (strcmp(name, "-") == 0)
                    804:                return(1);
                    805:        if (strchr(name, '!'))
                    806:                return(sendrmt(n, name, postmark));
                    807:        if (strchr(name, '/')) {
                    808:                fprintf(stderr, "mail: illegal name %s\n", name);
                    809:                return(0);
                    810:        }
                    811:        cat(file, maildir, name);
                    812:        if(areforwarding(file, sendto)) {
                    813:                int rf, sval;
                    814:                rf = normtf;
                    815:                normtf = 0;     /* to permit transshipping */
                    816:                sval = send(n, sendto, level+1, postmark);
                    817:                normtf = rf;
                    818:                return(sval);
                    819:        }
                    820:        exists = stat(file, &stbuf);
                    821:        if ((pw = getpwnam(name)) == NULL) {
                    822:                if (exists < 0) {
                    823:                        (void)strcpy (inetaddr, name);
                    824:                        if (isinet(inetaddr)) {
                    825:                                if (strcmp (thissys, igates[igate].via) == 0) {
                    826:                                        (void)inetgateaddr(inetaddr);
                    827:                                        return(sendinet(n,inetaddr,postmark));
                    828:                                } else {
                    829:                                        (void)strcpy (sendto, igates[igate].via);
                    830:                                        (void)strcat (sendto, "!");
                    831:                                        (void)strcat (sendto, name);
                    832:                                        return(sendrmt(n, sendto, postmark));
                    833:                                }
                    834:                        }
                    835:                        if (rflg) {
                    836:                                refuse(n, name, postmark,
                    837:                                      "addressee unknown");
                    838:                                return(1);
                    839:                        }
                    840:                        fprintf(stderr, "mail: can't send to %s\n", name);
                    841:                        return(0);
                    842:                }
                    843:        } else {
                    844:                stbuf.st_uid = pw->pw_uid;
                    845:                stbuf.st_gid = pw->pw_gid;
                    846:        }
                    847:        mask = umask(MAILMODE);
                    848:        lock(file);
                    849:        malf = fopen(file, "a");
                    850:        umask(mask);
                    851:        if (malf == NULL) {
                    852:                fprintf(stderr, "mail: cannot append to %s\n", file);
                    853:                return(0);
                    854:        }
                    855:        if (exists < 0)
                    856:                chown(file, stbuf.st_uid, stbuf.st_gid);
                    857:        copylet(n, malf, SENDING, postmark);
                    858:        fclose(malf);
                    859:        unlock();
                    860:        logsend(name, postmark, "delivered");
                    861:        notify(name);   /* let him know it right away! */
                    862:        return(1);
                    863: }
                    864: 
                    865: notify(name)
                    866: char *name;
                    867: {
                    868:        struct utmp entry;
                    869:        FILE *f;
                    870: 
                    871:        if ((f = fopen("/etc/utmp", "r")) == NULL)
                    872:                return;
                    873:        while (fread((char *)&entry, sizeof(entry), 1, f) == 1) {
                    874:                if (strncmp(name, entry.ut_name, sizeof(entry.ut_name)) == 0)
                    875:                        blurb(entry.ut_line);
                    876:        }
                    877:        fclose(f);
                    878: }
                    879: 
                    880: blurb(tty)
                    881: char *tty;
                    882: {
                    883:        FILE *f = NULL;
                    884:        struct stat s;
                    885:        int blurbtime();
                    886:        char devtty[32];
                    887: 
                    888:        cat(devtty, dev, tty);
                    889:        signal(SIGALRM, blurbtime);
                    890:        alarm(30);
                    891:        stat(devtty, &s);
                    892:        if (s.st_mode & S_IEXEC)        /* notify only if enabled */
                    893:        if ((f = fopen(devtty, "w")) != NULL) {
                    894:                fprintf(f, "\r\n[%s: mail from %s]\r\n\7", thissys,
                    895:                  real_name[0]?real_name: my_name);
                    896:        }
                    897:        if (f)
                    898:                fclose(f);
                    899:        alarm(0);
                    900: }
                    901: 
                    902: blurbtime()
                    903: {
                    904: }
                    905: 
                    906: refuse(n, name, postmark, reason)
                    907: char *name, *postmark, *reason;
                    908: {
                    909:        FILE *pf;
                    910:        char cbuf[256], *cp;
                    911: 
                    912:        cp = strchr(postmark+5, ' ');
                    913:        if (cp == NULL)
                    914:                return;
                    915:        *cp = '\0';
                    916:        sprintf(cbuf, "PATH=/bin:/usr/bin mail %s", postmark+5);
                    917:        *cp = ' ';
                    918:        if ((pf = popen(cbuf, "w")) == NULL)
                    919:                return;
                    920:        fprintf(pf, "Mail to %s failed: %s.  Message was:\n", name, reason);
                    921:        copylet(n, pf, SENDING, postmark);
                    922:        pclose(pf);
                    923: }
                    924: 
                    925: delete(i)
                    926: {
                    927:        setsig(i, delete);
                    928:        fprintf(stderr, "\n");
                    929:        if(delflg)
                    930:                longjmp(sjbuf, 1);
                    931:        done();
                    932: }
                    933: 
                    934: done()
                    935: {
                    936:        unlock();
                    937:        unlink(lettmp);
                    938:        exit(error);
                    939: }
                    940: 
                    941: 
                    942: #define LOCKPREFIX "/tmp/L."
                    943: char    lockname[DIRSIZ+sizeof(LOCKPREFIX)];
                    944: 
                    945: /* Lock the given file.  The parameter "file" must contain at least one '/'. */
                    946: void
                    947: lock(file)
                    948: char *file;
                    949: {
                    950: #      define TMPLNAME "/tmp/mlXXXXX"
                    951: #      define LOCKPREFIX "/tmp/L."
                    952:        char tmplname[sizeof(TMPLNAME)];
                    953:        struct stat stbuf;
                    954:        int fd;
                    955: 
                    956:        /* return if we are already in the middle of a lock */
                    957:        if (*lockname != '\0' || flgf)
                    958:                return;
                    959: 
                    960:        /* create a temporary file */
                    961:        strcpy(tmplname, TMPLNAME);
                    962:        mktemp(tmplname);
                    963:        if ((fd=creat(tmplname, 0444))<0)
                    964:                return;
                    965:        close(fd);
                    966: 
                    967:        /* Make a link to it with the lock file name.  This will fail only
                    968:         * if it already exists.
                    969:         */
                    970:        strcpy(lockname, LOCKPREFIX);
                    971:        strcat(lockname, strrchr(file, '/')+1);
                    972:        lockname[DIRSIZ+sizeof("/tmp/")-1] = '\0';
                    973:        while (link(tmplname, lockname) < 0) {
                    974:                long now;
                    975: 
                    976:                /* File is already locked.  Break it if the lock is old. */
                    977:                sleep(2);
                    978:                now = time((long *)0);
                    979:                if (stat(lockname, &stbuf)==0 && stbuf.st_ctime+60 < now) {
                    980:                        if (stat(file, &stbuf)==0 && stbuf.st_mtime+60 >= now)
                    981:                                continue;
                    982:                        fprintf(stderr, "mail: breaking lock\n");
                    983:                        unlink(lockname);
                    984:                }
                    985:        }
                    986:        unlink(tmplname);
                    987:        return;
                    988: }
                    989: 
                    990: void
                    991: unlock()
                    992: {
                    993:        if (*lockname != '\0')
                    994:                unlink(lockname);
                    995:        *lockname = '\0';
                    996: }
                    997: 
                    998: cat(to, from1, from2)
                    999: char *to, *from1, *from2;
                   1000: {
                   1001:        strcpy(to, from1);
                   1002:        strcat(to, from2);
                   1003: }
                   1004: 
                   1005: char *getarg(s, p)      /* copy p... into s, update p */
                   1006: register char *s, *p;
                   1007: {
                   1008:        while (*p == ' ' || *p == '\t')
                   1009:                p++;
                   1010:        if (*p == '\n' || *p == '\0')
                   1011:                return(NULL);
                   1012:        while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
                   1013:                *s++ = *p++;
                   1014:        *s = '\0';
                   1015:        return(p);
                   1016: }
                   1017: 
                   1018: 
                   1019: /* is this an internet address (characterized by "@" or ".") */
                   1020: isinet(string)
                   1021: char *string;
                   1022: {
                   1023:        char *rindex();
                   1024: 
                   1025:        return rindex(string, '@') != 0 || rindex(string, '.') != 0;
                   1026: }
                   1027: 
                   1028: /* add any gateway info to the address */
                   1029: inetgateaddr(string)
                   1030: char *string;
                   1031: {
                   1032:        char *at, *dot;
                   1033:        char *rindex();
                   1034: 
                   1035:        /* find last "." or "@" */
                   1036:        at = rindex (string, '@');
                   1037:        if (at != 0)
                   1038:                dot = rindex (at + 1, '.');
                   1039:        else
                   1040:                dot = rindex (string, '.');
                   1041:        if (dot != 0)
                   1042:                at = dot;
                   1043: 
                   1044:        for (igate=0; igate<NIGATES; igate++) {
                   1045:                if (istrcmp(at+1, igates[igate].id) == 0) {
                   1046:                        strcpy(at, igates[igate].addr);
                   1047:                        break;
                   1048:                }
                   1049:        }
                   1050:        if (igate == NIGATES) {
                   1051:                igate = 0;      /* csnet or arpa, we really don't know */
                   1052:                strcat(string, igates[igate].addr);
                   1053:        }
                   1054: }
                   1055: 
                   1056: /* case insensitive strcmp */
                   1057: istrcmp(p1, p2)
                   1058: char *p1, *p2;
                   1059: {
                   1060:        do {
                   1061:                if (tolower(*p1) != tolower(*p2))
                   1062:                        return *p1 - *p2;
                   1063:                p2++;
                   1064:        } while (*p1++ != 0);
                   1065: 
                   1066:        return 0;
                   1067: }
                   1068: 
                   1069: /* log a mail transmission */
                   1070: logsend (to, pm, tag)
                   1071:        char *to;       /* receiver */
                   1072:        char *pm;       /* the postmark */
                   1073:        char *tag;      /* type of mail */
                   1074: {
                   1075: #      include <grp.h>
                   1076: #      define LOGFILE "/usr/spool/mail/mail.log"
                   1077: #      define LOGTEMP "/usr/spool/mail/mail.tmp"
                   1078:        char buf[BUFSIZ];
                   1079:        int out, in;
                   1080:        long len;
                   1081:        struct stat sbuf;
                   1082:        struct group sysgroup;
                   1083:        struct group *getgrnam();
                   1084: 
                   1085:        lock(LOGFILE);
                   1086: 
                   1087:        /* append to log */
                   1088:        if (stat(LOGFILE, &sbuf) < 0) {
                   1089:                out = creat(LOGFILE, 0660);
                   1090:        } else if (sbuf.st_size < 32000) {
                   1091:                out = open(LOGFILE, 2);
                   1092:        } else {
                   1093:                out = creat(LOGTEMP, 0660);
                   1094:                in = open(LOGFILE, 0);
                   1095:                if (out >= 0 && in >= 0 && lseek(in, -4000L, 2) >= 0) {
                   1096:                        while ((len = read(in, buf, BUFSIZ)) > 0)
                   1097:                                (void)write(out, buf, len);
                   1098:                        close(in);
                   1099:                        close(out);
                   1100:                        unlink(LOGFILE);
                   1101:                        link(LOGTEMP, LOGFILE);
                   1102:                        unlink(LOGTEMP);
                   1103:                } else {
                   1104:                        close(in);
                   1105:                        close(out);
                   1106:                }
                   1107:                        
                   1108:                out = open(LOGFILE, 2);
                   1109:        }
                   1110:        sprintf (buf, "%s %s %s\n", tag, to, pm);
                   1111:        (void)lseek(out, 0, 2);
                   1112:        (void)write(out, buf, strlen(buf));
                   1113:        close(out);
                   1114: 
                   1115:        unlock ();
                   1116: }
                   1117: 
                   1118: /*
                   1119:  *     Stuff for INTERNET headers
                   1120:  */
                   1121: 
                   1122: char *
                   1123: inetheader (pm) 
                   1124: char *pm;
                   1125: {
                   1126:        static char buf[256];
                   1127:        char *sender, *date;
                   1128:        char *field[6];
                   1129:        int i;
                   1130: 
                   1131:        /* skip the old from field */
                   1132:        pm += strlen (from);
                   1133: 
                   1134:        /* skip over the sender */
                   1135:        for(sender=pm; !isspace(*sender) && *sender!=NULL; sender++)
                   1136:                ;
                   1137:        date = *sender == '\0' ? sender : sender+1;
                   1138: 
                   1139:        /* reverse the path and replace '!'s with '.'s */
                   1140:        (void)strcpy (buf, "From: ");
                   1141:        while (sender >= pm) {
                   1142:                for (*sender = NULL; sender >= pm && *sender != '!'; sender--)
                   1143:                        ;
                   1144:                (void)strcat (buf, sender + 1);
                   1145:                (void)strcat (buf, ".");
                   1146:        }
                   1147:        (void)strcat (buf, "btl.");
                   1148: 
                   1149:        /* change an asctime date to an INTERNET style one (yech!) */
                   1150:        /* parse the old date */
                   1151:        for (i = 0; i < 6; i++) {               
                   1152:                for (; isspace(*date) || *date==',' || *date=='-'; date++)
                   1153:                        ;
                   1154:                field[i] = date;
                   1155:                for (; !isspace(*date) && *date!=',' && *date!='-' && *date!='\0'; date++)
                   1156:                        ;
                   1157:                if (*date != '\0')
                   1158:                        *date++ = '\0';
                   1159:        }
                   1160: 
                   1161:        /* output the arpa type format */
                   1162:        pm = buf + strlen (buf) - 1;
                   1163:        sprintf (pm, "\nDate: %s %s %s %s %s\n", field[2], field[1],
                   1164:                 field[5], field[3], field[4]);
                   1165:        return buf;
                   1166: }
                   1167: 
                   1168: sendinet(n, name, postmark)
                   1169: char *name, *postmark;
                   1170: {
                   1171:        FILE *rmf;
                   1172:        char cmd[512], buf[512];
                   1173:        static forked;
                   1174: 
                   1175:        if (normtf) {
                   1176:                refuse(n, name, postmark, "forwarding to this system disallowed");
                   1177:                return(1);
                   1178:        }
                   1179:        if(onatty & !forked) {
                   1180:                int p = fork();
                   1181:                if(p == 0) {
                   1182:                        sig_ign();
                   1183:                        forked = 1;
                   1184:                } else if(p != -1)
                   1185:                        exit(0);
                   1186:        }
                   1187: #ifndef DEBUG
                   1188:        sprintf(cmd, "exec %s %s", igates[igate].cmd, name);
                   1189: #else
                   1190:        sprintf(cmd, "echo %s %s; cat", igates[igate].cmd, name);
                   1191: #endif DEBUG
                   1192:        if ((rmf=popen(cmd, "w")) == NULL) {
                   1193:                fprintf(stderr, "mail: can't pipe to %s\n", igates[igate].cmd);
                   1194:                exit(1);
                   1195:        }
                   1196:        copylet(n, rmf, INTERNET, postmark);
                   1197:        logsend(name, postmark, igates[igate].id);
                   1198:        return(pclose(rmf)==0);
                   1199: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.