Annotation of 3BSD/cmd/ucbmail/mail.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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