Annotation of researchv10no/lbin/mailx/cmd2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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