Annotation of 43BSD/ucb/Mail/cmd2.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)cmd2.c      5.3 (Berkeley) 9/10/85";
                      9: #endif not lint
                     10: 
                     11: #include "rcv.h"
                     12: #include <sys/stat.h>
                     13: 
                     14: /*
                     15:  * Mail -- a mail program
                     16:  *
                     17:  * More user commands.
                     18:  */
                     19: 
                     20: /*
                     21:  * If any arguments were given, go to the next applicable argument
                     22:  * following dot, otherwise, go to the next applicable message.
                     23:  * If given as first command with no arguments, print first message.
                     24:  */
                     25: 
                     26: next(msgvec)
                     27:        int *msgvec;
                     28: {
                     29:        register struct message *mp;
                     30:        register int *ip, *ip2;
                     31:        int list[2], mdot;
                     32: 
                     33:        if (*msgvec != NULL) {
                     34: 
                     35:                /*
                     36:                 * If some messages were supplied, find the 
                     37:                 * first applicable one following dot using
                     38:                 * wrap around.
                     39:                 */
                     40: 
                     41:                mdot = dot - &message[0] + 1;
                     42: 
                     43:                /*
                     44:                 * Find the first message in the supplied
                     45:                 * message list which follows dot.
                     46:                 */
                     47: 
                     48:                for (ip = msgvec; *ip != NULL; ip++)
                     49:                        if (*ip > mdot)
                     50:                                break;
                     51:                if (*ip == NULL)
                     52:                        ip = msgvec;
                     53:                ip2 = ip;
                     54:                do {
                     55:                        mp = &message[*ip2 - 1];
                     56:                        if ((mp->m_flag & MDELETED) == 0) {
                     57:                                dot = mp;
                     58:                                goto hitit;
                     59:                        }
                     60:                        if (*ip2 != NULL)
                     61:                                ip2++;
                     62:                        if (*ip2 == NULL)
                     63:                                ip2 = msgvec;
                     64:                } while (ip2 != ip);
                     65:                printf("No messages applicable\n");
                     66:                return(1);
                     67:        }
                     68: 
                     69:        /*
                     70:         * If this is the first command, select message 1.
                     71:         * Note that this must exist for us to get here at all.
                     72:         */
                     73: 
                     74:        if (!sawcom)
                     75:                goto hitit;
                     76: 
                     77:        /*
                     78:         * Just find the next good message after dot, no
                     79:         * wraparound.
                     80:         */
                     81: 
                     82:        for (mp = dot+1; mp < &message[msgCount]; mp++)
                     83:                if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
                     84:                        break;
                     85:        if (mp >= &message[msgCount]) {
                     86:                printf("At EOF\n");
                     87:                return(0);
                     88:        }
                     89:        dot = mp;
                     90: hitit:
                     91:        /*
                     92:         * Print dot.
                     93:         */
                     94: 
                     95:        list[0] = dot - &message[0] + 1;
                     96:        list[1] = NULL;
                     97:        return(type(list));
                     98: }
                     99: 
                    100: /*
                    101:  * Save a message in a file.  Mark the message as saved
                    102:  * so we can discard when the user quits.
                    103:  */
                    104: save(str)
                    105:        char str[];
                    106: {
                    107: 
                    108:        return(save1(str, 1));
                    109: }
                    110: 
                    111: /*
                    112:  * Copy a message to a file without affected its saved-ness
                    113:  */
                    114: copycmd(str)
                    115:        char str[];
                    116: {
                    117: 
                    118:        return(save1(str, 0));
                    119: }
                    120: 
                    121: /*
                    122:  * Save/copy the indicated messages at the end of the passed file name.
                    123:  * If mark is true, mark the message "saved."
                    124:  */
                    125: save1(str, mark)
                    126:        char str[];
                    127: {
                    128:        register int *ip, mesg;
                    129:        register struct message *mp;
                    130:        char *file, *disp, *cmd;
                    131:        int f, *msgvec, lc, t;
                    132:        long cc;
                    133:        FILE *obuf;
                    134:        struct stat statb;
                    135: 
                    136:        cmd = mark ? "save" : "copy";
                    137:        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
                    138:        if ((file = snarf(str, &f)) == NOSTR)
                    139:                return(1);
                    140:        if (!f) {
                    141:                *msgvec = first(0, MMNORM);
                    142:                if (*msgvec == NULL) {
                    143:                        printf("No messages to %s.\n", cmd);
                    144:                        return(1);
                    145:                }
                    146:                msgvec[1] = NULL;
                    147:        }
                    148:        if (f && getmsglist(str, msgvec, 0) < 0)
                    149:                return(1);
                    150:        if ((file = expand(file)) == NOSTR)
                    151:                return(1);
                    152:        printf("\"%s\" ", file);
                    153:        fflush(stdout);
                    154:        if (stat(file, &statb) >= 0)
                    155:                disp = "[Appended]";
                    156:        else
                    157:                disp = "[New file]";
                    158:        if ((obuf = fopen(file, "a")) == NULL) {
                    159:                perror(NOSTR);
                    160:                return(1);
                    161:        }
                    162:        cc = 0L;
                    163:        lc = 0;
                    164:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    165:                mesg = *ip;
                    166:                touch(mesg);
                    167:                mp = &message[mesg-1];
                    168:                if ((t = send(mp, obuf, 0)) < 0) {
                    169:                        perror(file);
                    170:                        fclose(obuf);
                    171:                        return(1);
                    172:                }
                    173:                lc += t;
                    174:                cc += mp->m_size;
                    175:                if (mark)
                    176:                        mp->m_flag |= MSAVED;
                    177:        }
                    178:        fflush(obuf);
                    179:        if (ferror(obuf))
                    180:                perror(file);
                    181:        fclose(obuf);
                    182:        printf("%s %d/%ld\n", disp, lc, cc);
                    183:        return(0);
                    184: }
                    185: 
                    186: /*
                    187:  * Write the indicated messages at the end of the passed
                    188:  * file name, minus header and trailing blank line.
                    189:  */
                    190: 
                    191: swrite(str)
                    192:        char str[];
                    193: {
                    194:        register int *ip, mesg;
                    195:        register struct message *mp;
                    196:        register char *file, *disp;
                    197:        char linebuf[BUFSIZ];
                    198:        int f, *msgvec, lc, cc, t;
                    199:        FILE *obuf, *mesf;
                    200:        struct stat statb;
                    201: 
                    202:        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
                    203:        if ((file = snarf(str, &f)) == NOSTR)
                    204:                return(1);
                    205:        if ((file = expand(file)) == NOSTR)
                    206:                return(1);
                    207:        if (!f) {
                    208:                *msgvec = first(0, MMNORM);
                    209:                if (*msgvec == NULL) {
                    210:                        printf("No messages to write.\n");
                    211:                        return(1);
                    212:                }
                    213:                msgvec[1] = NULL;
                    214:        }
                    215:        if (f && getmsglist(str, msgvec, 0) < 0)
                    216:                return(1);
                    217:        printf("\"%s\" ", file);
                    218:        fflush(stdout);
                    219:        if (stat(file, &statb) >= 0)
                    220:                disp = "[Appended]";
                    221:        else
                    222:                disp = "[New file]";
                    223:        if ((obuf = fopen(file, "a")) == NULL) {
                    224:                perror(NOSTR);
                    225:                return(1);
                    226:        }
                    227:        cc = lc = 0;
                    228:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    229:                mesg = *ip;
                    230:                touch(mesg);
                    231:                mp = &message[mesg-1];
                    232:                mesf = setinput(mp);
                    233:                t = mp->m_lines - 1;
                    234:                while (t-- > 0) {
                    235:                        readline(mesf, linebuf);
                    236:                        if (blankline(linebuf))
                    237:                                break;
                    238:                }
                    239:                while (t-- > 0) {
                    240:                        fgets(linebuf, BUFSIZ, mesf);
                    241:                        fputs(linebuf, obuf);
                    242:                        cc += strlen(linebuf);
                    243:                }
                    244:                lc += mp->m_lines - 2;
                    245:                mp->m_flag |= MSAVED;
                    246:        }
                    247:        fflush(obuf);
                    248:        if (ferror(obuf))
                    249:                perror(file);
                    250:        fclose(obuf);
                    251:        printf("%s %d/%d\n", disp, lc, cc);
                    252:        return(0);
                    253: }
                    254: 
                    255: /*
                    256:  * Snarf the file from the end of the command line and
                    257:  * return a pointer to it.  If there is no file attached,
                    258:  * just return NOSTR.  Put a null in front of the file
                    259:  * name so that the message list processing won't see it,
                    260:  * unless the file name is the only thing on the line, in
                    261:  * which case, return 0 in the reference flag variable.
                    262:  */
                    263: 
                    264: char *
                    265: snarf(linebuf, flag)
                    266:        char linebuf[];
                    267:        int *flag;
                    268: {
                    269:        register char *cp;
                    270: 
                    271:        *flag = 1;
                    272:        cp = strlen(linebuf) + linebuf - 1;
                    273: 
                    274:        /*
                    275:         * Strip away trailing blanks.
                    276:         */
                    277: 
                    278:        while (*cp == ' ' && cp > linebuf)
                    279:                cp--;
                    280:        *++cp = 0;
                    281: 
                    282:        /*
                    283:         * Now search for the beginning of the file name.
                    284:         */
                    285: 
                    286:        while (cp > linebuf && !any(*cp, "\t "))
                    287:                cp--;
                    288:        if (*cp == '\0') {
                    289:                printf("No file specified.\n");
                    290:                return(NOSTR);
                    291:        }
                    292:        if (any(*cp, " \t"))
                    293:                *cp++ = 0;
                    294:        else
                    295:                *flag = 0;
                    296:        return(cp);
                    297: }
                    298: 
                    299: /*
                    300:  * Delete messages.
                    301:  */
                    302: 
                    303: delete(msgvec)
                    304:        int msgvec[];
                    305: {
                    306:        return(delm(msgvec));
                    307: }
                    308: 
                    309: /*
                    310:  * Delete messages, then type the new dot.
                    311:  */
                    312: 
                    313: deltype(msgvec)
                    314:        int msgvec[];
                    315: {
                    316:        int list[2];
                    317:        int lastdot;
                    318: 
                    319:        lastdot = dot - &message[0] + 1;
                    320:        if (delm(msgvec) >= 0) {
                    321:                list[0] = dot - &message[0];
                    322:                list[0]++;
                    323:                if (list[0] > lastdot) {
                    324:                        touch(list[0]);
                    325:                        list[1] = NULL;
                    326:                        return(type(list));
                    327:                }
                    328:                printf("At EOF\n");
                    329:                return(0);
                    330:        }
                    331:        else {
                    332:                printf("No more messages\n");
                    333:                return(0);
                    334:        }
                    335: }
                    336: 
                    337: /*
                    338:  * Delete the indicated messages.
                    339:  * Set dot to some nice place afterwards.
                    340:  * Internal interface.
                    341:  */
                    342: 
                    343: delm(msgvec)
                    344:        int *msgvec;
                    345: {
                    346:        register struct message *mp;
                    347:        register *ip, mesg;
                    348:        int last;
                    349: 
                    350:        last = NULL;
                    351:        for (ip = msgvec; *ip != NULL; ip++) {
                    352:                mesg = *ip;
                    353:                touch(mesg);
                    354:                mp = &message[mesg-1];
                    355:                mp->m_flag |= MDELETED|MTOUCH;
                    356:                mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
                    357:                last = mesg;
                    358:        }
                    359:        if (last != NULL) {
                    360:                dot = &message[last-1];
                    361:                last = first(0, MDELETED);
                    362:                if (last != NULL) {
                    363:                        dot = &message[last-1];
                    364:                        return(0);
                    365:                }
                    366:                else {
                    367:                        dot = &message[0];
                    368:                        return(-1);
                    369:                }
                    370:        }
                    371: 
                    372:        /*
                    373:         * Following can't happen -- it keeps lint happy
                    374:         */
                    375: 
                    376:        return(-1);
                    377: }
                    378: 
                    379: /*
                    380:  * Undelete the indicated messages.
                    381:  */
                    382: 
                    383: undelete(msgvec)
                    384:        int *msgvec;
                    385: {
                    386:        register struct message *mp;
                    387:        register *ip, mesg;
                    388: 
                    389:        for (ip = msgvec; ip-msgvec < msgCount; ip++) {
                    390:                mesg = *ip;
                    391:                if (mesg == 0)
                    392:                        return;
                    393:                touch(mesg);
                    394:                mp = &message[mesg-1];
                    395:                dot = mp;
                    396:                mp->m_flag &= ~MDELETED;
                    397:        }
                    398: }
                    399: 
                    400: /*
                    401:  * Interactively dump core on "core"
                    402:  */
                    403: 
                    404: core()
                    405: {
                    406:        register int pid;
                    407:        int status;
                    408: 
                    409:        if ((pid = vfork()) == -1) {
                    410:                perror("fork");
                    411:                return(1);
                    412:        }
                    413:        if (pid == 0) {
                    414:                sigchild();
                    415:                abort();
                    416:                _exit(1);
                    417:        }
                    418:        printf("Okie dokie");
                    419:        fflush(stdout);
                    420:        while (wait(&status) != pid)
                    421:                ;
                    422:        if (status & 0200)
                    423:                printf(" -- Core dumped\n");
                    424:        else
                    425:                printf("\n");
                    426: }
                    427: 
                    428: /*
                    429:  * Clobber as many bytes of stack as the user requests.
                    430:  */
                    431: clobber(argv)
                    432:        char **argv;
                    433: {
                    434:        register int times;
                    435: 
                    436:        if (argv[0] == 0)
                    437:                times = 1;
                    438:        else
                    439:                times = (atoi(argv[0]) + 511) / 512;
                    440:        clob1(times);
                    441: }
                    442: 
                    443: /*
                    444:  * Clobber the stack.
                    445:  */
                    446: clob1(n)
                    447: {
                    448:        char buf[512];
                    449:        register char *cp;
                    450: 
                    451:        if (n <= 0)
                    452:                return;
                    453:        for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
                    454:                ;
                    455:        clob1(n - 1);
                    456: }
                    457: 
                    458: /*
                    459:  * Add the given header fields to the retained list.
                    460:  * If no arguments, print the current list of retained fields.
                    461:  */
                    462: retfield(list)
                    463:        char *list[];
                    464: {
                    465:        char field[BUFSIZ];
                    466:        register int h;
                    467:        register struct ignore *igp;
                    468:        char **ap;
                    469: 
                    470:        if (argcount(list) == 0)
                    471:                return(retshow());
                    472:        for (ap = list; *ap != 0; ap++) {
                    473:                istrcpy(field, *ap);
                    474: 
                    475:                if (member(field, retain))
                    476:                        continue;
                    477: 
                    478:                h = hash(field);
                    479:                igp = (struct ignore *) calloc(1, sizeof (struct ignore));
                    480:                igp->i_field = calloc(strlen(field) + 1, sizeof (char));
                    481:                strcpy(igp->i_field, field);
                    482:                igp->i_link = retain[h];
                    483:                retain[h] = igp;
                    484:                nretained++;
                    485:        }
                    486:        return(0);
                    487: }
                    488: 
                    489: /*
                    490:  * Print out all currently retained fields.
                    491:  */
                    492: retshow()
                    493: {
                    494:        register int h, count;
                    495:        struct ignore *igp;
                    496:        char **ap, **ring;
                    497:        int igcomp();
                    498: 
                    499:        count = 0;
                    500:        for (h = 0; h < HSHSIZE; h++)
                    501:                for (igp = retain[h]; igp != 0; igp = igp->i_link)
                    502:                        count++;
                    503:        if (count == 0) {
                    504:                printf("No fields currently being retained.\n");
                    505:                return(0);
                    506:        }
                    507:        ring = (char **) salloc((count + 1) * sizeof (char *));
                    508:        ap = ring;
                    509:        for (h = 0; h < HSHSIZE; h++)
                    510:                for (igp = retain[h]; igp != 0; igp = igp->i_link)
                    511:                        *ap++ = igp->i_field;
                    512:        *ap = 0;
                    513:        qsort(ring, count, sizeof (char *), igcomp);
                    514:        for (ap = ring; *ap != 0; ap++)
                    515:                printf("%s\n", *ap);
                    516:        return(0);
                    517: }
                    518: 
                    519: /*
                    520:  * Add the given header fields to the ignored list.
                    521:  * If no arguments, print the current list of ignored fields.
                    522:  */
                    523: igfield(list)
                    524:        char *list[];
                    525: {
                    526:        char field[BUFSIZ];
                    527:        register int h;
                    528:        register struct ignore *igp;
                    529:        char **ap;
                    530: 
                    531:        if (argcount(list) == 0)
                    532:                return(igshow());
                    533:        for (ap = list; *ap != 0; ap++) {
                    534:                if (isign(*ap))
                    535:                        continue;
                    536:                istrcpy(field, *ap);
                    537:                h = hash(field);
                    538:                igp = (struct ignore *) calloc(1, sizeof (struct ignore));
                    539:                igp->i_field = calloc(strlen(field) + 1, sizeof (char));
                    540:                strcpy(igp->i_field, field);
                    541:                igp->i_link = ignore[h];
                    542:                ignore[h] = igp;
                    543:        }
                    544:        return(0);
                    545: }
                    546: 
                    547: /*
                    548:  * Print out all currently ignored fields.
                    549:  */
                    550: igshow()
                    551: {
                    552:        register int h, count;
                    553:        struct ignore *igp;
                    554:        char **ap, **ring;
                    555:        int igcomp();
                    556: 
                    557:        count = 0;
                    558:        for (h = 0; h < HSHSIZE; h++)
                    559:                for (igp = ignore[h]; igp != 0; igp = igp->i_link)
                    560:                        count++;
                    561:        if (count == 0) {
                    562:                printf("No fields currently being ignored.\n");
                    563:                return(0);
                    564:        }
                    565:        ring = (char **) salloc((count + 1) * sizeof (char *));
                    566:        ap = ring;
                    567:        for (h = 0; h < HSHSIZE; h++)
                    568:                for (igp = ignore[h]; igp != 0; igp = igp->i_link)
                    569:                        *ap++ = igp->i_field;
                    570:        *ap = 0;
                    571:        qsort(ring, count, sizeof (char *), igcomp);
                    572:        for (ap = ring; *ap != 0; ap++)
                    573:                printf("%s\n", *ap);
                    574:        return(0);
                    575: }
                    576: 
                    577: /*
                    578:  * Compare two names for sorting ignored field list.
                    579:  */
                    580: igcomp(l, r)
                    581:        char **l, **r;
                    582: {
                    583: 
                    584:        return(strcmp(*l, *r));
                    585: }

unix.superglobalmegacorp.com

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