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

Annotation of src/usr.bin/mail/cmd1.c, Revision 1.17

1.17    ! millert     1: /*     $OpenBSD: cmd1.c,v 1.16 2000/06/30 16:00:18 millert Exp $       */
1.6       millert     2: /*     $NetBSD: cmd1.c,v 1.9 1997/07/09 05:29:48 mikel Exp $   */
1.2       niklas      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.3       deraadt    38: #if 0
1.6       millert    39: static char sccsid[] = "@(#)cmd1.c     8.2 (Berkeley) 4/20/95";
1.3       deraadt    40: #else
1.17    ! millert    41: static char rcsid[] = "$OpenBSD: cmd1.c,v 1.16 2000/06/30 16:00:18 millert Exp $";
1.3       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:  * User commands.
                     52:  */
                     53:
                     54: /*
                     55:  * Print the current active headings.
                     56:  * Don't change dot if invoker didn't give an argument.
                     57:  */
                     58:
                     59: static int screen;
                     60:
                     61: int
1.3       deraadt    62: headers(v)
                     63:        void *v;
1.1       deraadt    64: {
1.3       deraadt    65:        int *msgvec = v;
1.12      millert    66:        int n, mesg, flag, size;
                     67:        struct message *mp;
1.1       deraadt    68:
                     69:        size = screensize();
                     70:        n = msgvec[0];
                     71:        if (n != 0)
                     72:                screen = (n-1)/size;
                     73:        if (screen < 0)
                     74:                screen = 0;
                     75:        mp = &message[screen * size];
                     76:        if (mp >= &message[msgCount])
                     77:                mp = &message[msgCount - size];
                     78:        if (mp < &message[0])
                     79:                mp = &message[0];
                     80:        flag = 0;
                     81:        mesg = mp - &message[0];
                     82:        if (dot != &message[n-1])
                     83:                dot = mp;
                     84:        for (; mp < &message[msgCount]; mp++) {
                     85:                mesg++;
                     86:                if (mp->m_flag & MDELETED)
                     87:                        continue;
                     88:                if (flag++ >= size)
                     89:                        break;
                     90:                printhead(mesg);
                     91:        }
                     92:        if (flag == 0) {
1.6       millert    93:                puts("No more mail.");
1.1       deraadt    94:                return(1);
                     95:        }
                     96:        return(0);
                     97: }
                     98:
                     99: /*
                    100:  * Scroll to the next/previous screen
                    101:  */
                    102: int
1.3       deraadt   103: scroll(v)
                    104:        void *v;
1.1       deraadt   105: {
1.3       deraadt   106:        char *arg = v;
1.13      millert   107:        int size, maxscreen;
1.1       deraadt   108:        int cur[1];
                    109:
                    110:        cur[0] = 0;
                    111:        size = screensize();
1.13      millert   112:        maxscreen = (msgCount - 1) / size;
1.1       deraadt   113:        switch (*arg) {
                    114:        case 0:
                    115:        case '+':
1.13      millert   116:                if (screen >= maxscreen) {
1.6       millert   117:                        puts("On last screenful of messages");
1.1       deraadt   118:                        return(0);
                    119:                }
1.13      millert   120:                screen++;
1.1       deraadt   121:                break;
                    122:
                    123:        case '-':
1.13      millert   124:                if (screen <= 0) {
1.6       millert   125:                        puts("On first screenful of messages");
1.1       deraadt   126:                        return(0);
                    127:                }
1.13      millert   128:                screen--;
1.1       deraadt   129:                break;
                    130:
                    131:        default:
                    132:                printf("Unrecognized scrolling command \"%s\"\n", arg);
                    133:                return(1);
                    134:        }
                    135:        return(headers(cur));
                    136: }
                    137:
                    138: /*
                    139:  * Compute screen size.
                    140:  */
                    141: int
                    142: screensize()
                    143: {
                    144:        int s;
                    145:        char *cp;
                    146:
1.8       millert   147:        if ((cp = value("screen")) != NULL && (s = atoi(cp)) > 0)
1.6       millert   148:                return(s);
                    149:        return(screenheight - 4);
1.1       deraadt   150: }
                    151:
                    152: /*
                    153:  * Print out the headlines for each message
                    154:  * in the passed message list.
                    155:  */
                    156: int
