Annotation of researchv8dc/cmd/upas/print/print.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     print mail
        !             3:  */
        !             4: #include <stdio.h>
        !             5: #include <sys/types.h>
        !             6: #include <sys/stat.h>
        !             7: #include <setjmp.h>
        !             8: #include <ctype.h>
        !             9: #include "mail.h"
        !            10: #include "letter.h"
        !            11: #include "string.h"
        !            12: 
        !            13: /* globals */
        !            14: static int flgp;
        !            15: static int manual;
        !            16: static int forward;
        !            17: static int nlet;
        !            18: static int error;
        !            19: static int otherfile;
        !            20: static jmp_buf sjbuf;
        !            21: #define seq(i) (forward ? i-1 : nlet-i)
        !            22: static int changed;            /* true if mail file has been changed */
        !            23: 
        !            24: /* exported */
        !            25: char *thissys;
        !            26: 
        !            27: /* imported */
        !            28: extern void lock();
        !            29: extern void unlock();
        !            30: extern char *getlogin();
        !            31: extern char *getenv();
        !            32: extern char *getarg();
        !            33: extern FILE *popen();
        !            34: extern char *mailpath();
        !            35: extern long getunix();
        !            36: extern char *getsysname();
        !            37: extern char *P();
        !            38: extern void V();
        !            39: 
        !            40: /* predefined */
        !            41: static char *doargs();
        !            42: static long copymt();
        !            43: static void domanual();
        !            44: static void doauto();
        !            45: static int docommand();
        !            46: static int copyback();
        !            47: static int done();
        !            48: static int special_mailfile();
        !            49: static int doprint();
        !            50: static void dohelp();
        !            51: static void print_from();
        !            52: static int reply();
        !            53: static int remail();
        !            54: static int squirrel_away();
        !            55: 
        !            56: main(argc, argv)
        !            57: char **argv;
        !            58: {
        !            59:        struct stat stbuf;
        !            60:        char *mp, *tp;
        !            61:        long mailsize;
        !            62:        FILE *malf;
        !            63: 
        !            64:        mp = doargs(argc, argv);
        !            65:        if (stat(mp, &stbuf) < 0 || stbuf.st_size == 0L) {
        !            66:                printf("No mail.\n");
        !            67:                return 0;
        !            68:        }
        !            69:        thissys = getsysname();
        !            70:        (void)signal(SIGINT, done);
        !            71:        (void)signal(SIGHUP, done);
        !            72:        lock(mp);
        !            73:        tp = otherfile ? NULL : P();
        !            74:        if (tp != NULL)
        !            75:                fprintf(stderr, "You are already reading mail on %s!\n\n", tp);
        !            76:        malf = fopen(mp, "r");
        !            77:        if (malf == NULL) {
        !            78:                fprintf(stderr, "mail: cannot read %s.\n", mp);
        !            79:                error++;
        !            80:                (void)done();
        !            81:        }
        !            82: 
        !            83:        /* see if we're piping or forwarding */
        !            84:        if(special_mailfile(mp))
        !            85:                (void)done();
        !            86: 
        !            87:        /* make temporary */
        !            88:        inittmp();
        !            89: 
        !            90:        /* read mbox */
        !            91:        mailsize = copymt(malf);
        !            92:        fclose(malf);
        !            93:        unlock();
        !            94: 
        !            95:        /* print the mail */
        !            96:        if (flgp)
        !            97:                printall();
        !            98:        else {
        !            99:                if (manual)
        !           100:                        domanual();
        !           101:                else
        !           102:                        doauto();
        !           103:        }
        !           104:        if (changed)
        !           105:                copyback(mailsize, mp);
        !           106:        (void)done();
        !           107: 
        !           108:        return 0;
        !           109: }
        !           110: 
        !           111: /*     Output all messages */
        !           112: printall()
        !           113: {
        !           114:        int i, current;
        !           115: 
        !           116:        for (i = 0; i < nlet; i++) {
        !           117:                current = forward ? i : nlet - i - 1;
        !           118:                doprint(current);
        !           119:        }
        !           120: }
        !           121: 
        !           122: /* remember an interrupt happened */
        !           123: rememberint()
        !           124: {
        !           125:        signal(SIGINT, rememberint);
        !           126:        clearerr(stdin);
        !           127:        clearerr(stdout);
        !           128:        longjmp(sjbuf, 1);
        !           129: }
        !           130: 
        !           131: #define eatwhite(p) while(*p==' '||*p=='\t') p++
        !           132: 
        !           133: /*
        !           134:  *     Return a letter number
        !           135:  */
        !           136: static int
        !           137: lnumber(pp, dot, def)
        !           138:        char **pp;
        !           139: {
        !           140:        eatwhite(*pp);
        !           141:        switch(**pp) {
        !           142:        case '$':
        !           143:                (*pp)++;
        !           144:                dot = nlet;
        !           145:                break;
        !           146:        case 'n':
        !           147:        case '+':
        !           148:                (*pp)++;
        !           149:                dot = dot + 1;
        !           150:                break;
        !           151:        case '^':
        !           152:        case '-':
        !           153:                (*pp)++;
        !           154:                dot = dot - 1;
        !           155:                break;
        !           156:        case '.':
        !           157:                (*pp)++;
        !           158:                break;
        !           159:        case '0': case '1': case '2': case '3': case '4':
        !           160:        case '5': case '6': case '7': case '8': case '9':
        !           161:                dot = 0;
        !           162:                while (isdigit(**pp))
        !           163:                        dot = dot*10 + *(*pp)++ - '0';
        !           164:                break;          /* first letter is 1 */
        !           165:        default:
        !           166:                dot = def;
        !           167:                break;
        !           168:        }
        !           169:        if (dot <= 0)
        !           170:                dot = 1;
        !           171:        return dot;
        !           172: }
        !           173: 
        !           174: /*
        !           175:  *     Read and parse a command line.  A command consists of an optional
        !           176:  *     range, a single letter command, and optional arguments.
        !           177:  */
        !           178: static char *
        !           179: parse(cmdp, firstp, lastp, dot)
        !           180:        char *cmdp;             /* the 1 letter command */
        !           181:        int *firstp;            /* first command in a range */
        !           182:        int *lastp;             /* last command in a range */
        !           183:        int dot;                /* current letter */
        !           184: {
        !           185:        static char resp[CMDSIZE];
        !           186:        char *p = resp;
        !           187: 
        !           188:        /* get command and dump trailing newline */
        !           189:        printf("? ");
        !           190:        fflush(stdout);
        !           191:        if (fgets(resp, CMDSIZE, stdin) == NULL)
        !           192:                return NULL;
        !           193:        p[strlen(p) - 1] = '\0';
        !           194: 
        !           195:        /* get range */
        !           196:        eatwhite(p);
        !           197:        if (*p != '\0') {
        !           198:                if (*p == ',')
        !           199:                        *firstp = 1;
        !           200:                else
        !           201:                        *firstp = lnumber(&p, dot, dot);
        !           202:                eatwhite(p);
        !           203:                if (*p != ',')
        !           204:                        *lastp = *firstp;
        !           205:                else {
        !           206:                        p++;
        !           207:                        *lastp = lnumber(&p, dot, nlet);
        !           208:                }
        !           209:        } else
        !           210:                *firstp = *lastp = dot+1;
        !           211:        
        !           212:        /* get command */
        !           213:        eatwhite(p);
        !           214:        if (*p != '\0')
        !           215:                *cmdp = *p++;
        !           216:        else
        !           217:                *cmdp = 'p';
        !           218: 
        !           219:        /* compound command */
        !           220:        if (*cmdp == 'd' && (*p == 'q' || *p == 'p'))
        !           221:                *(cmdp+1) = *p++;
        !           222:        else
        !           223:                *(cmdp+1) = '\0';
        !           224:        eatwhite(p);
        !           225:        return p;
        !           226: }
        !           227: 
        !           228: /*     Process user commands in the new style.
        !           229:  *     All actions are prompted for.
        !           230:  */
        !           231: static void
        !           232: domanual()
        !           233: {
        !           234:        int dot=1, print, i;
        !           235:        int first, last;
        !           236:        char cmd[2], *args;
        !           237: 
        !           238:        printf("%d letters\n", nlet);
        !           239:        while (1) {
        !           240:                /* in case of interrupt, come back here but don't print */
        !           241:                if (setjmp(sjbuf))      /* after long jump */
        !           242:                        printf("\n");
        !           243:                signal(SIGINT, rememberint);
        !           244:                args = parse(cmd, &first, &last, dot);
        !           245:                if (args == NULL)
        !           246:                        break;
        !           247:                for (i = first; i <= last && i <= nlet; i++) {
        !           248:                        dot = i;        /* must be here in case of interrupt */
        !           249:                        if (docommand(cmd[0], args, i, &print) < 0)
        !           250:                                return;
        !           251:                }
        !           252:                switch (cmd[1]) {
        !           253:                case 'q':
        !           254:                        return;
        !           255:                case 'p':
        !           256:                        doprint(seq(++dot));
        !           257:                        break;
        !           258:                }
        !           259:        }
        !           260: }
        !           261: 
        !           262: /*     Process user commands in the old style.
        !           263:  *     This implies printing the next message 
        !           264:  *     without prompting for it
        !           265:  */
        !           266: static void
        !           267: doauto()
        !           268: {
        !           269:        int print=1, dot=1, i;
        !           270:        int first, last;
        !           271:        char cmd[2], *args;
        !           272: 
        !           273:        while (dot <= nlet && dot >= 0) {
        !           274:                /* in case of interrupt, come back here but don't print */
        !           275:                if (setjmp(sjbuf))      /* after long jump */
        !           276:                        printf("\n");
        !           277:                else {          /* here normally */
        !           278:                        signal(SIGINT, rememberint);
        !           279:                        if (print)
        !           280:                                doprint(seq(dot));
        !           281:                }
        !           282:                print = 0;
        !           283:                args = parse(cmd, &first, &last, dot);
        !           284:                if (args == NULL)
        !           285:                        break;
        !           286:                for (i = first; i <= last && i <= nlet; i++) {
        !           287:                        dot = i;        /* in case of interrupt while printing */
        !           288:                        dot = docommand(cmd[0], args, i, &print);
        !           289:                }
        !           290:                if (dot > 0 && dot < last)
        !           291:                        dot = last;
        !           292:                switch (cmd[1]) {
        !           293:                case 'q':
        !           294:                        return;
        !           295:                case 'p':
        !           296:                        print++;
        !           297:                        break;
        !           298:                }
        !           299:        }
        !           300: }
        !           301: 
        !           302: /*
        !           303:  *     Perform a command.
        !           304:  */
        !           305: static int
        !           306: docommand(cmd, args, dot, pflag)
        !           307:        char cmd;               /* command to perform */
        !           308:        char *args;             /* arguments to the command */
        !           309:        int dot;                /* the message to apply it to */
        !           310:        int *pflag;             /* (returned) true if next message to be printed */
        !           311: {
        !           312:        switch (cmd) {
        !           313:        default:
        !           314:                printf("usage\n");
        !           315:        case '?':
        !           316:                dohelp();
        !           317:                break;
        !           318:        case 'h':
        !           319:                print_from(seq(dot));
        !           320:                break;
        !           321:        case '=':
        !           322:                printf("at letter %d\n", dot);  
        !           323:                break;
        !           324:        case 'p':
        !           325:                doprint(seq(dot));
        !           326:                break;
        !           327:        case 'x':
        !           328:                changed = 0;
        !           329:                dot = -1;
        !           330:                break;
        !           331:        case 'y':
        !           332:        case 'w':
        !           333:        case 's':
        !           334:                if (squirrel_away(seq(dot), args) == 0) {
        !           335:                        (void)ldelete(seq(dot));
        !           336:                        changed++;
        !           337:                        (*pflag)++;
        !           338:                        dot++;
        !           339:                }
        !           340:                break;
        !           341:        case 'm':
        !           342:                if (remail(seq(dot), args) == 0) {
        !           343:                        (void)ldelete(seq(dot));
        !           344:                        changed++;
        !           345:                        (*pflag)++;
        !           346:                        dot++;
        !           347:                }
        !           348:                break;
        !           349:        case 'r':
        !           350:                if (*args != '\0') {
        !           351:                        fprintf(stderr, "invalid: r takes no arguments\n");
        !           352:                        break;
        !           353:                }
        !           354:                (void)reply(seq(dot));
        !           355:                printf("!\n");
        !           356:                break;
        !           357:        case '!':
        !           358:                system(args);
        !           359:                printf("!\n");
        !           360:                break;
        !           361:        case 'd':
        !           362:                if (*args != '\0') {
        !           363:                        fprintf(stderr,"invalid: d takes no arguments\n");
        !           364:                        break;
        !           365:                }
        !           366:                (void)ldelete(seq(dot));
        !           367:                changed++;
        !           368:                (*pflag)++;
        !           369:                dot++;
        !           370:                break;
        !           371:        case 'u':
        !           372:                if (*args != '\0') {
        !           373:                        fprintf(stderr,"invalid: u takes no arguments\n");
        !           374:                        break;
        !           375:                }
        !           376:                (void)lundelete(seq(dot));
        !           377:                (*pflag)++;
        !           378:                dot++;
        !           379:                break;
        !           380:        case 'q':
        !           381:                dot = -1;
        !           382:                break;
        !           383:        }
        !           384:        return dot;
        !           385: }
        !           386: 
        !           387: /* copy mail to temp file, returns size of mail file */
        !           388: static long
        !           389: copymt(mfp)
        !           390:        FILE *mfp;
        !           391: {
        !           392:        letter *lp=NULL;
        !           393:        char line[FROMLINESIZE];
        !           394: 
        !           395:        /* read in letters */
        !           396:        while (fgets(line, FROMLINESIZE, mfp) != NULL) {
        !           397:                if (strncmp(line, FROM, FSIZE)==0 || lp==NULL) {
        !           398:                        lp = lopen(nlet++, "w");
        !           399:                }
        !           400:                lputs(line, lp);
        !           401:        }
        !           402: 
        !           403:        /* remember where end of file is */
        !           404:        return ftell(mfp);
        !           405: }
        !           406: 
        !           407: /* copy temp or whatever back to /usr/spool/mail */
        !           408: static int
        !           409: copyback(oldsize, mp)
        !           410:        long oldsize;
        !           411:        char *mp;
        !           412: {
        !           413:        register i;
        !           414:        register int new = 0;
        !           415:        struct stat stbuf;
        !           416:        letter *lp;
        !           417:        FILE *malf;
        !           418: 
        !           419:        lock(mp);
        !           420: 
        !           421:        /* read new mail that arrived while we were printing */
        !           422:        stat(mp, &stbuf);
        !           423:        if (stbuf.st_size != oldsize) {   /* new mail has arrived */
        !           424:                malf = fopen(mp, "r");
        !           425:                if (malf == NULL) {
        !           426:                        fprintf(stderr, "mail: can't re-read %s\n", mp);
        !           427:                        (void)done();
        !           428:                }
        !           429:                fseek(malf, oldsize, 0);
        !           430:                (void)copymt(malf);
        !           431:                fclose(malf);
        !           432:                new++;
        !           433:        }
        !           434: 
        !           435:        /* turn off interrupts while writing back */
        !           436:        signal(SIGHUP, SIG_IGN);
        !           437:        signal(SIGINT, SIG_IGN);
        !           438:        signal(SIGQUIT, SIG_IGN);
        !           439:        signal(SIGTERM, SIG_IGN);
        !           440: 
        !           441:        /* write the sucker back */
        !           442:        malf = fopen(mp, "w");
        !           443:        if (malf == NULL) {
        !           444:                fprintf(stderr, "mail: can't rewrite %s\n", mp);
        !           445:                (void)done();
        !           446:        }
        !           447:        for (i = 0; i < nlet; i++)
        !           448:                if ((lp=lopen(i, "ru")) != NULL) {
        !           449:                        copyfrom(lp, malf);
        !           450:                }
        !           451:        fclose(malf);
        !           452:        unlock();
        !           453:        if (new)
        !           454:                printf("new mail arrived\n");
        !           455: }
        !           456: 
        !           457: /* come here to finish up */
        !           458: static int
        !           459: done()
        !           460: {
        !           461:        unlock();
        !           462:        V();
        !           463:        releasetmp();
        !           464:        exit(error);
        !           465:        return 0;
        !           466: }
        !           467: 
        !           468: static char *
        !           469: doargs(argc, argv)
        !           470:        int argc;
        !           471:        char *argv[];
        !           472: {
        !           473:        static char mailfile[256];
        !           474: 
        !           475:        (void)strcpy(mailfile, mailpath(getlogin()));
        !           476: 
        !           477:        for (; argc>1; argv++, argc--) {
        !           478:                if (argv[1][0]=='-') {
        !           479:                        if (argv[1][1]=='p') {
        !           480:                                flgp++;
        !           481:                        } else if (argv[1][1]=='f') {
        !           482:                                if (argc>=3) {
        !           483:                                        strcpy(mailfile, argv[2]);
        !           484:                                        argv++;
        !           485:                                        argc--;
        !           486:                                        otherfile = 1;
        !           487:                                }
        !           488:                        } else if (argv[1][1]=='r') {
        !           489:                                forward = 1;
        !           490:                        } else if (argv[1][1]=='m') {
        !           491:                                manual = 1;
        !           492:                        } else {
        !           493:                                fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
        !           494:                                done();
        !           495:                        }
        !           496:                } else
        !           497:                        break;
        !           498:        }
        !           499:        return mailfile;
        !           500: }
        !           501: 
        !           502: /* return non-zero if this is not a normal mail file */
        !           503: static int
        !           504: special_mailfile(mp)
        !           505:        char *mp;               /* mail file */
        !           506: {
        !           507:        char fbuf[256];
        !           508:        char *sp1, *sp2;
        !           509:        int stat;
        !           510: 
        !           511:        sp2 = "";
        !           512: 
        !           513:        /* if something is being done to the mail, go away */
        !           514:        stat = delivery_status(mp, fbuf);
        !           515:        switch(stat & MFTYPE) {
        !           516:        case MF_FORWARD:
        !           517:                sp1 = "Your mail is being forwarded to";
        !           518:                break;
        !           519:        case MF_PIPE:
        !           520:                sp1 = "Your mail is being piped to";
        !           521:                break;
        !           522:        default:
        !           523:                return 0;
        !           524:        }
        !           525: 
        !           526:        if (stat & MFEXTRA)
        !           527:                sp2 = "and your mailbox contains extra stuff\n";
        !           528:        printf("%s %s %s\n", sp1, fbuf, sp2);
        !           529:        return stat & MFTYPE;
        !           530: }
        !           531: 
        !           532: static void
        !           533: dohelp()
        !           534: {
        !           535:        printf("Commands are of the form '[range] command [args]'.\n");
        !           536:        printf("The command can be:\n");
        !           537:        printf("d\tdelete\n");
        !           538:        printf("u\tundelete\n");
        !           539:        printf("h\tprint from lines of all messages\n");
        !           540:        printf("m user\tmail to user\n");
        !           541:        printf("p\tprint\n");
        !           542:        printf("r\treply to last message\n");
        !           543:        printf("q\tquit\n");
        !           544:        printf("s[file]\tsave (default mbox)\n");
        !           545:        printf("x\texit without changing mail\n");
        !           546:        printf("=\tprint current message number\n");
        !           547:        printf("! cmd\texecute cmd\n");
        !           548: }
        !           549: 
        !           550: /* print the from line (and status) of each message */
        !           551: static void
        !           552: print_from(let)
        !           553:        int let;
        !           554: {
        !           555:        int deleted;
        !           556:        char from[FROMLINESIZE];
        !           557:        letter *lp;
        !           558: 
        !           559:        lp = lopen(let, "ru");
        !           560:        if (lp == NULL) {
        !           561:                deleted = 1;
        !           562:                lp = lopen(let, "r");
        !           563:        } else
        !           564:                deleted = 0;
        !           565:        lgets(from, FROMLINESIZE, lp);
        !           566:        printf("%3d %c %4d  %s", seq(let), deleted?'d':' ',
        !           567:                lsize(lp), from+FSIZE);
        !           568: }
        !           569: 
        !           570: /* save a letter in a file, return 0 if successful */
        !           571: static int
        !           572: squirrel_away(let, resp)
        !           573:        int let;
        !           574:        char *resp;
        !           575: {
        !           576:        char *p;
        !           577:        letter *lp;
        !           578:        char path[PATHSIZE];
        !           579:        int problems=0;
        !           580:        FILE *malf;
        !           581: 
        !           582:        if (*resp == '\0') {
        !           583:                p = getenv("HOME");
        !           584:                if(p != 0) {
        !           585:                        strcpy(resp, p);
        !           586:                        strcat(resp, "/mbox");
        !           587:                } else
        !           588:                        strcpy(resp, "mbox");
        !           589:        }
        !           590:        for (p = resp; (p = getarg(path, p)) != NULL; ) {
        !           591:                malf = fopen(path, "a");
        !           592:                if (malf == NULL) {
        !           593:                        fprintf(stderr, "mail: cannot append to %s\n", path);
        !           594:                        problems++;
        !           595:                        continue;
        !           596:                }
        !           597:                lp = lopen(let, "r");
        !           598:                copyfrom(lp, malf);
        !           599:                fclose(malf);
        !           600:        }
        !           601:        return problems;
        !           602: }
        !           603: 
        !           604: /* reply to mail, return 0 if no problems */
        !           605: static char replyline[FROMLINESIZE];
        !           606: static char replycmd[CMDSIZE];
        !           607: static int
        !           608: reply(let)
        !           609:        int let;
        !           610: {
        !           611:        char *sp;
        !           612:        letter *lp;
        !           613: 
        !           614:        lp = lopen(let, "r");
        !           615:        lgets(replyline, FROMLINESIZE, lp);
        !           616:        sp = strchr(replyline+FSIZE, ' ');
        !           617:        if (sp != NULL)
        !           618:                *sp = '\0';
        !           619:        strcpy(replycmd, "/bin/mail ");
        !           620:        strcat(replycmd, replyline+FSIZE);
        !           621:        printf("!%s\n", replycmd);
        !           622:        system(replycmd);
        !           623:        return 0;
        !           624: }
        !           625: 
        !           626: /* pass mail onto someone else, return 0 if no problems */
        !           627: static int
        !           628: remail(let, resp)
        !           629:        int let;
        !           630:        char *resp;
        !           631: {
        !           632:        char cmd[CMDSIZE];
        !           633:        FILE *pipf;
        !           634:        letter *lp;
        !           635: 
        !           636:        if (*resp == '\0') {
        !           637:                fprintf(stderr, "invalid: m requires a destination\n");
        !           638:                return -1;
        !           639:        }
        !           640:        strcpy(cmd, "mail ");
        !           641:        strcat(cmd, resp);
        !           642: 
        !           643:        /* fork so that mail becomes super-user again */
        !           644:        pipf = popen(cmd, "w");
        !           645:        if(pipf == NULL) {
        !           646:                fprintf(stderr, "mail: can't fork to remail\n");
        !           647:                return -1;
        !           648:        }
        !           649:        lp = lopen(let, "r");
        !           650:        copyfrom(lp, pipf);
        !           651:        return pclose(pipf);
        !           652: }
        !           653: 
        !           654: /* output the letter */
        !           655: static int
        !           656: doprint(let)
        !           657:        int let;
        !           658: {
        !           659:        letter *lp;
        !           660: 
        !           661:        lp = lopen(let, "r");
        !           662:        if (lp == NULL)
        !           663:                return -1;
        !           664:        copyfrom(lp, stdout);
        !           665:        return 0;
        !           666: }

unix.superglobalmegacorp.com

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