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

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