1.3       deraadt   157: from(v)
                    158:        void *v;
1.1       deraadt   159: {
1.3       deraadt   160:        int *msgvec = v;
1.12      millert   161:        int *ip;
1.1       deraadt   162:
                    163:        for (ip = msgvec; *ip != NULL; ip++)
                    164:                printhead(*ip);
                    165:        if (--ip >= msgvec)
                    166:                dot = &message[*ip - 1];
                    167:        return(0);
                    168: }
                    169:
                    170: /*
                    171:  * Print out the header of a specific message.
                    172:  * This is a slight improvement to the standard one.
                    173:  */
                    174: void
                    175: printhead(mesg)
                    176:        int mesg;
                    177: {
                    178:        struct message *mp;
                    179:        char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
                    180:        char pbuf[BUFSIZ];
                    181:        struct headline hl;
                    182:        int subjlen;
                    183:        char *name;
1.17    ! millert   184:        char *to, *from;
        !           185:        struct name *np;
        !           186:        char **ap;
1.1       deraadt   187:
                    188:        mp = &message[mesg-1];
1.7       millert   189:        (void)readline(setinput(mp), headline, LINESIZE);
1.8       millert   190:        if ((subjline = hfield("subject", mp)) == NULL)
1.1       deraadt   191:                subjline = hfield("subj", mp);
                    192:        /*
                    193:         * Bletch!
                    194:         */
                    195:        curind = dot == mp ? '>' : ' ';
                    196:        dispc = ' ';
                    197:        if (mp->m_flag & MSAVED)
                    198:                dispc = '*';
                    199:        if (mp->m_flag & MPRESERVE)
                    200:                dispc = 'P';
                    201:        if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
                    202:                dispc = 'N';
                    203:        if ((mp->m_flag & (MREAD|MNEW)) == 0)
                    204:                dispc = 'U';
                    205:        if (mp->m_flag & MBOX)
                    206:                dispc = 'M';
                    207:        parse(headline, &hl, pbuf);
1.17    ! millert   208:        (void)snprintf(wcount, sizeof(wcount), "%4d/%-5d", mp->m_lines,
1.10      millert   209:            mp->m_size);
1.17    ! millert   210:        subjlen = screenwidth - 44 - strlen(wcount);
        !           211:        from = nameof(mp, 0);
        !           212:        to = skin(hfield("to", mp));
        !           213:        np = extract(from, GTO);
        !           214:        np = delname(np, myname);
        !           215:        if (altnames)
        !           216:                for (ap = altnames; *ap; ap++)
        !           217:                        np = delname(np, *ap);
        !           218:        if (np)
        !           219:                /* not from me */
        !           220:                name = value("show-rcpt") != NULL && to ? to : from;
1.1       deraadt   221:        else
1.17    ! millert   222:                /* from me - show TO */
        !           223:                name = value("showto") != NULL && to ? to : from;
        !           224:        if (subjline == NULL || subjlen < 0) { /* pretty pathetic */
        !           225:                subjline="";
        !           226:                subjlen=0;
        !           227:        }
        !           228:        if (name == to)
        !           229:                printf("%c%c%3d TO %-14.14s  %16.16s %s %.*s\n",
        !           230:                        curind, dispc, mesg, name, hl.l_date, wcount,
        !           231:                        subjlen, subjline);
        !           232:        else
        !           233:                printf("%c%c%3d %-17.17s  %16.16s %s %.*s\n",
1.1       deraadt   234:                        curind, dispc, mesg, name, hl.l_date, wcount,
                    235:                        subjlen, subjline);
                    236: }
                    237:
                    238: /*
                    239:  * Print out the value of dot.
                    240:  */
                    241: int
