Annotation of 43BSDReno/usr.bin/mail/list.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: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)list.c     5.14 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: #include "rcv.h"
                     25: #include <ctype.h>
                     26: 
                     27: /*
                     28:  * Mail -- a mail program
                     29:  *
                     30:  * Message list handling.
                     31:  */
                     32: 
                     33: /*
                     34:  * Convert the user string of message numbers and
                     35:  * store the numbers into vector.
                     36:  *
                     37:  * Returns the count of messages picked up or -1 on error.
                     38:  */
                     39: 
                     40: getmsglist(buf, vector, flags)
                     41:        char *buf;
                     42:        int *vector;
                     43: {
                     44:        register int *ip;
                     45:        register struct message *mp;
                     46: 
                     47:        if (msgCount == 0) {
                     48:                *vector = 0;
                     49:                return 0;
                     50:        }
                     51:        if (markall(buf, flags) < 0)
                     52:                return(-1);
                     53:        ip = vector;
                     54:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                     55:                if (mp->m_flag & MMARK)
                     56:                        *ip++ = mp - &message[0] + 1;
                     57:        *ip = 0;
                     58:        return(ip - vector);
                     59: }
                     60: 
                     61: /*
                     62:  * Mark all messages that the user wanted from the command
                     63:  * line in the message structure.  Return 0 on success, -1
                     64:  * on error.
                     65:  */
                     66: 
                     67: /*
                     68:  * Bit values for colon modifiers.
                     69:  */
                     70: 
                     71: #define        CMNEW           01              /* New messages */
                     72: #define        CMOLD           02              /* Old messages */
                     73: #define        CMUNREAD        04              /* Unread messages */
                     74: #define        CMDELETED       010             /* Deleted messages */
                     75: #define        CMREAD          020             /* Read messages */
                     76: 
                     77: /*
                     78:  * The following table describes the letters which can follow
                     79:  * the colon and gives the corresponding modifier bit.
                     80:  */
                     81: 
                     82: struct coltab {
                     83:        char    co_char;                /* What to find past : */
                     84:        int     co_bit;                 /* Associated modifier bit */
                     85:        int     co_mask;                /* m_status bits to mask */
                     86:        int     co_equal;               /* ... must equal this */
                     87: } coltab[] = {
                     88:        'n',            CMNEW,          MNEW,           MNEW,
                     89:        'o',            CMOLD,          MNEW,           0,
                     90:        'u',            CMUNREAD,       MREAD,          0,
                     91:        'd',            CMDELETED,      MDELETED,       MDELETED,
                     92:        'r',            CMREAD,         MREAD,          MREAD,
                     93:        0,              0,              0,              0
                     94: };
                     95: 
                     96: static int     lastcolmod;
                     97: 
                     98: markall(buf, f)
                     99:        char buf[];
                    100: {
                    101:        register char **np;
                    102:        register int i;
                    103:        register struct message *mp;
                    104:        char *namelist[NMLSIZE], *bufp;
                    105:        int tok, beg, mc, star, other, valdot, colmod, colresult;
                    106: 
                    107:        valdot = dot - &message[0] + 1;
                    108:        colmod = 0;
                    109:        for (i = 1; i <= msgCount; i++)
                    110:                unmark(i);
                    111:        bufp = buf;
                    112:        mc = 0;
                    113:        np = &namelist[0];
                    114:        scaninit();
                    115:        tok = scan(&bufp);
                    116:        star = 0;
                    117:        other = 0;
                    118:        beg = 0;
                    119:        while (tok != TEOL) {
                    120:                switch (tok) {
                    121:                case TNUMBER:
                    122: number:
                    123:                        if (star) {
                    124:                                printf("No numbers mixed with *\n");
                    125:                                return(-1);
                    126:                        }
                    127:                        mc++;
                    128:                        other++;
                    129:                        if (beg != 0) {
                    130:                                if (check(lexnumber, f))
                    131:                                        return(-1);
                    132:                                for (i = beg; i <= lexnumber; i++)
                    133:                                        if (f == MDELETED || (message[i - 1].m_flag & MDELETED) == 0)
                    134:                                                mark(i);
                    135:                                beg = 0;
                    136:                                break;
                    137:                        }
                    138:                        beg = lexnumber;
                    139:                        if (check(beg, f))
                    140:                                return(-1);
                    141:                        tok = scan(&bufp);
                    142:                        regret(tok);
                    143:                        if (tok != TDASH) {
                    144:                                mark(beg);
                    145:                                beg = 0;
                    146:                        }
                    147:                        break;
                    148: 
                    149:                case TPLUS:
                    150:                        if (beg != 0) {
                    151:                                printf("Non-numeric second argument\n");
                    152:                                return(-1);
                    153:                        }
                    154:                        i = valdot;
                    155:                        do {
                    156:                                i++;
                    157:                                if (i > msgCount) {
                    158:                                        printf("Referencing beyond EOF\n");
                    159:                                        return(-1);
                    160:                                }
                    161:                        } while ((message[i - 1].m_flag & MDELETED) != f);
                    162:                        mark(i);
                    163:                        break;
                    164: 
                    165:                case TDASH:
                    166:                        if (beg == 0) {
                    167:                                i = valdot;
                    168:                                do {
                    169:                                        i--;
                    170:                                        if (i <= 0) {
                    171:                                                printf("Referencing before 1\n");
                    172:                                                return(-1);
                    173:                                        }
                    174:                                } while ((message[i - 1].m_flag & MDELETED) != f);
                    175:                                mark(i);
                    176:                        }
                    177:                        break;
                    178: 
                    179:                case TSTRING:
                    180:                        if (beg != 0) {
                    181:                                printf("Non-numeric second argument\n");
                    182:                                return(-1);
                    183:                        }
                    184:                        other++;
                    185:                        if (lexstring[0] == ':') {
                    186:                                colresult = evalcol(lexstring[1]);
                    187:                                if (colresult == 0) {
                    188:                                        printf("Unknown colon modifier \"%s\"\n",
                    189:                                            lexstring);
                    190:                                        return(-1);
                    191:                                }
                    192:                                colmod |= colresult;
                    193:                        }
                    194:                        else
                    195:                                *np++ = savestr(lexstring);
                    196:                        break;
                    197: 
                    198:                case TDOLLAR:
                    199:                case TUP:
                    200:                case TDOT:
                    201:                        lexnumber = metamess(lexstring[0], f);
                    202:                        if (lexnumber == -1)
                    203:                                return(-1);
                    204:                        goto number;
                    205: 
                    206:                case TSTAR:
                    207:                        if (other) {
                    208:                                printf("Can't mix \"*\" with anything\n");
                    209:                                return(-1);
                    210:                        }
                    211:                        star++;
                    212:                        break;
                    213: 
                    214:                case TERROR:
                    215:                        return -1;
                    216:                }
                    217:                tok = scan(&bufp);
                    218:        }
                    219:        lastcolmod = colmod;
                    220:        *np = NOSTR;
                    221:        mc = 0;
                    222:        if (star) {
                    223:                for (i = 0; i < msgCount; i++)
                    224:                        if ((message[i].m_flag & MDELETED) == f) {
                    225:                                mark(i+1);
                    226:                                mc++;
                    227:                        }
                    228:                if (mc == 0) {
                    229:                        printf("No applicable messages.\n");
                    230:                        return(-1);
                    231:                }
                    232:                return(0);
                    233:        }
                    234: 
                    235:        /*
                    236:         * If no numbers were given, mark all of the messages,
                    237:         * so that we can unmark any whose sender was not selected
                    238:         * if any user names were given.
                    239:         */
                    240: 
                    241:        if ((np > namelist || colmod != 0) && mc == 0)
                    242:                for (i = 1; i <= msgCount; i++)
                    243:                        if ((message[i-1].m_flag & MDELETED) == f)
                    244:                                mark(i);
                    245: 
                    246:        /*
                    247:         * If any names were given, go through and eliminate any
                    248:         * messages whose senders were not requested.
                    249:         */
                    250: 
                    251:        if (np > namelist) {
                    252:                for (i = 1; i <= msgCount; i++) {
                    253:                        for (mc = 0, np = &namelist[0]; *np != NOSTR; np++)
                    254:                                if (**np == '/') {
                    255:                                        if (matchsubj(*np, i)) {
                    256:                                                mc++;
                    257:                                                break;
                    258:                                        }
                    259:                                }
                    260:                                else {
                    261:                                        if (matchsender(*np, i)) {
                    262:                                                mc++;
                    263:                                                break;
                    264:                                        }
                    265:                                }
                    266:                        if (mc == 0)
                    267:                                unmark(i);
                    268:                }
                    269: 
                    270:                /*
                    271:                 * Make sure we got some decent messages.
                    272:                 */
                    273: 
                    274:                mc = 0;
                    275:                for (i = 1; i <= msgCount; i++)
                    276:                        if (message[i-1].m_flag & MMARK) {
                    277:                                mc++;
                    278:                                break;
                    279:                        }
                    280:                if (mc == 0) {
                    281:                        printf("No applicable messages from {%s",
                    282:                                namelist[0]);
                    283:                        for (np = &namelist[1]; *np != NOSTR; np++)
                    284:                                printf(", %s", *np);
                    285:                        printf("}\n");
                    286:                        return(-1);
                    287:                }
                    288:        }
                    289: 
                    290:        /*
                    291:         * If any colon modifiers were given, go through and
                    292:         * unmark any messages which do not satisfy the modifiers.
                    293:         */
                    294: 
                    295:        if (colmod != 0) {
                    296:                for (i = 1; i <= msgCount; i++) {
                    297:                        register struct coltab *colp;
                    298: 
                    299:                        mp = &message[i - 1];
                    300:                        for (colp = &coltab[0]; colp->co_char; colp++)
                    301:                                if (colp->co_bit & colmod)
                    302:                                        if ((mp->m_flag & colp->co_mask)
                    303:                                            != colp->co_equal)
                    304:                                                unmark(i);
                    305:                        
                    306:                }
                    307:                for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    308:                        if (mp->m_flag & MMARK)
                    309:                                break;
                    310:                if (mp >= &message[msgCount]) {
                    311:                        register struct coltab *colp;
                    312: 
                    313:                        printf("No messages satisfy");
                    314:                        for (colp = &coltab[0]; colp->co_char; colp++)
                    315:                                if (colp->co_bit & colmod)
                    316:                                        printf(" :%c", colp->co_char);
                    317:                        printf("\n");
                    318:                        return(-1);
                    319:                }
                    320:        }
                    321:        return(0);
                    322: }
                    323: 
                    324: /*
                    325:  * Turn the character after a colon modifier into a bit
                    326:  * value.
                    327:  */
                    328: evalcol(col)
                    329: {
                    330:        register struct coltab *colp;
                    331: 
                    332:        if (col == 0)
                    333:                return(lastcolmod);
                    334:        for (colp = &coltab[0]; colp->co_char; colp++)
                    335:                if (colp->co_char == col)
                    336:                        return(colp->co_bit);
                    337:        return(0);
                    338: }
                    339: 
                    340: /*
                    341:  * Check the passed message number for legality and proper flags.
                    342:  * If f is MDELETED, then either kind will do.  Otherwise, the message
                    343:  * has to be undeleted.
                    344:  */
                    345: check(mesg, f)
                    346: {
                    347:        register struct message *mp;
                    348: 
                    349:        if (mesg < 1 || mesg > msgCount) {
                    350:                printf("%d: Invalid message number\n", mesg);
                    351:                return(-1);
                    352:        }
                    353:        mp = &message[mesg-1];
                    354:        if (f != MDELETED && (mp->m_flag & MDELETED) != 0) {
                    355:                printf("%d: Inappropriate message\n", mesg);
                    356:                return(-1);
                    357:        }
                    358:        return(0);
                    359: }
                    360: 
                    361: /*
                    362:  * Scan out the list of string arguments, shell style
                    363:  * for a RAWLIST.
                    364:  */
                    365: 
                    366: getrawlist(line, argv, argc)
                    367:        char line[];
                    368:        char **argv;
                    369:        int  argc;
                    370: {
                    371:        register char c, *cp, *cp2, quotec;
                    372:        int argn;
                    373:        char linebuf[BUFSIZ];
                    374: 
                    375:        argn = 0;
                    376:        cp = line;
                    377:        for (;;) {
                    378:                for (; *cp == ' ' || *cp == '\t'; cp++)
                    379:                        ;
                    380:                if (*cp == '\0')
                    381:                        break;
                    382:                if (argn >= argc - 1) {
                    383:                        printf(
                    384:                        "Too many elements in the list; excess discarded.\n");
                    385:                        break;
                    386:                }
                    387:                cp2 = linebuf;
                    388:                quotec = '\0';
                    389:                while ((c = *cp) != '\0') {
                    390:                        cp++;
                    391:                        if (quotec != '\0') {
                    392:                                if (c == quotec)
                    393:                                        quotec = '\0';
                    394:                                else if (c == '\\')
                    395:                                        switch (c = *cp++) {
                    396:                                        case '\0':
                    397:                                                *cp2++ = *--cp;
                    398:                                                break;
                    399:                                        case '0': case '1': case '2': case '3':
                    400:                                        case '4': case '5': case '6': case '7':
                    401:                                                c -= '0';
                    402:                                                if (*cp >= '0' && *cp <= '7')
                    403:                                                        c = c * 8 + *cp++ - '0';
                    404:                                                if (*cp >= '0' && *cp <= '7')
                    405:                                                        c = c * 8 + *cp++ - '0';
                    406:                                                *cp2++ = c;
                    407:                                                break;
                    408:                                        case 'b':
                    409:                                                *cp2++ = '\b';
                    410:                                                break;
                    411:                                        case 'f':
                    412:                                                *cp2++ = '\f';
                    413:                                                break;
                    414:                                        case 'n':
                    415:                                                *cp2++ = '\n';
                    416:                                                break;
                    417:                                        case 'r':
                    418:                                                *cp2++ = '\r';
                    419:                                                break;
                    420:                                        case 't':
                    421:                                                *cp2++ = '\t';
                    422:                                                break;
                    423:                                        case 'v':
                    424:                                                *cp2++ = '\v';
                    425:                                                break;
                    426:                                        }
                    427:                                else if (c == '^') {
                    428:                                        c = *cp++;
                    429:                                        if (c == '?')
                    430:                                                *cp2++ = '\177';
                    431:                                        /* null doesn't show up anyway */
                    432:                                        else if (c >= 'A' && c <= '_' ||
                    433:                                                 c >= 'a' && c <= 'z')
                    434:                                                *cp2++ &= 037;
                    435:                                        else
                    436:                                                *cp2++ = *--cp;
                    437:                                } else
                    438:                                        *cp2++ = c;
                    439:                        } else if (c == '"' || c == '\'')
                    440:                                quotec = c;
                    441:                        else if (c == ' ' || c == '\t')
                    442:                                break;
                    443:                        else
                    444:                                *cp2++ = c;
                    445:                }
                    446:                *cp2 = '\0';
                    447:                argv[argn++] = savestr(linebuf);
                    448:        }
                    449:        argv[argn] = NOSTR;
                    450:        return argn;
                    451: }
                    452: 
                    453: /*
                    454:  * scan out a single lexical item and return its token number,
                    455:  * updating the string pointer passed **p.  Also, store the value
                    456:  * of the number or string scanned in lexnumber or lexstring as
                    457:  * appropriate.  In any event, store the scanned `thing' in lexstring.
                    458:  */
                    459: 
                    460: struct lex {
                    461:        char    l_char;
                    462:        char    l_token;
                    463: } singles[] = {
                    464:        '$',    TDOLLAR,
                    465:        '.',    TDOT,
                    466:        '^',    TUP,
                    467:        '*',    TSTAR,
                    468:        '-',    TDASH,
                    469:        '+',    TPLUS,
                    470:        '(',    TOPEN,
                    471:        ')',    TCLOSE,
                    472:        0,      0
                    473: };
                    474: 
                    475: scan(sp)
                    476:        char **sp;
                    477: {
                    478:        register char *cp, *cp2;
                    479:        register int c;
                    480:        register struct lex *lp;
                    481:        int quotec;
                    482: 
                    483:        if (regretp >= 0) {
                    484:                strcpy(lexstring, string_stack[regretp]);
                    485:                lexnumber = numberstack[regretp];
                    486:                return(regretstack[regretp--]);
                    487:        }
                    488:        cp = *sp;
                    489:        cp2 = lexstring;
                    490:        c = *cp++;
                    491: 
                    492:        /*
                    493:         * strip away leading white space.
                    494:         */
                    495: 
                    496:        while (c == ' ' || c == '\t')
                    497:                c = *cp++;
                    498: 
                    499:        /*
                    500:         * If no characters remain, we are at end of line,
                    501:         * so report that.
                    502:         */
                    503: 
                    504:        if (c == '\0') {
                    505:                *sp = --cp;
                    506:                return(TEOL);
                    507:        }
                    508: 
                    509:        /*
                    510:         * If the leading character is a digit, scan
                    511:         * the number and convert it on the fly.
                    512:         * Return TNUMBER when done.
                    513:         */
                    514: 
                    515:        if (isdigit(c)) {
                    516:                lexnumber = 0;
                    517:                while (isdigit(c)) {
                    518:                        lexnumber = lexnumber*10 + c - '0';
                    519:                        *cp2++ = c;
                    520:                        c = *cp++;
                    521:                }
                    522:                *cp2 = '\0';
                    523:                *sp = --cp;
                    524:                return(TNUMBER);
                    525:        }
                    526: 
                    527:        /*
                    528:         * Check for single character tokens; return such
                    529:         * if found.
                    530:         */
                    531: 
                    532:        for (lp = &singles[0]; lp->l_char != 0; lp++)
                    533:                if (c == lp->l_char) {
                    534:                        lexstring[0] = c;
                    535:                        lexstring[1] = '\0';
                    536:                        *sp = cp;
                    537:                        return(lp->l_token);
                    538:                }
                    539: 
                    540:        /*
                    541:         * We've got a string!  Copy all the characters
                    542:         * of the string into lexstring, until we see
                    543:         * a null, space, or tab.
                    544:         * If the lead character is a " or ', save it
                    545:         * and scan until you get another.
                    546:         */
                    547: 
                    548:        quotec = 0;
                    549:        if (c == '\'' || c == '"') {
                    550:                quotec = c;
                    551:                c = *cp++;
                    552:        }
                    553:        while (c != '\0') {
                    554:                if (c == quotec) {
                    555:                        cp++;
                    556:                        break;
                    557:                }
                    558:                if (quotec == 0 && (c == ' ' || c == '\t'))
                    559:                        break;
                    560:                if (cp2 - lexstring < STRINGLEN-1)
                    561:                        *cp2++ = c;
                    562:                c = *cp++;
                    563:        }
                    564:        if (quotec && c == 0) {
                    565:                fprintf(stderr, "Missing %c\n", quotec);
                    566:                return TERROR;
                    567:        }
                    568:        *sp = --cp;
                    569:        *cp2 = '\0';
                    570:        return(TSTRING);
                    571: }
                    572: 
                    573: /*
                    574:  * Unscan the named token by pushing it onto the regret stack.
                    575:  */
                    576: 
                    577: regret(token)
                    578: {
                    579:        if (++regretp >= REGDEP)
                    580:                panic("Too many regrets");
                    581:        regretstack[regretp] = token;
                    582:        lexstring[STRINGLEN-1] = '\0';
                    583:        string_stack[regretp] = savestr(lexstring);
                    584:        numberstack[regretp] = lexnumber;
                    585: }
                    586: 
                    587: /*
                    588:  * Reset all the scanner global variables.
                    589:  */
                    590: 
                    591: scaninit()
                    592: {
                    593:        regretp = -1;
                    594: }
                    595: 
                    596: /*
                    597:  * Find the first message whose flags & m == f  and return
                    598:  * its message number.
                    599:  */
                    600: 
                    601: first(f, m)
                    602: {
                    603:        register struct message *mp;
                    604: 
                    605:        if (msgCount == 0)
                    606:                return 0;
                    607:        f &= MDELETED;
                    608:        m &= MDELETED;
                    609:        for (mp = dot; mp < &message[msgCount]; mp++)
                    610:                if ((mp->m_flag & m) == f)
                    611:                        return mp - message + 1;
                    612:        for (mp = dot-1; mp >= &message[0]; mp--)
                    613:                if ((mp->m_flag & m) == f)
                    614:                        return mp - message + 1;
                    615:        return 0;
                    616: }
                    617: 
                    618: /*
                    619:  * See if the passed name sent the passed message number.  Return true
                    620:  * if so.
                    621:  */
                    622: 
                    623: matchsender(str, mesg)
                    624:        char *str;
                    625: {
                    626:        register char *cp, *cp2, *backup;
                    627: 
                    628:        if (!*str)      /* null string matches nothing instead of everything */
                    629:                return 0;
                    630:        backup = cp2 = nameof(&message[mesg - 1], 0);
                    631:        cp = str;
                    632:        while (*cp2) {
                    633:                if (*cp == 0)
                    634:                        return(1);
                    635:                if (raise(*cp++) != raise(*cp2++)) {
                    636:                        cp2 = ++backup;
                    637:                        cp = str;
                    638:                }
                    639:        }
                    640:        return(*cp == 0);
                    641: }
                    642: 
                    643: /*
                    644:  * See if the given string matches inside the subject field of the
                    645:  * given message.  For the purpose of the scan, we ignore case differences.
                    646:  * If it does, return true.  The string search argument is assumed to
                    647:  * have the form "/search-string."  If it is of the form "/," we use the
                    648:  * previous search string.
                    649:  */
                    650: 
                    651: char lastscan[128];
                    652: 
                    653: matchsubj(str, mesg)
                    654:        char *str;
                    655: {
                    656:        register struct message *mp;
                    657:        register char *cp, *cp2, *backup;
                    658: 
                    659:        str++;
                    660:        if (strlen(str) == 0)
                    661:                str = lastscan;
                    662:        else
                    663:                strcpy(lastscan, str);
                    664:        mp = &message[mesg-1];
                    665:        
                    666:        /*
                    667:         * Now look, ignoring case, for the word in the string.
                    668:         */
                    669: 
                    670:        cp = str;
                    671:        cp2 = hfield("subject", mp);
                    672:        if (cp2 == NOSTR)
                    673:                return(0);
                    674:        backup = cp2;
                    675:        while (*cp2) {
                    676:                if (*cp == 0)
                    677:                        return(1);
                    678:                if (raise(*cp++) != raise(*cp2++)) {
                    679:                        cp2 = ++backup;
                    680:                        cp = str;
                    681:                }
                    682:        }
                    683:        return(*cp == 0);
                    684: }
                    685: 
                    686: /*
                    687:  * Mark the named message by setting its mark bit.
                    688:  */
                    689: 
                    690: mark(mesg)
                    691: {
                    692:        register int i;
                    693: 
                    694:        i = mesg;
                    695:        if (i < 1 || i > msgCount)
                    696:                panic("Bad message number to mark");
                    697:        message[i-1].m_flag |= MMARK;
                    698: }
                    699: 
                    700: /*
                    701:  * Unmark the named message.
                    702:  */
                    703: 
                    704: unmark(mesg)
                    705: {
                    706:        register int i;
                    707: 
                    708:        i = mesg;
                    709:        if (i < 1 || i > msgCount)
                    710:                panic("Bad message number to unmark");
                    711:        message[i-1].m_flag &= ~MMARK;
                    712: }
                    713: 
                    714: /*
                    715:  * Return the message number corresponding to the passed meta character.
                    716:  */
                    717: 
                    718: metamess(meta, f)
                    719: {
                    720:        register int c, m;
                    721:        register struct message *mp;
                    722: 
                    723:        c = meta;
                    724:        switch (c) {
                    725:        case '^':
                    726:                /*
                    727:                 * First 'good' message left.
                    728:                 */
                    729:                for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    730:                        if ((mp->m_flag & MDELETED) == f)
                    731:                                return(mp - &message[0] + 1);
                    732:                printf("No applicable messages\n");
                    733:                return(-1);
                    734: 
                    735:        case '$':
                    736:                /*
                    737:                 * Last 'good message left.
                    738:                 */
                    739:                for (mp = &message[msgCount-1]; mp >= &message[0]; mp--)
                    740:                        if ((mp->m_flag & MDELETED) == f)
                    741:                                return(mp - &message[0] + 1);
                    742:                printf("No applicable messages\n");
                    743:                return(-1);
                    744: 
                    745:        case '.':
                    746:                /* 
                    747:                 * Current message.
                    748:                 */
                    749:                m = dot - &message[0] + 1;
                    750:                if ((dot->m_flag & MDELETED) != f) {
                    751:                        printf("%d: Inappropriate message\n", m);
                    752:                        return(-1);
                    753:                }
                    754:                return(m);
                    755: 
                    756:        default:
                    757:                printf("Unknown metachar (%c)\n", c);
                    758:                return(-1);
                    759:        }
                    760: }

unix.superglobalmegacorp.com

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