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

unix.superglobalmegacorp.com

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