[BACK]Return to cmd3.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/cmd3.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:  * Copyright (c) 1980, 1993
        !             3:  *     The Regents of the University of California.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: #ifndef lint
        !            35: static char sccsid[] = "@(#)cmd3.c     8.1 (Berkeley) 6/6/93";
        !            36: static char rcsid[] = "$Id: cmd3.c,v 1.4 1994/06/29 05:09:11 deraadt Exp $";
        !            37: #endif /* not lint */
        !            38:
        !            39: #include "rcv.h"
        !            40: #include "extern.h"
        !            41:
        !            42: /*
        !            43:  * Mail -- a mail program
        !            44:  *
        !            45:  * Still more user commands.
        !            46:  */
        !            47:
        !            48: /*
        !            49:  * Process a shell escape by saving signals, ignoring signals,
        !            50:  * and forking a sh -c
        !            51:  */
        !            52: int
        !            53: shell(str)
        !            54:        char *str;
        !            55: {
        !            56:        sig_t sigint = signal(SIGINT, SIG_IGN);
        !            57:        char *shell;
        !            58:        char cmd[BUFSIZ];
        !            59:
        !            60:        (void) strcpy(cmd, str);
        !            61:        if (bangexp(cmd) < 0)
        !            62:                return 1;
        !            63:        if ((shell = value("SHELL")) == NOSTR)
        !            64:                shell = _PATH_CSHELL;
        !            65:        (void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR);
        !            66:        (void) signal(SIGINT, sigint);
        !            67:        printf("!\n");
        !            68:        return 0;
        !            69: }
        !            70:
        !            71: /*
        !            72:  * Fork an interactive shell.
        !            73:  */
        !            74: /*ARGSUSED*/
        !            75: int
        !            76: dosh(str)
        !            77:        char *str;
        !            78: {
        !            79:        sig_t sigint = signal(SIGINT, SIG_IGN);
        !            80:        char *shell;
        !            81:
        !            82:        if ((shell = value("SHELL")) == NOSTR)
        !            83:                shell = _PATH_CSHELL;
        !            84:        (void) run_command(shell, 0, -1, -1, NOSTR, NOSTR, NOSTR);
        !            85:        (void) signal(SIGINT, sigint);
        !            86:        putchar('\n');
        !            87:        return 0;
        !            88: }
        !            89:
        !            90: /*
        !            91:  * Expand the shell escape by expanding unescaped !'s into the
        !            92:  * last issued command where possible.
        !            93:  */
        !            94:
        !            95: char   lastbang[128];
        !            96:
        !            97: int
        !            98: bangexp(str)
        !            99:        char *str;
        !           100: {
        !           101:        char bangbuf[BUFSIZ];
        !           102:        register char *cp, *cp2;
        !           103:        register int n;
        !           104:        int changed = 0;
        !           105:
        !           106:        cp = str;
        !           107:        cp2 = bangbuf;
        !           108:        n = BUFSIZ;
        !           109:        while (*cp) {
        !           110:                if (*cp == '!') {
        !           111:                        if (n < strlen(lastbang)) {
        !           112: overf:
        !           113:                                printf("Command buffer overflow\n");
        !           114:                                return(-1);
        !           115:                        }
        !           116:                        changed++;
        !           117:                        strcpy(cp2, lastbang);
        !           118:                        cp2 += strlen(lastbang);
        !           119:                        n -= strlen(lastbang);
        !           120:                        cp++;
        !           121:                        continue;
        !           122:                }
        !           123:                if (*cp == '\\' && cp[1] == '!') {
        !           124:                        if (--n <= 1)
        !           125:                                goto overf;
        !           126:                        *cp2++ = '!';
        !           127:                        cp += 2;
        !           128:                        changed++;
        !           129:                }
        !           130:                if (--n <= 1)
        !           131:                        goto overf;
        !           132:                *cp2++ = *cp++;
        !           133:        }
        !           134:        *cp2 = 0;
        !           135:        if (changed) {
        !           136:                printf("!%s\n", bangbuf);
        !           137:                fflush(stdout);
        !           138:        }
        !           139:        strcpy(str, bangbuf);
        !           140:        strncpy(lastbang, bangbuf, 128);
        !           141:        lastbang[127] = 0;
        !           142:        return(0);
        !           143: }
        !           144:
        !           145: /*
        !           146:  * Print out a nice help message from some file or another.
        !           147:  */
        !           148:
        !           149: int
        !           150: help()
        !           151: {
        !           152:        register c;
        !           153:        register FILE *f;
        !           154:
        !           155:        if ((f = Fopen(_PATH_HELP, "r")) == NULL) {
        !           156:                perror(_PATH_HELP);
        !           157:                return(1);
        !           158:        }
        !           159:        while ((c = getc(f)) != EOF)
        !           160:                putchar(c);
        !           161:        Fclose(f);
        !           162:        return(0);
        !           163: }
        !           164:
        !           165: /*
        !           166:  * Change user's working directory.
        !           167:  */
        !           168: int
        !           169: schdir(arglist)
        !           170:        char **arglist;
        !           171: {
        !           172:        char *cp;
        !           173:
        !           174:        if (*arglist == NOSTR)
        !           175:                cp = homedir;
        !           176:        else
        !           177:                if ((cp = expand(*arglist)) == NOSTR)
        !           178:                        return(1);
        !           179:        if (chdir(cp) < 0) {
        !           180:                perror(cp);
        !           181:                return(1);
        !           182:        }
        !           183:        return 0;
        !           184: }
        !           185:
        !           186: int
        !           187: respond(msgvec)
        !           188:        int *msgvec;
        !           189: {
        !           190:        if (value("Replyall") == NOSTR)
        !           191:                return (_respond(msgvec));
        !           192:        else
        !           193:                return (_Respond(msgvec));
        !           194: }
        !           195:
        !           196: /*
        !           197:  * Reply to a list of messages.  Extract each name from the
        !           198:  * message header and send them off to mail1()
        !           199:  */
        !           200: int
        !           201: _respond(msgvec)
        !           202:        int *msgvec;
        !           203: {
        !           204:        struct message *mp;
        !           205:        char *cp, *rcv, *replyto;
        !           206:        char **ap;
        !           207:        struct name *np;
        !           208:        struct header head;
        !           209:
        !           210:        if (msgvec[1] != 0) {
        !           211:                printf("Sorry, can't reply to multiple messages at once\n");
        !           212:                return(1);
        !           213:        }
        !           214:        mp = &message[msgvec[0] - 1];
        !           215:        touch(mp);
        !           216:        dot = mp;
        !           217:        if ((rcv = skin(hfield("from", mp))) == NOSTR)
        !           218:                rcv = skin(nameof(mp, 1));
        !           219:        if ((replyto = skin(hfield("reply-to", mp))) != NOSTR)
        !           220:                np = extract(replyto, GTO);
        !           221:        else if ((cp = skin(hfield("to", mp))) != NOSTR)
        !           222:                np = extract(cp, GTO);
        !           223:        else
        !           224:                np = NIL;
        !           225:        np = elide(np);
        !           226:        /*
        !           227:         * Delete my name from the reply list,
        !           228:         * and with it, all my alternate names.
        !           229:         */
        !           230:        np = delname(np, myname);
        !           231:        if (altnames)
        !           232:                for (ap = altnames; *ap; ap++)
        !           233:                        np = delname(np, *ap);
        !           234:        if (np != NIL && replyto == NOSTR)
        !           235:                np = cat(np, extract(rcv, GTO));
        !           236:        else if (np == NIL) {
        !           237:                if (replyto != NOSTR)
        !           238:                        printf("Empty reply-to field -- replying to author\n");
        !           239:                np = extract(rcv, GTO);
        !           240:        }
        !           241:        head.h_to = np;
        !           242:        if ((head.h_subject = hfield("subject", mp)) == NOSTR)
        !           243:                head.h_subject = hfield("subj", mp);
        !           244:        head.h_subject = reedit(head.h_subject);
        !           245:        if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) {
        !           246:                np = elide(extract(cp, GCC));
        !           247:                np = delname(np, myname);
        !           248:                if (altnames != 0)
        !           249:                        for (ap = altnames; *ap; ap++)
        !           250:                                np = delname(np, *ap);
        !           251:                head.h_cc = np;
        !           252:        } else
        !           253:                head.h_cc = NIL;
        !           254:        head.h_bcc = NIL;
        !           255:        head.h_smopts = NIL;
        !           256:        mail1(&head, 1);
        !           257:        return(0);
        !           258: }
        !           259:
        !           260: /*
        !           261:  * Modify the subject we are replying to to begin with Re: if
        !           262:  * it does not already.
        !           263:  */
        !           264: char *
        !           265: reedit(subj)
        !           266:        register char *subj;
        !           267: {
        !           268:        char *newsubj;
        !           269:
        !           270:        if (subj == NOSTR)
        !           271:                return NOSTR;
        !           272:        if ((subj[0] == 'r' || subj[0] == 'R') &&
        !           273:            (subj[1] == 'e' || subj[1] == 'E') &&
        !           274:            subj[2] == ':')
        !           275:                return subj;
        !           276:        newsubj = salloc(strlen(subj) + 5);
        !           277:        strcpy(newsubj, "Re: ");
        !           278:        strcpy(newsubj + 4, subj);
        !           279:        return newsubj;
        !           280: }
        !           281:
        !           282: /*
        !           283:  * Preserve the named messages, so that they will be sent
        !           284:  * back to the system mailbox.
        !           285:  */
        !           286: int
        !           287: preserve(msgvec)
        !           288:        int *msgvec;
        !           289: {
        !           290:        register struct message *mp;
        !           291:        register int *ip, mesg;
        !           292:
        !           293:        if (edit) {
        !           294:                printf("Cannot \"preserve\" in edit mode\n");
        !           295:                return(1);
        !           296:        }
        !           297:        for (ip = msgvec; *ip != NULL; ip++) {
        !           298:                mesg = *ip;
        !           299:                mp = &message[mesg-1];
        !           300:                mp->m_flag |= MPRESERVE;
        !           301:                mp->m_flag &= ~MBOX;
        !           302:                dot = mp;
        !           303:        }
        !           304:        return(0);
        !           305: }
        !           306:
        !           307: /*
        !           308:  * Mark all given messages as unread.
        !           309:  */
        !           310: int
        !           311: unread(msgvec)
        !           312:        int     msgvec[];
        !           313: {
        !           314:        register int *ip;
        !           315:
        !           316:        for (ip = msgvec; *ip != NULL; ip++) {
        !           317:                dot = &message[*ip-1];
        !           318:                dot->m_flag &= ~(MREAD|MTOUCH);
        !           319:                dot->m_flag |= MSTATUS;
        !           320:        }
        !           321:        return(0);
        !           322: }
        !           323:
        !           324: /*
        !           325:  * Print the size of each message.
        !           326:  */
        !           327: int
        !           328: messize(msgvec)
        !           329:        int *msgvec;
        !           330: {
        !           331:        register struct message *mp;
        !           332:        register int *ip, mesg;
        !           333:
        !           334:        for (ip = msgvec; *ip != NULL; ip++) {
        !           335:                mesg = *ip;
        !           336:                mp = &message[mesg-1];
        !           337:                printf("%d: %d/%ld\n", mesg, mp->m_lines, mp->m_size);
        !           338:        }
        !           339:        return(0);
        !           340: }
        !           341:
        !           342: /*
        !           343:  * Quit quickly.  If we are sourcing, just pop the input level
        !           344:  * by returning an error.
        !           345:  */
        !           346: int
        !           347: rexit(e)
        !           348:        int e;
        !           349: {
        !           350:        if (sourcing)
        !           351:                return(1);
        !           352:        exit(e);
        !           353:        /*NOTREACHED*/
        !           354: }
        !           355:
        !           356: /*
        !           357:  * Set or display a variable value.  Syntax is similar to that
        !           358:  * of csh.
        !           359:  */
        !           360: int
        !           361: set(arglist)
        !           362:        char **arglist;
        !           363: {
        !           364:        register struct var *vp;
        !           365:        register char *cp, *cp2;
        !           366:        char varbuf[BUFSIZ], **ap, **p;
        !           367:        int errs, h, s;
        !           368:
        !           369:        if (*arglist == NOSTR) {
        !           370:                for (h = 0, s = 1; h < HSHSIZE; h++)
        !           371:                        for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
        !           372:                                s++;
        !           373:                ap = (char **) salloc(s * sizeof *ap);
        !           374:                for (h = 0, p = ap; h < HSHSIZE; h++)
        !           375:                        for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
        !           376:                                *p++ = vp->v_name;
        !           377:                *p = NOSTR;
        !           378:                sort(ap);
        !           379:                for (p = ap; *p != NOSTR; p++)
        !           380:                        printf("%s\t%s\n", *p, value(*p));
        !           381:                return(0);
        !           382:        }
        !           383:        errs = 0;
        !           384:        for (ap = arglist; *ap != NOSTR; ap++) {
        !           385:                cp = *ap;
        !           386:                cp2 = varbuf;
        !           387:                while (*cp != '=' && *cp != '\0')
        !           388:                        *cp2++ = *cp++;
        !           389:                *cp2 = '\0';
        !           390:                if (*cp == '\0')
        !           391:                        cp = "";
        !           392:                else
        !           393:                        cp++;
        !           394:                if (equal(varbuf, "")) {
        !           395:                        printf("Non-null variable name required\n");
        !           396:                        errs++;
        !           397:                        continue;
        !           398:                }
        !           399:                assign(varbuf, cp);
        !           400:        }
        !           401:        return(errs);
        !           402: }
        !           403:
        !           404: /*
        !           405:  * Unset a bunch of variable values.
        !           406:  */
        !           407: int
        !           408: unset(arglist)
        !           409:        char **arglist;
        !           410: {
        !           411:        register struct var *vp, *vp2;
        !           412:        int errs, h;
        !           413:        char **ap;
        !           414:
        !           415:        errs = 0;
        !           416:        for (ap = arglist; *ap != NOSTR; ap++) {
        !           417:                if ((vp2 = lookup(*ap)) == NOVAR) {
        !           418:                        if (!sourcing) {
        !           419:                                printf("\"%s\": undefined variable\n", *ap);
        !           420:                                errs++;
        !           421:                        }
        !           422:                        continue;
        !           423:                }
        !           424:                h = hash(*ap);
        !           425:                if (vp2 == variables[h]) {
        !           426:                        variables[h] = variables[h]->v_link;
        !           427:                        vfree(vp2->v_name);
        !           428:                        vfree(vp2->v_value);
        !           429:                        free((char *)vp2);
        !           430:                        continue;
        !           431:                }
        !           432:                for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
        !           433:                        ;
        !           434:                vp->v_link = vp2->v_link;
        !           435:                vfree(vp2->v_name);
        !           436:                vfree(vp2->v_value);
        !           437:                free((char *) vp2);
        !           438:        }
        !           439:        return(errs);
        !           440: }
        !           441:
        !           442: /*
        !           443:  * Put add users to a group.
        !           444:  */
        !           445: int
        !           446: group(argv)
        !           447:        char **argv;
        !           448: {
        !           449:        register struct grouphead *gh;
        !           450:        register struct group *gp;
        !           451:        register int h;
        !           452:        int s;
        !           453:        char **ap, *gname, **p;
        !           454:
        !           455:        if (*argv == NOSTR) {
        !           456:                for (h = 0, s = 1; h < HSHSIZE; h++)
        !           457:                        for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
        !           458:                                s++;
        !           459:                ap = (char **) salloc(s * sizeof *ap);
        !           460:                for (h = 0, p = ap; h < HSHSIZE; h++)
        !           461:                        for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
        !           462:                                *p++ = gh->g_name;
        !           463:                *p = NOSTR;
        !           464:                sort(ap);
        !           465:                for (p = ap; *p != NOSTR; p++)
        !           466:                        printgroup(*p);
        !           467:                return(0);
        !           468:        }
        !           469:        if (argv[1] == NOSTR) {
        !           470:                printgroup(*argv);
        !           471:                return(0);
        !           472:        }
        !           473:        gname = *argv;
        !           474:        h = hash(gname);
        !           475:        if ((gh = findgroup(gname)) == NOGRP) {
        !           476:                gh = (struct grouphead *) calloc(sizeof *gh, 1);
        !           477:                gh->g_name = vcopy(gname);
        !           478:                gh->g_list = NOGE;
        !           479:                gh->g_link = groups[h];
        !           480:                groups[h] = gh;
        !           481:        }
        !           482:
        !           483:        /*
        !           484:         * Insert names from the command list into the group.
        !           485:         * Who cares if there are duplicates?  They get tossed
        !           486:         * later anyway.
        !           487:         */
        !           488:
        !           489:        for (ap = argv+1; *ap != NOSTR; ap++) {
        !           490:                gp = (struct group *) calloc(sizeof *gp, 1);
        !           491:                gp->ge_name = vcopy(*ap);
        !           492:                gp->ge_link = gh->g_list;
        !           493:                gh->g_list = gp;
        !           494:        }
        !           495:        return(0);
        !           496: }
        !           497:
        !           498: /*
        !           499:  * Sort the passed string vecotor into ascending dictionary
        !           500:  * order.
        !           501:  */
        !           502: void
        !           503: sort(list)
        !           504:        char **list;
        !           505: {
        !           506:        register char **ap;
        !           507:        int diction();
        !           508:
        !           509:        for (ap = list; *ap != NOSTR; ap++)
        !           510:                ;
        !           511:        if (ap-list < 2)
        !           512:                return;
        !           513:        qsort(list, ap-list, sizeof(*list), diction);
        !           514: }
        !           515:
        !           516: /*
        !           517:  * Do a dictionary order comparison of the arguments from
        !           518:  * qsort.
        !           519:  */
        !           520: int
        !           521: diction(a, b)
        !           522:        const void *a, *b;
        !           523: {
        !           524:        return(strcmp(*(char **)a, *(char **)b));
        !           525: }
        !           526:
        !           527: /*
        !           528:  * The do nothing command for comments.
        !           529:  */
        !           530:
        !           531: /*ARGSUSED*/
        !           532: int
        !           533: null(e)
        !           534:        int e;
        !           535: {
        !           536:        return 0;
        !           537: }
        !           538:
        !           539: /*
        !           540:  * Change to another file.  With no argument, print information about
        !           541:  * the current file.
        !           542:  */
        !           543: int
        !           544: file(argv)
        !           545:        register char **argv;
        !           546: {
        !           547:
        !           548:        if (argv[0] == NOSTR) {
        !           549:                newfileinfo();
        !           550:                return 0;
        !           551:        }
        !           552:        if (setfile(*argv) < 0)
        !           553:                return 1;
        !           554:        announce();
        !           555:        return 0;
        !           556: }
        !           557:
        !           558: /*
        !           559:  * Expand file names like echo
        !           560:  */
        !           561: int
        !           562: echo(argv)
        !           563:        char **argv;
        !           564: {
        !           565:        register char **ap;
        !           566:        register char *cp;
        !           567:
        !           568:        for (ap = argv; *ap != NOSTR; ap++) {
        !           569:                cp = *ap;
        !           570:                if ((cp = expand(cp)) != NOSTR) {
        !           571:                        if (ap != argv)
        !           572:                                putchar(' ');
        !           573:                        printf("%s", cp);
        !           574:                }
        !           575:        }
        !           576:        putchar('\n');
        !           577:        return 0;
        !           578: }
        !           579:
        !           580: int
        !           581: Respond(msgvec)
        !           582:        int *msgvec;
        !           583: {
        !           584:        if (value("Replyall") == NOSTR)
        !           585:                return (_Respond(msgvec));
        !           586:        else
        !           587:                return (_respond(msgvec));
        !           588: }
        !           589:
        !           590: /*
        !           591:  * Reply to a series of messages by simply mailing to the senders
        !           592:  * and not messing around with the To: and Cc: lists as in normal
        !           593:  * reply.
        !           594:  */
        !           595: int
        !           596: _Respond(msgvec)
        !           597:        int msgvec[];
        !           598: {
        !           599:        struct header head;
        !           600:        struct message *mp;
        !           601:        register int *ap;
        !           602:        register char *cp;
        !           603:
        !           604:        head.h_to = NIL;
        !           605:        for (ap = msgvec; *ap != 0; ap++) {
        !           606:                mp = &message[*ap - 1];
        !           607:                touch(mp);
        !           608:                dot = mp;
        !           609:                if ((cp = skin(hfield("from", mp))) == NOSTR)
        !           610:                        cp = skin(nameof(mp, 2));
        !           611:                head.h_to = cat(head.h_to, extract(cp, GTO));
        !           612:        }
        !           613:        if (head.h_to == NIL)
        !           614:                return 0;
        !           615:        mp = &message[msgvec[0] - 1];
        !           616:        if ((head.h_subject = hfield("subject", mp)) == NOSTR)
        !           617:                head.h_subject = hfield("subj", mp);
        !           618:        head.h_subject = reedit(head.h_subject);
        !           619:        head.h_cc = NIL;
        !           620:        head.h_bcc = NIL;
        !           621:        head.h_smopts = NIL;
        !           622:        mail1(&head, 1);
        !           623:        return 0;
        !           624: }
        !           625:
        !           626: /*
        !           627:  * Conditional commands.  These allow one to parameterize one's
        !           628:  * .mailrc and do some things if sending, others if receiving.
        !           629:  */
        !           630: int
        !           631: ifcmd(argv)
        !           632:        char **argv;
        !           633: {
        !           634:        register char *cp;
        !           635:
        !           636:        if (cond != CANY) {
        !           637:                printf("Illegal nested \"if\"\n");
        !           638:                return(1);
        !           639:        }
        !           640:        cond = CANY;
        !           641:        cp = argv[0];
        !           642:        switch (*cp) {
        !           643:        case 'r': case 'R':
        !           644:                cond = CRCV;
        !           645:                break;
        !           646:
        !           647:        case 's': case 'S':
        !           648:                cond = CSEND;
        !           649:                break;
        !           650:
        !           651:        default:
        !           652:                printf("Unrecognized if-keyword: \"%s\"\n", cp);
        !           653:                return(1);
        !           654:        }
        !           655:        return(0);
        !           656: }
        !           657:
        !           658: /*
        !           659:  * Implement 'else'.  This is pretty simple -- we just
        !           660:  * flip over the conditional flag.
        !           661:  */
        !           662: int
        !           663: elsecmd()
        !           664: {
        !           665:
        !           666:        switch (cond) {
        !           667:        case CANY:
        !           668:                printf("\"Else\" without matching \"if\"\n");
        !           669:                return(1);
        !           670:
        !           671:        case CSEND:
        !           672:                cond = CRCV;
        !           673:                break;
        !           674:
        !           675:        case CRCV:
        !           676:                cond = CSEND;
        !           677:                break;
        !           678:
        !           679:        default:
        !           680:                printf("Mail's idea of conditions is screwed up\n");
        !           681:                cond = CANY;
        !           682:                break;
        !           683:        }
        !           684:        return(0);
        !           685: }
        !           686:
        !           687: /*
        !           688:  * End of if statement.  Just set cond back to anything.
        !           689:  */
        !           690: int
        !           691: endifcmd()
        !           692: {
        !           693:
        !           694:        if (cond == CANY) {
        !           695:                printf("\"Endif\" without matching \"if\"\n");
        !           696:                return(1);
        !           697:        }
        !           698:        cond = CANY;
        !           699:        return(0);
        !           700: }
        !           701:
        !           702: /*
        !           703:  * Set the list of alternate names.
        !           704:  */
        !           705: int
        !           706: alternates(namelist)
        !           707:        char **namelist;
        !           708: {
        !           709:        register int c;
        !           710:        register char **ap, **ap2, *cp;
        !           711:
        !           712:        c = argcount(namelist) + 1;
        !           713:        if (c == 1) {
        !           714:                if (altnames == 0)
        !           715:                        return(0);
        !           716:                for (ap = altnames; *ap; ap++)
        !           717:                        printf("%s ", *ap);
        !           718:                printf("\n");
        !           719:                return(0);
        !           720:        }
        !           721:        if (altnames != 0)
        !           722:                free((char *) altnames);
        !           723:        altnames = (char **) calloc((unsigned) c, sizeof (char *));
        !           724:        for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
        !           725:                cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char));
        !           726:                strcpy(cp, *ap);
        !           727:                *ap2 = cp;
        !           728:        }
        !           729:        *ap2 = 0;
        !           730:        return(0);
        !           731: }