[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.13

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