home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / ucbmail / cmd1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-06-03  |  10.0 KB  |  560 lines

  1. /*
  2.  *  C M D 1 . C 
  3.  *
  4.  *  EE/CIS Computer Lab
  5.  *  Department of Computer and Information Sciences
  6.  *  Department of Electrical Engineering
  7.  *  University of Delaware
  8.  *
  9.  *  REVISION HISTORY:
  10.  *
  11.  *  $Revision: 1.6 $
  12.  *
  13.  *  $Log:    cmd1.c,v $
  14.  * Revision 1.6  86/01/14  14:09:45  galvin
  15.  * Let's not be lazy and use MMDF's smtpdate and makedate to parse the
  16.  * date of message into something nice (if we can).  Since the new
  17.  * something nice is smaller than the older mess, allow more room for the
  18.  * subject line to print.
  19.  * 
  20.  * Revision 1.5  86/01/07  13:42:35  galvin
  21.  * Change printhead to use the new parse return value.  Be
  22.  * lazy and if parse couldn't figure out the date, then use
  23.  * the contents of the "Date" header field as is.  It probably
  24.  * should be parsed into something nice, but ... .
  25.  * 
  26.  * Revision 1.4  85/12/18  13:19:14  galvin
  27.  * Add another argument to send to indicate whether or not this
  28.  * message should be delimited by MMDF message delimiters.
  29.  * 
  30.  * Revision 1.3  85/11/20  14:31:24  galvin
  31.  * Changed the name of the command table (cmdtab) to CmdTab so as not
  32.  * to conflict with the command table of MMDF.
  33.  * 
  34.  * Revision 1.2  85/11/20  14:24:51  galvin
  35.  * Added comment header for revision history.
  36.  * 
  37.  *
  38.  */
  39.  
  40. /*
  41.  * Copyright (c) 1980 Regents of the University of California.
  42.  * All rights reserved.  The Berkeley software License Agreement
  43.  * specifies the terms and conditions for redistribution.
  44.  */
  45.  
  46. #ifndef lint
  47. static char *sccsid = "@(#)cmd1.c    5.2 (Berkeley) 6/21/85";
  48. #endif not lint
  49.  
  50. #include "./rcv.h"
  51. #include <sys/stat.h>
  52.  
  53. /*
  54.  * Mail -- a mail program
  55.  *
  56.  * User commands.
  57.  */
  58.  
  59. /*
  60.  * Print the current active headings.
  61.  * Don't change dot if invoker didn't give an argument.
  62.  */
  63.  
  64. static int screen;
  65.  
  66. headers(msgvec)
  67.     int *msgvec;
  68. {
  69.     register int n, mesg, flag;
  70.     register struct message *mp;
  71.     int size;
  72.  
  73.     size = screensize();
  74.     n = msgvec[0];
  75.     if (n != 0)
  76.         screen = (n-1)/size;
  77.     if (screen < 0)
  78.         screen = 0;
  79.     mp = &message[screen * size];
  80.     if (mp >= &message[msgCount])
  81.         mp = &message[msgCount - size];
  82.     if (mp < &message[0])
  83.         mp = &message[0];
  84.     flag = 0;
  85.     mesg = mp - &message[0];
  86.     if (dot != &message[n-1])
  87.         dot = mp;
  88.     for (; mp < &message[msgCount]; mp++) {
  89.         mesg++;
  90.         if (mp->m_flag & MDELETED)
  91.             continue;
  92.         if (flag++ >= size)
  93.             break;
  94.         printhead(mesg);
  95.         sreset();
  96.     }
  97.     if (flag == 0) {
  98.         printf("No more mail.\n");
  99.         return(1);
  100.     }
  101.     return(0);
  102. }
  103.  
  104. /*
  105.  * Set the list of alternate names for out host.
  106.  */
  107. local(namelist)
  108.     char **namelist;
  109. {
  110.     register int c;
  111.     register char **ap, **ap2, *cp;
  112.  
  113.     c = argcount(namelist) + 1;
  114.     if (c == 1) {
  115.         if (localnames == 0)
  116.             return(0);
  117.         for (ap = localnames; *ap; ap++)
  118.             printf("%s ", *ap);
  119.         printf("\n");
  120.         return(0);
  121.     }
  122.     if (localnames != 0)
  123.         cfree((char *) localnames);
  124.     localnames = (char **) calloc((unsigned) c, sizeof (char *));
  125.     for (ap = namelist, ap2 = localnames; *ap; ap++, ap2++) {
  126.         cp = (char *) calloc((unsigned) (strlen(*ap) + 1),
  127.                      sizeof (char));
  128.         strcpy(cp, *ap);
  129.         *ap2 = cp;
  130.     }
  131.     *ap2 = 0;
  132.     return(0);
  133. }
  134.  
  135. /*
  136.  * Scroll to the next/previous screen
  137.  */
  138.  
  139. scroll(arg)
  140.     char arg[];
  141. {
  142.     register int s, size;
  143.     int cur[1];
  144.  
  145.     cur[0] = 0;
  146.     size = screensize();
  147.     s = screen;
  148.     switch (*arg) {
  149.     case 0:
  150.     case '+':
  151.         s++;
  152.         if (s * size > msgCount) {
  153.             printf("On last screenful of messages\n");
  154.             return(0);
  155.         }
  156.         screen = s;
  157.         break;
  158.  
  159.     case '-':
  160.         if (--s < 0) {
  161.             printf("On first screenful of messages\n");
  162.             return(0);
  163.         }
  164.         screen = s;
  165.         break;
  166.  
  167.     default:
  168.         printf("Unrecognized scrolling command \"%s\"\n", arg);
  169.         return(1);
  170.     }
  171.     return(headers(cur));
  172. }
  173.  
  174. /*
  175.  * Compute what the screen size should be.
  176.  * We use the following algorithm:
  177.  *    If user specifies with screen option, use that.
  178.  *    If baud rate < 1200, use  5
  179.  *    If baud rate = 1200, use 10
  180.  *    If baud rate > 1200, use 20
  181.  */
  182. screensize()
  183. {
  184.     register char *cp;
  185.     register int s;
  186. #ifdef    TIOCGWINSZ
  187.     struct winsize ws;
  188. #endif
  189.  
  190.     if ((cp = value("screen")) != NOSTR) {
  191.         s = atoi(cp);
  192.         if (s > 0)
  193.             return(s);
  194.     }
  195.     if (baud < B1200)
  196.         s = 5;
  197.     else if (baud == B1200)
  198.         s = 10;
  199. #ifdef    TIOCGWINSZ
  200.     else if (ioctl(fileno(stdout), TIOCGWINSZ, &ws) == 0 && ws.ws_row != 0)
  201.         s = ws.ws_row - 4;
  202. #endif
  203.     else
  204.         s = 20;
  205.     return(s);
  206. }
  207.  
  208. /*
  209.  * Print out the headlines for each message
  210.  * in the passed message list.
  211.  */
  212.  
  213. from(msgvec)
  214.     int *msgvec;
  215. {
  216.     register int *ip;
  217.  
  218.     for (ip = msgvec; *ip != NULL; ip++) {
  219.         printhead(*ip);
  220.         sreset();
  221.     }
  222.     if (--ip >= msgvec)
  223.         dot = &message[*ip - 1];
  224.     return(0);
  225. }
  226.  
  227. /*
  228.  * Print out the header of a specific message.
  229.  * This is a slight improvement to the standard one.
  230.  */
  231.  
  232. printhead(mesg)
  233. {
  234.     struct message *mp;
  235.     FILE *ibuf;
  236.     char headline[LINESIZE], wcount[10], *subjline, dispc, curind;
  237.     char pbuf[BUFSIZ];
  238.     int s;
  239.     long smtpdate();
  240.     long date;
  241.     struct headline hl;
  242.     register char *cp;
  243.  
  244.     mp = &message[mesg-1];
  245.     ibuf = setinput(mp);
  246.     readline(ibuf, headline);
  247.     subjline = hfield("subject", mp);
  248.     if (subjline == NOSTR)
  249.         subjline = hfield("subj", mp);
  250.  
  251.     /*
  252.      * Bletch!
  253.      */
  254.  
  255.     if (subjline != NOSTR && strlen(subjline) > 34)
  256.         subjline[35] = '\0';
  257.     curind = dot == mp ? '>' : ' ';
  258.     dispc = ' ';
  259.     if (mp->m_flag & MSAVED)
  260.         dispc = '*';
  261.     if (mp->m_flag & MPRESERVE)
  262.         dispc = 'P';
  263.     if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
  264.         dispc = 'N';
  265.     if ((mp->m_flag & (MREAD|MNEW)) == 0)
  266.         dispc = 'U';
  267.     if (mp->m_flag & MBOX)
  268.         dispc = 'M';
  269.     if (parse(headline, &hl, pbuf))
  270.         if ((cp = hfield("date", mp)) != NOSTR)
  271.             if ((date = smtpdate(cp)) != -1L) {
  272.                 makedate(&date, headline);
  273.                 headline[9] = '\0';
  274.                 hl.l_date = savestr(headline);
  275.             }
  276.             else
  277.                 hl.l_date = cp;
  278.     sprintf(wcount, " %d/%ld", mp->m_lines, mp->m_size);
  279.     s = strlen(wcount);
  280.     cp = wcount + s;
  281.     while (s < 7)
  282.         s++, *cp++ = ' ';
  283.     *cp = '\0';
  284.     if (subjline != NOSTR)
  285.         printf("%c%c%3d %-8.8s %9.9s %s \"%s\"\n", curind, dispc,
  286.             mesg, nameof(mp, 0), hl.l_date, wcount, subjline);
  287.     else
  288.         printf("%c%c%3d %-8.8s %9.9s %s\n", curind, dispc, mesg,
  289.             nameof(mp, 0), hl.l_date, wcount);
  290. }
  291.  
  292. /*
  293.  * Print out the value of dot.
  294.  */
  295.  
  296. pdot()
  297. {
  298.     printf("%d\n", dot - &message[0] + 1);
  299.     return(0);
  300. }
  301.  
  302. /*
  303.  * Print out all the possible commands.
  304.  */
  305.  
  306. pcmdlist()
  307. {
  308.     register struct cmd *cp;
  309.     register int cc;
  310.     extern struct cmd CmdTab[];
  311.  
  312.     printf("Commands are:\n");
  313.     for (cc = 0, cp = CmdTab; cp->c_name != NULL; cp++) {
  314.         cc += strlen(cp->c_name) + 2;
  315.         if (cc > 72) {
  316.             printf("\n");
  317.             cc = strlen(cp->c_name) + 2;
  318.         }
  319.         if ((cp+1)->c_name != NOSTR)
  320.             printf("%s, ", cp->c_name);
  321.         else
  322.             printf("%s\n", cp->c_name);
  323.     }
  324.     return(0);
  325. }
  326.  
  327. /*
  328.  * Paginate messages, honor ignored fields.
  329.  */
  330. more(msgvec)
  331.     int *msgvec;
  332. {
  333.     return (type1(msgvec, 1, 1));
  334. }
  335.  
  336. /*
  337.  * Paginate messages, even printing ignored fields.
  338.  */
  339. More(msgvec)
  340.     int *msgvec;
  341. {
  342.  
  343.     return (type1(msgvec, 0, 1));
  344. }
  345.  
  346. /*
  347.  * Type out messages, honor ignored fields.
  348.  */
  349. type(msgvec)
  350.     int *msgvec;
  351. {
  352.  
  353.     return(type1(msgvec, 1, 0));
  354. }
  355.  
  356. /*
  357.  * Type out messages, even printing ignored fields.
  358.  */
  359. Type(msgvec)
  360.     int *msgvec;
  361. {
  362.  
  363.     return(type1(msgvec, 0, 0));
  364. }
  365.  
  366. /*
  367.  * Type out the messages requested.
  368.  */
  369. jmp_buf    pipestop;
  370.  
  371. type1(msgvec, doign, page)
  372.     int *msgvec;
  373. {
  374.     register *ip;
  375.     register struct message *mp;
  376.     register int mesg;
  377.     register char *cp;
  378.     int nlines;
  379.     int brokpipe();
  380.     FILE *obuf;
  381.  
  382.     obuf = stdout;
  383.     if (setjmp(pipestop)) {
  384.         if (obuf != stdout) {
  385.             pipef = NULL;
  386.             pclose(obuf);
  387.         }
  388.         sigset(SIGPIPE, SIG_DFL);
  389.         return(0);
  390.     }
  391.     if (intty && outtty && (page || (cp = value("crt")) != NOSTR)) {
  392.         if (!page) {
  393.             nlines = 0;
  394.             for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
  395.                 nlines += message[*ip - 1].m_lines;
  396.         }
  397.         if (page || nlines > atoi(cp)) {
  398.             obuf = popen(MORE, "w");
  399.             if (obuf == NULL) {
  400.                 perror(MORE);
  401.                 obuf = stdout;
  402.             }
  403.             else {
  404.                 pipef = obuf;
  405.                 sigset(SIGPIPE, brokpipe);
  406.             }
  407.         }
  408.     }
  409.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  410.         mesg = *ip;
  411.         touch(mesg);
  412.         mp = &message[mesg-1];
  413.         dot = mp;
  414.         print(mp, obuf, doign);
  415.     }
  416.     if (obuf != stdout) {
  417.         pipef = NULL;
  418.         pclose(obuf);
  419.     }
  420.     sigset(SIGPIPE, SIG_DFL);
  421.     return(0);
  422. }
  423.  
  424. /*
  425.  * Respond to a broken pipe signal --
  426.  * probably caused by using quitting more.
  427.  */
  428.  
  429. brokpipe()
  430. {
  431. # ifndef VMUNIX
  432.     signal(SIGPIPE, brokpipe);
  433. # endif
  434.     longjmp(pipestop, 1);
  435. }
  436.  
  437. /*
  438.  * Print the indicated message on standard output.
  439.  */
  440.  
  441. print(mp, obuf, doign)
  442.     register struct message *mp;
  443.     FILE *obuf;
  444. {
  445.  
  446.     if (value("quiet") == NOSTR)
  447.         fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1);
  448.     touch(mp - &message[0] + 1);
  449.     send(mp, obuf, doign, 0);
  450. }
  451.  
  452. /*
  453.  * Print the top so many lines of each desired message.
  454.  * The number of lines is taken from the variable "toplines"
  455.  * and defaults to 5.
  456.  */
  457.  
  458. top(msgvec)
  459.     int *msgvec;
  460. {
  461.     register int *ip;
  462.     register struct message *mp;
  463.     register int mesg;
  464.     int c, topl, lines, lineb;
  465.     char *valtop, linebuf[LINESIZE];
  466.     FILE *ibuf;
  467.  
  468.     topl = 5;
  469.     valtop = value("toplines");
  470.     if (valtop != NOSTR) {
  471.         topl = atoi(valtop);
  472.         if (topl < 0 || topl > 10000)
  473.             topl = 5;
  474.     }
  475.     lineb = 1;
  476.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  477.         mesg = *ip;
  478.         touch(mesg);
  479.         mp = &message[mesg-1];
  480.         dot = mp;
  481.         if (value("quiet") == NOSTR)
  482.             printf("Message %2d:\n", mesg);
  483.         ibuf = setinput(mp);
  484.         c = mp->m_lines;
  485.         if (!lineb)
  486.             printf("\n");
  487.         for (lines = 0; lines < c && lines <= topl; lines++) {
  488.             if (readline(ibuf, linebuf) <= 0)
  489.                 break;
  490.             puts(linebuf);
  491.             lineb = blankline(linebuf);
  492.         }
  493.     }
  494.     return(0);
  495. }
  496.  
  497. /*
  498.  * Touch all the given messages so that they will
  499.  * get mboxed.
  500.  */
  501.  
  502. stouch(msgvec)
  503.     int msgvec[];
  504. {
  505.     register int *ip;
  506.  
  507.     for (ip = msgvec; *ip != 0; ip++) {
  508.         dot = &message[*ip-1];
  509.         dot->m_flag |= MTOUCH;
  510.         dot->m_flag &= ~MPRESERVE;
  511.     }
  512.     return(0);
  513. }
  514.  
  515. /*
  516.  * Make sure all passed messages get mboxed.
  517.  */
  518.  
  519. mboxit(msgvec)
  520.     int msgvec[];
  521. {
  522.     register int *ip;
  523.  
  524.     for (ip = msgvec; *ip != 0; ip++) {
  525.         dot = &message[*ip-1];
  526.         dot->m_flag |= MTOUCH|MBOX;
  527.         dot->m_flag &= ~MPRESERVE;
  528.     }
  529.     return(0);
  530. }
  531.  
  532. /*
  533.  * List the folders the user currently has.
  534.  */
  535. folders()
  536. {
  537.     char dirname[BUFSIZ];
  538.     int pid, s, e;
  539.  
  540.     if (getfold(dirname) < 0) {
  541.         printf("No value set for \"folder\"\n");
  542.         return(-1);
  543.     }
  544.     switch ((pid = fork())) {
  545.     case 0:
  546.         sigchild();
  547.         execlp("ls", "ls", dirname, 0);
  548.         _exit(1);
  549.  
  550.     case -1:
  551.         perror("fork");
  552.         return(-1);
  553.  
  554.     default:
  555.         while ((e = wait(&s)) != -1 && e != pid)
  556.             ;
  557.     }
  558.     return(0);
  559. }
  560.