Annotation of 43BSDReno/usr.bin/mail/cmd2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.