1.3       deraadt   242: pdot(v)
                    243:        void *v;
1.1       deraadt   244: {
1.12      millert   245:        printf("%d\n", (int)(dot - &message[0] + 1));
1.1       deraadt   246:        return(0);
                    247: }
                    248:
                    249: /*
                    250:  * Print out all the possible commands.
                    251:  */
                    252: int
1.3       deraadt   253: pcmdlist(v)
                    254:        void *v;
1.1       deraadt   255: {
1.2       niklas    256:        extern const struct cmd cmdtab[];
1.12      millert   257:        const struct cmd *cp;
                    258:        int cc;
1.1       deraadt   259:
1.6       millert   260:        puts("Commands are:");
1.1       deraadt   261:        for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
                    262:                cc += strlen(cp->c_name) + 2;
                    263:                if (cc > 72) {
1.6       millert   264:                        putchar('\n');
1.1       deraadt   265:                        cc = strlen(cp->c_name) + 2;
                    266:                }
1.8       millert   267:                if ((cp+1)->c_name != NULL)
1.1       deraadt   268:                        printf("%s, ", cp->c_name);
                    269:                else
1.6       millert   270:                        puts(cp->c_name);
1.1       deraadt   271:        }
                    272:        return(0);
                    273: }
                    274:
                    275: /*
1.17    ! millert   276:  * Pipe message to command
        !           277:  */
        !           278: int
        !           279: pipeit(ml, sl)
        !           280:        void *ml, *sl;
        !           281: {
        !           282:        int  *msgvec = ml;
        !           283:        char *cmd    = sl;
        !           284:
        !           285:        return(type1(msgvec, cmd, 0, 0));
        !           286: }
        !           287:
        !           288: /*
1.1       deraadt   289:  * Paginate messages, honor ignored fields.
                    290:  */
                    291: int
1.3       deraadt   292: more(v)
                    293:        void *v;
1.1       deraadt   294: {
1.3       deraadt   295:        int *msgvec = v;
1.17    ! millert   296:        return(type1(msgvec, NULL, 1, 1));
1.1       deraadt   297: }
                    298:
                    299: /*
                    300:  * Paginate messages, even printing ignored fields.
                    301:  */
                    302: int
1.3       deraadt   303: More(v)
                    304:        void *v;
1.1       deraadt   305: {
1.3       deraadt   306:        int *msgvec = v;
1.1       deraadt   307:
1.17    ! millert   308:        return(type1(msgvec, NULL, 0, 1));
1.1       deraadt   309: }
                    310:
                    311: /*
                    312:  * Type out messages, honor ignored fields.
                    313:  */
                    314: int
1.3       deraadt   315: type(v)
                    316:        void *v;
1.1       deraadt   317: {
1.3       deraadt   318:        int *msgvec = v;
1.1       deraadt   319:
1.17    ! millert   320:        return(type1(msgvec, NULL, 1, 0));
1.1       deraadt   321: }
                    322:
                    323: /*
                    324:  * Type out messages, even printing ignored fields.
                    325:  */
                    326: int
1.3       deraadt   327: Type(v)
                    328:        void *v;
1.1       deraadt   329: {
1.3       deraadt   330:        int *msgvec = v;
1.1       deraadt   331:
1.17    ! millert   332:        return(type1(msgvec, NULL, 0, 0));
1.1       deraadt   333: }
                    334:
                    335: /*
                    336:  * Type out the messages requested.
                    337:  */
