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

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