Annotation of researchv8dc/cmd/mail/mail.c, revision 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.