1.8       millert   338: sigjmp_buf     pipestop;
1.1       deraadt   339: int
1.17    ! millert   340: type1(msgvec, cmd, doign, page)
1.1       deraadt   341:        int *msgvec;
1.17    ! millert   342:        char *cmd;
1.1       deraadt   343:        int doign, page;
                    344: {
1.12      millert   345:        int nlines, *ip;
1.3       deraadt   346:        struct message *mp;
                    347:        char *cp;
1.1       deraadt   348:        FILE *obuf;
1.17    ! millert   349:
1.3       deraadt   350: #if __GNUC__
1.8       millert   351:        /* Avoid siglongjmp clobbering */
1.7       millert   352:        (void)&cp;
                    353:        (void)&obuf;
1.3       deraadt   354: #endif
1.1       deraadt   355:
                    356:        obuf = stdout;
1.8       millert   357:        if (sigsetjmp(pipestop, 1))
1.1       deraadt   358:                goto close_pipe;
1.17    ! millert   359:
        !           360:        /*
        !           361:         * start a pipe if needed.
        !           362:         */
        !           363:        if (cmd) {
        !           364:                obuf = Popen(cmd, "w");
        !           365:                if (obuf == NULL) {
        !           366:                        warn("%s", cp);
        !           367:                        obuf = stdout;
        !           368:                } else {
        !           369:                        (void)signal(SIGPIPE, brokpipe);
        !           370:                }
        !           371:        } else if (value("interactive") != NULL &&
        !           372:                 (page || (cp = value("crt")) != NULL)) {
1.1       deraadt   373:                nlines = 0;
                    374:                if (!page) {
                    375:                        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
                    376:                                nlines += message[*ip - 1].m_lines;
                    377:                }
                    378:                if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
1.17    ! millert   379:                        obuf = Popen(value("PAGER"), "w");
1.1       deraadt   380:                        if (obuf == NULL) {
1.16      millert   381:                                warn("%s", cp);
1.1       deraadt   382:                                obuf = stdout;
                    383:                        } else
1.11      millert   384:                                (void)signal(SIGPIPE, brokpipe);
1.1       deraadt   385:                }
                    386:        }
1.17    ! millert   387:
        !           388:        /*
        !           389:         * send messages to the output.
        !           390:         */
1.1       deraadt   391:        for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
                    392:                mp = &message[*ip - 1];
                    393:                touch(mp);
                    394:                dot = mp;
1.17    ! millert   395:                if (cmd == NULL && value("quiet") == NULL)
1.1       deraadt   396:                        fprintf(obuf, "Message %d:\n", *ip);
1.15      millert   397:                (void)sendmessage(mp, obuf, doign ? ignore : 0, NULL);
1.1       deraadt   398:        }
1.17    ! millert   399:
1.1       deraadt   400: close_pipe:
                    401:        if (obuf != stdout) {
                    402:                /*
                    403:                 * Ignore SIGPIPE so it can't cause a duplicate close.
                    404:                 */
1.11      millert   405:                (void)signal(SIGPIPE, SIG_IGN);
1.6       millert   406:                (void)Pclose(obuf);
1.11      millert   407:                (void)signal(SIGPIPE, SIG_DFL);
1.1       deraadt   408:        }
                    409:        return(0);
                    410: }
                    411:
                    412: /*
                    413:  * Respond to a broken pipe signal --
                    414:  * probably caused by quitting more.
                    415:  */
                    416: void
                    417: brokpipe(signo)
                    418:        int signo;
                    419: {
1.8       millert   420:        siglongjmp(pipestop, 1);
1.1       deraadt   421: }
                    422:
                    423: /*
                    424:  * Print the top so many lines of each desired message.
                    425:  * The number of lines is taken from the variable "toplines"
                    426:  * and defaults to 5.
                    427:  */
                    428: int
1.3       deraadt   429: top(v)
                    430:        void *v;
