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

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