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

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