home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / mail / cmd1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  8.8 KB  |  441 lines

  1. /*-
  2.  * Copyright (c) 1980 The Regents of the University of California.
  3.  * 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[] = "@(#)cmd1.c    5.22 (Berkeley) 4/1/91";
  36. #endif /* not lint */
  37.  
  38. #include "rcv.h"
  39.  
  40. /*
  41.  * Mail -- a mail program
  42.  *
  43.  * User commands.
  44.  */
  45.  
  46. /*
  47.  * Print the current active headings.
  48.  * Don't change dot if invoker didn't give an argument.
  49.  */
  50.  
  51. static int screen;
  52.  
  53. headers(msgvec)
  54.     int *msgvec;
  55. {
  56.     register int n, mesg, flag;
  57.     register struct message *mp;
  58.     int size;
  59.  
  60.     size = screensize();
  61.     n = msgvec[0];
  62.     if (n != 0)
  63.         screen = (n-1)/size;
  64.     if (screen < 0)
  65.         screen = 0;
  66.     mp = &message[screen * size];
  67.     if (mp >= &message[msgCount])
  68.         mp = &message[msgCount - size];
  69.     if (mp < &message[0])
  70.         mp = &message[0];
  71.     flag = 0;
  72.     mesg = mp - &message[0];
  73.     if (dot != &message[n-1])
  74.         dot = mp;
  75.     for (; mp < &message[msgCount]; mp++) {
  76.         mesg++;
  77.         if (mp->m_flag & MDELETED)
  78.             continue;
  79.         if (flag++ >= size)
  80.             break;
  81.         printhead(mesg);
  82.     }
  83.     if (flag == 0) {
  84.         printf("No more mail.\n");
  85.         return(1);
  86.     }
  87.     return(0);
  88. }
  89.  
  90. /*
  91.  * Scroll to the next/previous screen
  92.  */
  93. scroll(arg)
  94.     char arg[];
  95. {
  96.     register int s, size;
  97.     int cur[1];
  98.  
  99.     cur[0] = 0;
  100.     size = screensize();
  101.     s = screen;
  102.     switch (*arg) {
  103.     case 0:
  104.     case '+':
  105.         s++;
  106.         if (s * size > msgCount) {
  107.             printf("On last screenful of messages\n");
  108.             return(0);
  109.         }
  110.         screen = s;
  111.         break;
  112.  
  113.     case '-':
  114.         if (--s < 0) {
  115.             printf("On first screenful of messages\n");
  116.             return(0);
  117.         }
  118.         screen = s;
  119.         break;
  120.  
  121.     default:
  122.         printf("Unrecognized scrolling command \"%s\"\n", arg);
  123.         return(1);
  124.     }
  125.     return(headers(cur));
  126. }
  127.  
  128. /*
  129.  * Compute screen size.
  130.  */
  131. screensize()
  132. {
  133.     int s;
  134.     char *cp;
  135.  
  136.     if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
  137.         return s;
  138.     return screenheight - 4;
  139. }
  140.  
  141. /*
  142.  * Print out the headlines for each message
  143.  * in the passed message list.
  144.  */
  145.  
  146. from(msgvec)
  147.     int *msgvec;
  148. {
  149.     register int *ip;
  150.  
  151.     for (ip = msgvec; *ip != NULL; ip++)
  152.         printhead(*ip);
  153.     if (--ip >= msgvec)
  154.         dot = &message[*ip - 1];
  155.     return(0);
  156. }
  157.  
  158. /*
  159.  * Print out the header of a specific message.
  160.  * This is a slight improvement to the standard one.
  161.  */
  162.  
  163. printhead(mesg)
  164. {
  165.     struct message *mp;
  166.     char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
  167.     char pbuf[BUFSIZ];
  168.     struct headline hl;
  169.     int subjlen;
  170.     char *name;
  171.  
  172.     mp = &message[mesg-1];
  173.     (void) readline(setinput(mp), headline, LINESIZE);
  174.     if ((subjline = hfield("subject", mp)) == NOSTR)
  175.         subjline = hfield("subj", mp);
  176.     /*
  177.      * Bletch!
  178.      */
  179.     curind = dot == mp ? '>' : ' ';
  180.     dispc = ' ';
  181.     if (mp->m_flag & MSAVED)
  182.         dispc = '*';
  183.     if (mp->m_flag & MPRESERVE)
  184.         dispc = 'P';
  185.     if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
  186.         dispc = 'N';
  187.     if ((mp->m_flag & (MREAD|MNEW)) == 0)
  188.         dispc = 'U';
  189.     if (mp->m_flag & MBOX)
  190.         dispc = 'M';
  191.     parse(headline, &hl, pbuf);
  192.     sprintf(wcount, "%3d/%-5ld", mp->m_lines, mp->m_size);
  193.     subjlen = screenwidth - 50 - strlen(wcount);
  194.     name = value("show-rcpt") != NOSTR ?
  195.         skin(hfield("to", mp)) : nameof(mp, 0);
  196.     if (subjline == NOSTR || subjlen < 0)        /* pretty pathetic */
  197.         printf("%c%c%3d %-20.20s  %16.16s %s\n",
  198.             curind, dispc, mesg, name, hl.l_date, wcount);
  199.     else
  200.         printf("%c%c%3d %-20.20s  %16.16s %s \"%.*s\"\n",
  201.             curind, dispc, mesg, name, hl.l_date, wcount,
  202.             subjlen, subjline);
  203. }
  204.  
  205. /*
  206.  * Print out the value of dot.
  207.  */
  208.  
  209. pdot()
  210. {
  211.     printf("%d\n", dot - &message[0] + 1);
  212.     return(0);
  213. }
  214.  
  215. /*
  216.  * Print out all the possible commands.
  217.  */
  218.  
  219. pcmdlist()
  220. {
  221.     register struct cmd *cp;
  222.     register int cc;
  223.     extern struct cmd cmdtab[];
  224.  
  225.     printf("Commands are:\n");
  226.     for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
  227.         cc += strlen(cp->c_name) + 2;
  228.         if (cc > 72) {
  229.             printf("\n");
  230.             cc = strlen(cp->c_name) + 2;
  231.         }
  232.         if ((cp+1)->c_name != NOSTR)
  233.             printf("%s, ", cp->c_name);
  234.         else
  235.             printf("%s\n", cp->c_name);
  236.     }
  237.     return(0);
  238. }
  239.  
  240. /*
  241.  * Paginate messages, honor ignored fields.
  242.  */
  243. more(msgvec)
  244.     int *msgvec;
  245. {
  246.     return (type1(msgvec, 1, 1));
  247. }
  248.  
  249. /*
  250.  * Paginate messages, even printing ignored fields.
  251.  */
  252. More(msgvec)
  253.     int *msgvec;
  254. {
  255.  
  256.     return (type1(msgvec, 0, 1));
  257. }
  258.  
  259. /*
  260.  * Type out messages, honor ignored fields.
  261.  */
  262. type(msgvec)
  263.     int *msgvec;
  264. {
  265.  
  266.     return(type1(msgvec, 1, 0));
  267. }
  268.  
  269. /*
  270.  * Type out messages, even printing ignored fields.
  271.  */
  272. Type(msgvec)
  273.     int *msgvec;
  274. {
  275.  
  276.     return(type1(msgvec, 0, 0));
  277. }
  278.  
  279. /*
  280.  * Type out the messages requested.
  281.  */
  282. jmp_buf    pipestop;
  283.  
  284. type1(msgvec, doign, page)
  285.     int *msgvec;
  286. {
  287.     register *ip;
  288.     register struct message *mp;
  289.     register char *cp;
  290.     int nlines;
  291.     FILE *obuf;
  292.     void brokpipe();
  293.  
  294.     obuf = stdout;
  295.     if (setjmp(pipestop))
  296.         goto close_pipe;
  297.     if (value("interactive") != NOSTR &&
  298.         (page || (cp = value("crt")) != NOSTR)) {
  299.         nlines = 0;
  300.         if (!page) {
  301.             for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
  302.                 nlines += message[*ip - 1].m_lines;
  303.         }
  304.         if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
  305.             cp = value("PAGER");
  306.             if (cp == NULL || *cp == '\0')
  307.                 cp = _PATH_MORE;
  308.             obuf = Popen(cp, "w");
  309.             if (obuf == NULL) {
  310.                 perror(cp);
  311.                 obuf = stdout;
  312.             } else
  313.                 signal(SIGPIPE, brokpipe);
  314.         }
  315.     }
  316.     for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
  317.         mp = &message[*ip - 1];
  318.         touch(mp);
  319.         dot = mp;
  320.         if (value("quiet") == NOSTR)
  321.             fprintf(obuf, "Message %d:\n", *ip);
  322.         (void) send(mp, obuf, doign ? ignore : 0, NOSTR);
  323.     }
  324. close_pipe:
  325.     if (obuf != stdout) {
  326.         /*
  327.          * Ignore SIGPIPE so it can't cause a duplicate close.
  328.          */
  329.         signal(SIGPIPE, SIG_IGN);
  330.         Pclose(obuf);
  331.         signal(SIGPIPE, SIG_DFL);
  332.     }
  333.     return(0);
  334. }
  335.  
  336. /*
  337.  * Respond to a broken pipe signal --
  338.  * probably caused by quitting more.
  339.  */
  340.  
  341. void
  342. brokpipe()
  343. {
  344.     longjmp(pipestop, 1);
  345. }
  346.  
  347. /*
  348.  * Print the top so many lines of each desired message.
  349.  * The number of lines is taken from the variable "toplines"
  350.  * and defaults to 5.
  351.  */
  352.  
  353. top(msgvec)
  354.     int *msgvec;
  355. {
  356.     register int *ip;
  357.     register struct message *mp;
  358.     int c, topl, lines, lineb;
  359.     char *valtop, linebuf[LINESIZE];
  360.     FILE *ibuf;
  361.  
  362.     topl = 5;
  363.     valtop = value("toplines");
  364.     if (valtop != NOSTR) {
  365.         topl = atoi(valtop);
  366.         if (topl < 0 || topl > 10000)
  367.             topl = 5;
  368.     }
  369.     lineb = 1;
  370.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  371.         mp = &message[*ip - 1];
  372.         touch(mp);
  373.         dot = mp;
  374.         if (value("quiet") == NOSTR)
  375.             printf("Message %d:\n", *ip);
  376.         ibuf = setinput(mp);
  377.         c = mp->m_lines;
  378.         if (!lineb)
  379.             printf("\n");
  380.         for (lines = 0; lines < c && lines <= topl; lines++) {
  381.             if (readline(ibuf, linebuf, LINESIZE) < 0)
  382.                 break;
  383.             puts(linebuf);
  384.             lineb = blankline(linebuf);
  385.         }
  386.     }
  387.     return(0);
  388. }
  389.  
  390. /*
  391.  * Touch all the given messages so that they will
  392.  * get mboxed.
  393.  */
  394. stouch(msgvec)
  395.     int msgvec[];
  396. {
  397.     register int *ip;
  398.  
  399.     for (ip = msgvec; *ip != 0; ip++) {
  400.         dot = &message[*ip-1];
  401.         dot->m_flag |= MTOUCH;
  402.         dot->m_flag &= ~MPRESERVE;
  403.     }
  404.     return(0);
  405. }
  406.  
  407. /*
  408.  * Make sure all passed messages get mboxed.
  409.  */
  410.  
  411. mboxit(msgvec)
  412.     int msgvec[];
  413. {
  414.     register int *ip;
  415.  
  416.     for (ip = msgvec; *ip != 0; ip++) {
  417.         dot = &message[*ip-1];
  418.         dot->m_flag |= MTOUCH|MBOX;
  419.         dot->m_flag &= ~MPRESERVE;
  420.     }
  421.     return(0);
  422. }
  423.  
  424. /*
  425.  * List the folders the user currently has.
  426.  */
  427. folders()
  428. {
  429.     char dirname[BUFSIZ];
  430.     char *cmd;
  431.  
  432.     if (getfold(dirname) < 0) {
  433.         printf("No value set for \"folder\"\n");
  434.         return 1;
  435.     }
  436.     if ((cmd = value("LISTER")) == NOSTR)
  437.         cmd = "ls";
  438.     (void) run_command(cmd, 0, -1, -1, dirname, NOSTR);
  439.     return 0;
  440. }
  441.