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

1.2     ! niklas      1: /*     $OpenBSD$       */
        !             2:
1.1       deraadt     3: /*-
                      4:  * Copyright (c) 1980, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #ifndef lint
                     37: static char sccsid[] = "from: @(#)cmd1.c       8.1 (Berkeley) 6/6/93";
1.2     ! niklas     38: static char rcsid[] = "$OpenBSD$";
1.1       deraadt    39: #endif /* not lint */
                     40:
                     41: #include "rcv.h"
                     42: #include "extern.h"
                     43:
                     44: /*
                     45:  * Mail -- a mail program
                     46:  *
                     47:  * User commands.
                     48:  */
                     49:
                     50: /*
                     51:  * Print the current active headings.
                     52:  * Don't change dot if invoker didn't give an argument.
                     53:  */
                     54:
                     55: static int screen;
                     56:
                     57: int
                     58: headers(msgvec)
                     59:        int *msgvec;
                     60: {
                     61:        register int n, mesg, flag;
                     62:        register struct message *mp;
                     63:        int size;
                     64:
                     65:        size = screensize();
                     66:        n = msgvec[0];
                     67:        if (n != 0)
                     68:                screen = (n-1)/size;
                     69:        if (screen < 0)
                     70:                screen = 0;
                     71:        mp = &message[screen * size];
                     72:        if (mp >= &message[msgCount])
                     73:                mp = &message[msgCount - size];
                     74:        if (mp < &message[0])
                     75:                mp = &message[0];
                     76:        flag = 0;
                     77:        mesg = mp - &message[0];
                     78:        if (dot != &message[n-1])
                     79:                dot = mp;
                     80:        for (; mp < &message[msgCount]; mp++) {
                     81:                mesg++;
                     82:                if (mp->m_flag & MDELETED)
                     83:                        continue;
                     84:                if (flag++ >= size)
                     85:                        break;
                     86:                printhead(mesg);
                     87:        }
                     88:        if (flag == 0) {
                     89:                printf("No more mail.\n");
                     90:                return(1);
                     91:        }
                     92:        return(0);
                     93: }
                     94:
                     95: /*
                     96:  * Scroll to the next/previous screen
                     97:  */
                     98: int
                     99: scroll(arg)
                    100:        char arg[];
                    101: {
                    102:        register int s, size;
                    103:        int cur[1];
                    104:
                    105:        cur[0] = 0;
                    106:        size = screensize();
                    107:        s = screen;
                    108:        switch (*arg) {
                    109:        case 0:
                    110:        case '+':
                    111:                s++;
                    112:                if (s * size > msgCount) {
                    113:                        printf("On last screenful of messages\n");
                    114:                        return(0);
                    115:                }
                    116:                screen = s;
                    117:                break;
                    118:
                    119:        case '-':
                    120:                if (--s < 0) {
                    121:                        printf("On first screenful of messages\n");
                    122:                        return(0);
                    123:                }
                    124:                screen = s;
                    125:                break;
                    126:
                    127:        default:
                    128:                printf("Unrecognized scrolling command \"%s\"\n", arg);
                    129:                return(1);
                    130:        }
                    131:        return(headers(cur));
                    132: }
                    133:
                    134: /*
                    135:  * Compute screen size.
                    136:  */
                    137: int
                    138: screensize()
                    139: {
                    140:        int s;
                    141:        char *cp;
                    142:
                    143:        if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
                    144:                return s;
                    145:        return screenheight - 4;
                    146: }
                    147:
                    148: /*
                    149:  * Print out the headlines for each message
                    150:  * in the passed message list.
                    151:  */
                    152: int
                    153: from(msgvec)
                    154:        int *msgvec;
                    155: {
                    156:        register int *ip;
                    157:
                    158:        for (ip = msgvec; *ip != NULL; ip++)
                    159:                printhead(*ip);
                    160:        if (--ip >= msgvec)
                    161:                dot = &message[*ip - 1];
                    162:        return(0);
                    163: }
                    164:
                    165: /*
                    166:  * Print out the header of a specific message.
                    167:  * This is a slight improvement to the standard one.
                    168:  */
                    169: void
                    170: printhead(mesg)
                    171:        int mesg;
                    172: {
                    173:        struct message *mp;
                    174:        char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
                    175:        char pbuf[BUFSIZ];
                    176:        struct headline hl;
                    177:        int subjlen;
                    178:        char *name;
                    179:
                    180:        mp = &message[mesg-1];
                    181:        (void) readline(setinput(mp), headline, LINESIZE);
                    182:        if ((subjline = hfield("subject", mp)) == NOSTR)
                    183:                subjline = hfield("subj", mp);
                    184:        /*
                    185:         * Bletch!
                    186:         */
                    187:        curind = dot == mp ? '>' : ' ';
                    188:        dispc = ' ';
                    189:        if (mp->m_flag & MSAVED)
                    190:                dispc = '*';
                    191:        if (mp->m_flag & MPRESERVE)
                    192:                dispc = 'P';
                    193:        if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
                    194:                dispc = 'N';
                    195:        if ((mp->m_flag & (MREAD|MNEW)) == 0)
                    196:                dispc = 'U';
                    197:        if (mp->m_flag & MBOX)
                    198:                dispc = 'M';
                    199:        parse(headline, &hl, pbuf);
                    200:        sprintf(wcount, "%3d/%-5ld", mp->m_lines, mp->m_size);
                    201:        subjlen = screenwidth - 50 - strlen(wcount);
                    202:        name = value("show-rcpt") != NOSTR ?
                    203:                skin(hfield("to", mp)) : nameof(mp, 0);
                    204:        if (subjline == NOSTR || subjlen < 0)           /* pretty pathetic */
                    205:                printf("%c%c%3d %-20.20s  %16.16s %s\n",
                    206:                        curind, dispc, mesg, name, hl.l_date, wcount);
                    207:        else
                    208:                printf("%c%c%3d %-20.20s  %16.16s %s \"%.*s\"\n",
                    209:                        curind, dispc, mesg, name, hl.l_date, wcount,
                    210:                        subjlen, subjline);
                    211: }
                    212:
                    213: /*
                    214:  * Print out the value of dot.
                    215:  */
                    216: int
                    217: pdot()
                    218: {
                    219:        printf("%d\n", dot - &message[0] + 1);
                    220:        return(0);
                    221: }
                    222:
                    223: /*
                    224:  * Print out all the possible commands.
                    225:  */
                    226: int
                    227: pcmdlist()
                    228: {
1.2     ! niklas    229:        extern const struct cmd cmdtab[];
        !           230:        register const struct cmd *cp;
1.1       deraadt   231:        register int cc;
                    232:
                    233:        printf("Commands are:\n");
                    234:        for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
                    235:                cc += strlen(cp->c_name) + 2;
                    236:                if (cc > 72) {
                    237:                        printf("\n");
                    238:                        cc = strlen(cp->c_name) + 2;
                    239:                }
                    240:                if ((cp+1)->c_name != NOSTR)
                    241:                        printf("%s, ", cp->c_name);
                    242:                else
                    243:                        printf("%s\n", cp->c_name);
                    244:        }
                    245:        return(0);
                    246: }
                    247:
                    248: /*
                    249:  * Paginate messages, honor ignored fields.
                    250:  */
                    251: int
                    252: more(msgvec)
                    253:        int *msgvec;
                    254: {
                    255:        return (type1(msgvec, 1, 1));
                    256: }
                    257:
                    258: /*
                    259:  * Paginate messages, even printing ignored fields.
                    260:  */
                    261: int
                    262: More(msgvec)
                    263:        int *msgvec;
                    264: {
                    265:
                    266:        return (type1(msgvec, 0, 1));
                    267: }
                    268:
                    269: /*
                    270:  * Type out messages, honor ignored fields.
                    271:  */
                    272: int
                    273: type(msgvec)
                    274:        int *msgvec;
                    275: {
                    276:
                    277:        return(type1(msgvec, 1, 0));
                    278: }
                    279:
                    280: /*
                    281:  * Type out messages, even printing ignored fields.
                    282:  */
                    283: int
                    284: Type(msgvec)
                    285:        int *msgvec;
                    286: {
                    287:
                    288:        return(type1(msgvec, 0, 0));
                    289: }
                    290:
                    291: /*
                    292:  * Type out the messages requested.
                    293:  */
                    294: jmp_buf        pipestop;
                    295: int
                    296: type1(msgvec, doign, page)
                    297:        int *msgvec;
                    298:        int doign, page;
                    299: {
                    300:        register *ip;
                    301:        register struct message *mp;
                    302:        register char *cp;
                    303:        int nlines;
                    304:        FILE *obuf;
                    305:
                    306:        obuf = stdout;
                    307:        if (setjmp(pipestop))
                    308:                goto close_pipe;
                    309:        if (value("interactive") != NOSTR &&
                    310:            (page || (cp = value("crt")) != NOSTR)) {
                    311:                nlines = 0;
                    312:                if (!page) {
                    313:                        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
                    314:                                nlines += message[*ip - 1].m_lines;
                    315:                }
                    316:                if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
                    317:                        cp = value("PAGER");
                    318:                        if (cp == NULL || *cp == '\0')
                    319:                                cp = _PATH_MORE;
                    320:                        obuf = Popen(cp, "w");
                    321:                        if (obuf == NULL) {
                    322:                                perror(cp);
                    323:                                obuf = stdout;
                    324:                        } else
                    325:                                signal(SIGPIPE, brokpipe);
                    326:                }
                    327:        }
                    328:        for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
                    329:                mp = &message[*ip - 1];
                    330:                touch(mp);
                    331:                dot = mp;
                    332:                if (value("quiet") == NOSTR)
                    333:                        fprintf(obuf, "Message %d:\n", *ip);
                    334:                (void) send(mp, obuf, doign ? ignore : 0, NOSTR);
                    335:        }
                    336: close_pipe:
                    337:        if (obuf != stdout) {
                    338:                /*
                    339:                 * Ignore SIGPIPE so it can't cause a duplicate close.
                    340:                 */
                    341:                signal(SIGPIPE, SIG_IGN);
                    342:                Pclose(obuf);
                    343:                signal(SIGPIPE, SIG_DFL);
                    344:        }
                    345:        return(0);
                    346: }
                    347:
                    348: /*
                    349:  * Respond to a broken pipe signal --
                    350:  * probably caused by quitting more.
                    351:  */
                    352: void
                    353: brokpipe(signo)
                    354:        int signo;
                    355: {
                    356:        longjmp(pipestop, 1);
                    357: }
                    358:
                    359: /*
                    360:  * Print the top so many lines of each desired message.
                    361:  * The number of lines is taken from the variable "toplines"
                    362:  * and defaults to 5.
                    363:  */
                    364: int
                    365: top(msgvec)
                    366:        int *msgvec;
                    367: {
                    368:        register int *ip;
                    369:        register struct message *mp;
                    370:        int c, topl, lines, lineb;
                    371:        char *valtop, linebuf[LINESIZE];
                    372:        FILE *ibuf;
                    373:
                    374:        topl = 5;
                    375:        valtop = value("toplines");
                    376:        if (valtop != NOSTR) {
                    377:                topl = atoi(valtop);
                    378:                if (topl < 0 || topl > 10000)
                    379:                        topl = 5;
                    380:        }
                    381:        lineb = 1;
                    382:        for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
                    383:                mp = &message[*ip - 1];
                    384:                touch(mp);
                    385:                dot = mp;
                    386:                if (value("quiet") == NOSTR)
                    387:                        printf("Message %d:\n", *ip);
                    388:                ibuf = setinput(mp);
                    389:                c = mp->m_lines;
                    390:                if (!lineb)
                    391:                        printf("\n");
                    392:                for (lines = 0; lines < c && lines <= topl; lines++) {
                    393:                        if (readline(ibuf, linebuf, LINESIZE) < 0)
                    394:                                break;
                    395:                        puts(linebuf);
                    396:                        lineb = blankline(linebuf);
                    397:                }
                    398:        }
                    399:        return(0);
                    400: }
                    401:
                    402: /*
                    403:  * Touch all the given messages so that they will
                    404:  * get mboxed.
                    405:  */
                    406: int
                    407: stouch(msgvec)
                    408:        int msgvec[];
                    409: {
                    410:        register int *ip;
                    411:
                    412:        for (ip = msgvec; *ip != 0; ip++) {
                    413:                dot = &message[*ip-1];
                    414:                dot->m_flag |= MTOUCH;
                    415:                dot->m_flag &= ~MPRESERVE;
                    416:        }
                    417:        return(0);
                    418: }
                    419:
                    420: /*
                    421:  * Make sure all passed messages get mboxed.
                    422:  */
                    423: int
                    424: mboxit(msgvec)
                    425:        int msgvec[];
                    426: {
                    427:        register int *ip;
                    428:
                    429:        for (ip = msgvec; *ip != 0; ip++) {
                    430:                dot = &message[*ip-1];
                    431:                dot->m_flag |= MTOUCH|MBOX;
                    432:                dot->m_flag &= ~MPRESERVE;
                    433:        }
                    434:        return(0);
                    435: }
                    436:
                    437: /*
                    438:  * List the folders the user currently has.
                    439:  */
                    440: int
                    441: folders()
                    442: {
                    443:        char dirname[BUFSIZ];
                    444:        char *cmd;
                    445:
                    446:        if (getfold(dirname) < 0) {
                    447:                printf("No value set for \"folder\"\n");
                    448:                return 1;
                    449:        }
                    450:        if ((cmd = value("LISTER")) == NOSTR)
                    451:                cmd = "ls";
                    452:        (void) run_command(cmd, 0, -1, -1, dirname, NOSTR, NOSTR);
                    453:        return 0;
                    454: }