1.1       deraadt   431: {
1.3       deraadt   432:        int *msgvec = v;
1.12      millert   433:        int *ip;
                    434:        struct message *mp;
1.1       deraadt   435:        int c, topl, lines, lineb;
                    436:        char *valtop, linebuf[LINESIZE];
                    437:        FILE *ibuf;
                    438:
                    439:        topl = 5;
                    440:        valtop = value("toplines");
1.8       millert   441:        if (valtop != NULL) {
1.1       deraadt   442:                topl = atoi(valtop);
                    443:                if (topl < 0 || topl > 10000)
                    444:                        topl = 5;
                    445:        }
                    446:        lineb = 1;
                    447:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    448:                mp = &message[*ip - 1];
                    449:                touch(mp);
                    450:                dot = mp;
1.8       millert   451:                if (value("quiet") == NULL)
1.1       deraadt   452:                        printf("Message %d:\n", *ip);
                    453:                ibuf = setinput(mp);
                    454:                c = mp->m_lines;
                    455:                if (!lineb)
1.6       millert   456:                        putchar('\n');
1.1       deraadt   457:                for (lines = 0; lines < c && lines <= topl; lines++) {
1.9       millert   458:                        if (readline(ibuf, linebuf, sizeof(linebuf)) < 0)
1.1       deraadt   459:                                break;
                    460:                        puts(linebuf);
                    461:                        lineb = blankline(linebuf);
                    462:                }
                    463:        }
                    464:        return(0);
                    465: }
                    466:
                    467: /*
                    468:  * Touch all the given messages so that they will
                    469:  * get mboxed.
                    470:  */
                    471: int
1.3       deraadt   472: stouch(v)
                    473:        void *v;
1.1       deraadt   474: {
1.3       deraadt   475:        int *msgvec = v;
1.12      millert   476:        int *ip;
1.1       deraadt   477:
                    478:        for (ip = msgvec; *ip != 0; ip++) {
                    479:                dot = &message[*ip-1];
                    480:                dot->m_flag |= MTOUCH;
                    481:                dot->m_flag &= ~MPRESERVE;
                    482:        }
                    483:        return(0);
                    484: }
                    485:
                    486: /*
                    487:  * Make sure all passed messages get mboxed.
                    488:  */
                    489: int
1.3       deraadt   490: mboxit(v)
                    491:        void *v;
1.1       deraadt   492: {
1.3       deraadt   493:        int *msgvec = v;
1.12      millert   494:        int *ip;
1.1       deraadt   495:
                    496:        for (ip = msgvec; *ip != 0; ip++) {
                    497:                dot = &message[*ip-1];
                    498:                dot->m_flag |= MTOUCH|MBOX;
                    499:                dot->m_flag &= ~MPRESERVE;
                    500:        }
                    501:        return(0);
                    502: }
                    503:
                    504: /*
                    505:  * List the folders the user currently has.
                    506:  */
                    507: int
1.3       deraadt   508: folders(v)
                    509:        void *v;
1.1       deraadt   510: {
1.17    ! millert   511:        char *files = (char *)v;
1.5       deraadt   512:        char dirname[PATHSIZE];
1.17    ! millert   513:        char cmd[BUFSIZ];
1.1       deraadt   514:
1.6       millert   515:        if (getfold(dirname, sizeof(dirname)) < 0) {
1.17    ! millert   516:                strcpy(dirname, "$HOME");
1.1       deraadt   517:        }
1.17    ! millert   518:
        !           519:        snprintf(cmd, sizeof(cmd), "cd %s; %s %s", dirname, value("LISTER"),
        !           520:                files && *files ? files : "");
        !           521:
        !           522:        (void)run_command(value("SHELL"), 0, -1, -1, "-c", cmd, NULL);
1.6       millert   523:        return(0);
                    524: }
                    525:
                    526: /*
                    527:  * Update the mail file with any new messages that have
                    528:  * come in since we started reading mail.
                    529:  */
                    530: int
                    531: inc(v)
                    532:        void *v;
                    533: {
                    534:        int nmsg, mdot;
                    535:
                    536:        nmsg = incfile();
                    537:
                    538:        if (nmsg == 0) {
                    539:                puts("No new mail.");
                    540:        } else if (nmsg > 0) {
                    541:                mdot = newfileinfo(msgCount - nmsg);
                    542:                dot = &message[mdot - 1];
                    543:        } else {
                    544:                puts("\"inc\" command failed...");
                    545:        }
                    546:
                    547:        return(0);
1.1       deraadt   548: }