[BACK]Return to cmd2.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/cmd2.c, Revision 1.1.1.1

1.1       deraadt     1: /*
                      2:  * Copyright (c) 1980, 1993
                      3:  *     The Regents of the University of California.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33:
                     34: #ifndef lint
                     35: static char sccsid[] = "from: @(#)cmd2.c       8.1 (Berkeley) 6/6/93";
                     36: static char rcsid[] = "$Id: cmd2.c,v 1.4 1994/12/28 13:16:12 mycroft Exp $";
                     37: #endif /* not lint */
                     38:
                     39: #include "rcv.h"
                     40: #include <sys/wait.h>
                     41: #include "extern.h"
                     42:
                     43: /*
                     44:  * Mail -- a mail program
                     45:  *
                     46:  * More user commands.
                     47:  */
                     48:
                     49: /*
                     50:  * If any arguments were given, go to the next applicable argument
                     51:  * following dot, otherwise, go to the next applicable message.
                     52:  * If given as first command with no arguments, print first message.
                     53:  */
                     54: int
                     55: next(msgvec)
                     56:        int *msgvec;
                     57: {
                     58:        register struct message *mp;
                     59:        register int *ip, *ip2;
                     60:        int list[2], mdot;
                     61:
                     62:        if (*msgvec != NULL) {
                     63:
                     64:                /*
                     65:                 * If some messages were supplied, find the
                     66:                 * first applicable one following dot using
                     67:                 * wrap around.
                     68:                 */
                     69:
                     70:                mdot = dot - &message[0] + 1;
                     71:
                     72:                /*
                     73:                 * Find the first message in the supplied
                     74:                 * message list which follows dot.
                     75:                 */
                     76:
                     77:                for (ip = msgvec; *ip != NULL; ip++)
                     78:                        if (*ip > mdot)
                     79:                                break;
                     80:                if (*ip == NULL)
                     81:                        ip = msgvec;
                     82:                ip2 = ip;
                     83:                do {
                     84:                        mp = &message[*ip2 - 1];
                     85:                        if ((mp->m_flag & MDELETED) == 0) {
                     86:                                dot = mp;
                     87:                                goto hitit;
                     88:                        }
                     89:                        if (*ip2 != NULL)
                     90:                                ip2++;
                     91:                        if (*ip2 == NULL)
                     92:                                ip2 = msgvec;
                     93:                } while (ip2 != ip);
                     94:                printf("No messages applicable\n");
                     95:                return(1);
                     96:        }
                     97:
                     98:        /*
                     99:         * If this is the first command, select message 1.
                    100:         * Note that this must exist for us to get here at all.
                    101:         */
                    102:
                    103:        if (!sawcom)
                    104:                goto hitit;
                    105:
                    106:        /*
                    107:         * Just find the next good message after dot, no
                    108:         * wraparound.
                    109:         */
                    110:
                    111:        for (mp = dot+1; mp < &message[msgCount]; mp++)
                    112:                if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
                    113:                        break;
                    114:        if (mp >= &message[msgCount]) {
                    115:                printf("At EOF\n");
                    116:                return(0);
                    117:        }
                    118:        dot = mp;
                    119: hitit:
                    120:        /*
                    121:         * Print dot.
                    122:         */
                    123:
                    124:        list[0] = dot - &message[0] + 1;
                    125:        list[1] = NULL;
                    126:        return(type(list));
                    127: }
                    128:
                    129: /*
                    130:  * Save a message in a file.  Mark the message as saved
                    131:  * so we can discard when the user quits.
                    132:  */
                    133: int
                    134: save(str)
                    135:        char str[];
                    136: {
                    137:
                    138:        return save1(str, 1, "save", saveignore);
                    139: }
                    140:
                    141: /*
                    142:  * Copy a message to a file without affected its saved-ness
                    143:  */
                    144: int
                    145: copycmd(str)
                    146:        char str[];
                    147: {
                    148:
                    149:        return save1(str, 0, "copy", saveignore);
                    150: }
                    151:
                    152: /*
                    153:  * Save/copy the indicated messages at the end of the passed file name.
                    154:  * If mark is true, mark the message "saved."
                    155:  */
                    156: int
                    157: save1(str, mark, cmd, ignore)
                    158:        char str[];
                    159:        int mark;
                    160:        char *cmd;
                    161:        struct ignoretab *ignore;
                    162: {
                    163:        register int *ip;
                    164:        register struct message *mp;
                    165:        char *file, *disp;
                    166:        int f, *msgvec;
                    167:        FILE *obuf;
                    168:
                    169:        msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
                    170:        if ((file = snarf(str, &f)) == NOSTR)
                    171:                return(1);
                    172:        if (!f) {
                    173:                *msgvec = first(0, MMNORM);
                    174:                if (*msgvec == NULL) {
                    175:                        printf("No messages to %s.\n", cmd);
                    176:                        return(1);
                    177:                }
                    178:                msgvec[1] = NULL;
                    179:        }
                    180:        if (f && getmsglist(str, msgvec, 0) < 0)
                    181:                return(1);
                    182:        if ((file = expand(file)) == NOSTR)
                    183:                return(1);
                    184:        printf("\"%s\" ", file);
                    185:        fflush(stdout);
                    186:        if (access(file, 0) >= 0)
                    187:                disp = "[Appended]";
                    188:        else
                    189:                disp = "[New file]";
                    190:        if ((obuf = Fopen(file, "a")) == NULL) {
                    191:                perror(NOSTR);
                    192:                return(1);
                    193:        }
                    194:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    195:                mp = &message[*ip - 1];
                    196:                touch(mp);
                    197:                if (send(mp, obuf, ignore, NOSTR) < 0) {
                    198:                        perror(file);
                    199:                        Fclose(obuf);
                    200:                        return(1);
                    201:                }
                    202:                if (mark)
                    203:                        mp->m_flag |= MSAVED;
                    204:        }
                    205:        fflush(obuf);
                    206:        if (ferror(obuf))
                    207:                perror(file);
                    208:        Fclose(obuf);
                    209:        printf("%s\n", disp);
                    210:        return(0);
                    211: }
                    212:
                    213: /*
                    214:  * Write the indicated messages at the end of the passed
                    215:  * file name, minus header and trailing blank line.
                    216:  */
                    217: int
                    218: swrite(str)
                    219:        char str[];
                    220: {
                    221:
                    222:        return save1(str, 1, "write", ignoreall);
                    223: }
                    224:
                    225: /*
                    226:  * Snarf the file from the end of the command line and
                    227:  * return a pointer to it.  If there is no file attached,
                    228:  * just return NOSTR.  Put a null in front of the file
                    229:  * name so that the message list processing won't see it,
                    230:  * unless the file name is the only thing on the line, in
                    231:  * which case, return 0 in the reference flag variable.
                    232:  */
                    233:
                    234: char *
                    235: snarf(linebuf, flag)
                    236:        char linebuf[];
                    237:        int *flag;
                    238: {
                    239:        register char *cp;
                    240:
                    241:        *flag = 1;
                    242:        cp = strlen(linebuf) + linebuf - 1;
                    243:
                    244:        /*
                    245:         * Strip away trailing blanks.
                    246:         */
                    247:
                    248:        while (cp > linebuf && isspace(*cp))
                    249:                cp--;
                    250:        *++cp = 0;
                    251:
                    252:        /*
                    253:         * Now search for the beginning of the file name.
                    254:         */
                    255:
                    256:        while (cp > linebuf && !isspace(*cp))
                    257:                cp--;
                    258:        if (*cp == '\0') {
                    259:                printf("No file specified.\n");
                    260:                return(NOSTR);
                    261:        }
                    262:        if (isspace(*cp))
                    263:                *cp++ = 0;
                    264:        else
                    265:                *flag = 0;
                    266:        return(cp);
                    267: }
                    268:
                    269: /*
                    270:  * Delete messages.
                    271:  */
                    272: int
                    273: delete(msgvec)
                    274:        int msgvec[];
                    275: {
                    276:        delm(msgvec);
                    277:        return 0;
                    278: }
                    279:
                    280: /*
                    281:  * Delete messages, then type the new dot.
                    282:  */
                    283: int
                    284: deltype(msgvec)
                    285:        int msgvec[];
                    286: {
                    287:        int list[2];
                    288:        int lastdot;
                    289:
                    290:        lastdot = dot - &message[0] + 1;
                    291:        if (delm(msgvec) >= 0) {
                    292:                list[0] = dot - &message[0] + 1;
                    293:                if (list[0] > lastdot) {
                    294:                        touch(dot);
                    295:                        list[1] = NULL;
                    296:                        return(type(list));
                    297:                }
                    298:                printf("At EOF\n");
                    299:        } else
                    300:                printf("No more messages\n");
                    301:        return(0);
                    302: }
                    303:
                    304: /*
                    305:  * Delete the indicated messages.
                    306:  * Set dot to some nice place afterwards.
                    307:  * Internal interface.
                    308:  */
                    309: int
                    310: delm(msgvec)
                    311:        int *msgvec;
                    312: {
                    313:        register struct message *mp;
                    314:        register *ip;
                    315:        int last;
                    316:
                    317:        last = NULL;
                    318:        for (ip = msgvec; *ip != NULL; ip++) {
                    319:                mp = &message[*ip - 1];
                    320:                touch(mp);
                    321:                mp->m_flag |= MDELETED|MTOUCH;
                    322:                mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
                    323:                last = *ip;
                    324:        }
                    325:        if (last != NULL) {
                    326:                dot = &message[last-1];
                    327:                last = first(0, MDELETED);
                    328:                if (last != NULL) {
                    329:                        dot = &message[last-1];
                    330:                        return(0);
                    331:                }
                    332:                else {
                    333:                        dot = &message[0];
                    334:                        return(-1);
                    335:                }
                    336:        }
                    337:
                    338:        /*
                    339:         * Following can't happen -- it keeps lint happy
                    340:         */
                    341:
                    342:        return(-1);
                    343: }
                    344:
                    345: /*
                    346:  * Undelete the indicated messages.
                    347:  */
                    348: int
                    349: undeletecmd(msgvec)
                    350:        int *msgvec;
                    351: {
                    352:        register struct message *mp;
                    353:        register *ip;
                    354:
                    355:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    356:                mp = &message[*ip - 1];
                    357:                touch(mp);
                    358:                dot = mp;
                    359:                mp->m_flag &= ~MDELETED;
                    360:        }
                    361:        return 0;
                    362: }
                    363:
                    364: /*
                    365:  * Interactively dump core on "core"
                    366:  */
                    367: int
                    368: core()
                    369: {
                    370:        int pid;
                    371:        extern union wait wait_status;
                    372:
                    373:        switch (pid = vfork()) {
                    374:        case -1:
                    375:                perror("fork");
                    376:                return(1);
                    377:        case 0:
                    378:                abort();
                    379:                _exit(1);
                    380:        }
                    381:        printf("Okie dokie");
                    382:        fflush(stdout);
                    383:        wait_child(pid);
                    384:        if (wait_status.w_coredump)
                    385:                printf(" -- Core dumped.\n");
                    386:        else
                    387:                printf(" -- Can't dump core.\n");
                    388:        return 0;
                    389: }
                    390:
                    391: /*
                    392:  * Clobber as many bytes of stack as the user requests.
                    393:  */
                    394: int
                    395: clobber(argv)
                    396:        char **argv;
                    397: {
                    398:        register int times;
                    399:
                    400:        if (argv[0] == 0)
                    401:                times = 1;
                    402:        else
                    403:                times = (atoi(argv[0]) + 511) / 512;
                    404:        clob1(times);
                    405:        return 0;
                    406: }
                    407:
                    408: /*
                    409:  * Clobber the stack.
                    410:  */
                    411: void
                    412: clob1(n)
                    413:        int n;
                    414: {
                    415:        char buf[512];
                    416:        register char *cp;
                    417:
                    418:        if (n <= 0)
                    419:                return;
                    420:        for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
                    421:                ;
                    422:        clob1(n - 1);
                    423: }
                    424:
                    425: /*
                    426:  * Add the given header fields to the retained list.
                    427:  * If no arguments, print the current list of retained fields.
                    428:  */
                    429: int
                    430: retfield(list)
                    431:        char *list[];
                    432: {
                    433:
                    434:        return ignore1(list, ignore + 1, "retained");
                    435: }
                    436:
                    437: /*
                    438:  * Add the given header fields to the ignored list.
                    439:  * If no arguments, print the current list of ignored fields.
                    440:  */
                    441: int
                    442: igfield(list)
                    443:        char *list[];
                    444: {
                    445:
                    446:        return ignore1(list, ignore, "ignored");
                    447: }
                    448:
                    449: int
                    450: saveretfield(list)
                    451:        char *list[];
                    452: {
                    453:
                    454:        return ignore1(list, saveignore + 1, "retained");
                    455: }
                    456:
                    457: int
                    458: saveigfield(list)
                    459:        char *list[];
                    460: {
                    461:
                    462:        return ignore1(list, saveignore, "ignored");
                    463: }
                    464:
                    465: int
                    466: ignore1(list, tab, which)
                    467:        char *list[];
                    468:        struct ignoretab *tab;
                    469:        char *which;
                    470: {
                    471:        char field[BUFSIZ];
                    472:        register int h;
                    473:        register struct ignore *igp;
                    474:        char **ap;
                    475:
                    476:        if (*list == NOSTR)
                    477:                return igshow(tab, which);
                    478:        for (ap = list; *ap != 0; ap++) {
                    479:                istrcpy(field, *ap);
                    480:                if (member(field, tab))
                    481:                        continue;
                    482:                h = hash(field);
                    483:                igp = (struct ignore *) calloc(1, sizeof (struct ignore));
                    484:                igp->i_field = calloc((unsigned) strlen(field) + 1,
                    485:                        sizeof (char));
                    486:                strcpy(igp->i_field, field);
                    487:                igp->i_link = tab->i_head[h];
                    488:                tab->i_head[h] = igp;
                    489:                tab->i_count++;
                    490:        }
                    491:        return 0;
                    492: }
                    493:
                    494: /*
                    495:  * Print out all currently retained fields.
                    496:  */
                    497: int
                    498: igshow(tab, which)
                    499:        struct ignoretab *tab;
                    500:        char *which;
                    501: {
                    502:        register int h;
                    503:        struct ignore *igp;
                    504:        char **ap, **ring;
                    505:        int igcomp();
                    506:
                    507:        if (tab->i_count == 0) {
                    508:                printf("No fields currently being %s.\n", which);
                    509:                return 0;
                    510:        }
                    511:        ring = (char **) salloc((tab->i_count + 1) * sizeof (char *));
                    512:        ap = ring;
                    513:        for (h = 0; h < HSHSIZE; h++)
                    514:                for (igp = tab->i_head[h]; igp != 0; igp = igp->i_link)
                    515:                        *ap++ = igp->i_field;
                    516:        *ap = 0;
                    517:        qsort(ring, tab->i_count, sizeof (char *), igcomp);
                    518:        for (ap = ring; *ap != 0; ap++)
                    519:                printf("%s\n", *ap);
                    520:        return 0;
                    521: }
                    522:
                    523: /*
                    524:  * Compare two names for sorting ignored field list.
                    525:  */
                    526: int
                    527: igcomp(l, r)
                    528:        const void *l, *r;
                    529: {
                    530:        return (strcmp(*(char **)l, *(char **)r));
                    531: }