home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / metamail / tahoe / cmd1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-02  |  10.6 KB  |  573 lines

  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
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifdef notdef
  14. static char sccsid[] = "@(#)cmd1.c    5.5 (Berkeley) 2/18/88";
  15. #endif /* notdef */
  16.  
  17. #include "rcv.h"
  18. #include <sys/stat.h>
  19. #include <sys/wait.h>
  20.  
  21. /*
  22.  * Mail -- a mail program
  23.  *
  24.  * User commands.
  25.  */
  26.  
  27. /*
  28.  * Print the current active headings.
  29.  * Don't change dot if invoker didn't give an argument.
  30.  */
  31.  
  32. static int screen;
  33.  
  34. headers(msgvec)
  35.     int *msgvec;
  36. {
  37.     register int n, mesg, flag;
  38.     register struct message *mp;
  39.     int size;
  40.  
  41.     size = screensize();
  42.     n = msgvec[0];
  43.     if (n != 0)
  44.         screen = (n-1)/size;
  45.     if (screen < 0)
  46.         screen = 0;
  47.     mp = &message[screen * size];
  48.     if (mp >= &message[msgCount])
  49.         mp = &message[msgCount - size];
  50.     if (mp < &message[0])
  51.         mp = &message[0];
  52.     flag = 0;
  53.     mesg = mp - &message[0];
  54.     if (dot != &message[n-1])
  55.         dot = mp;
  56.     for (; mp < &message[msgCount]; mp++) {
  57.         mesg++;
  58.         if (mp->m_flag & MDELETED)
  59.             continue;
  60.         if (flag++ >= size)
  61.             break;
  62.         printhead(mesg);
  63.         sreset();
  64.     }
  65.     if (flag == 0) {
  66.         printf("No more mail.\n");
  67.         return(1);
  68.     }
  69.     return(0);
  70. }
  71.  
  72. /*
  73.  * Set the list of alternate names for out host.
  74.  */
  75. local(namelist)
  76.     char **namelist;
  77. {
  78.     register int c;
  79.     register char **ap, **ap2, *cp;
  80.  
  81.     c = argcount(namelist) + 1;
  82.     if (c == 1) {
  83.         if (localnames == 0)
  84.             return(0);
  85.         for (ap = localnames; *ap; ap++)
  86.             printf("%s ", *ap);
  87.         printf("\n");
  88.         return(0);
  89.     }
  90.     if (localnames != 0)
  91.         cfree((char *) localnames);
  92.     localnames = (char **) calloc((unsigned) c, sizeof (char *));
  93.     for (ap = namelist, ap2 = localnames; *ap; ap++, ap2++) {
  94.         cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char));
  95.         strcpy(cp, *ap);
  96.         *ap2 = cp;
  97.     }
  98.     *ap2 = 0;
  99.     return(0);
  100. }
  101.  
  102. /*
  103.  * Scroll to the next/previous screen
  104.  */
  105.  
  106. scroll(arg)
  107.     char arg[];
  108. {
  109.     register int s, size;
  110.     int cur[1];
  111.  
  112.     cur[0] = 0;
  113.     size = screensize();
  114.     s = screen;
  115.     switch (*arg) {
  116.     case 0:
  117.     case '+':
  118.         s++;
  119.         if (s * size > msgCount) {
  120.             printf("On last screenful of messages\n");
  121.             return(0);
  122.         }
  123.         screen = s;
  124.         break;
  125.  
  126.     case '-':
  127.         if (--s < 0) {
  128.             printf("On first screenful of messages\n");
  129.             return(0);
  130.         }
  131.         screen = s;
  132.         break;
  133.  
  134.     default:
  135.         printf("Unrecognized scrolling command \"%s\"\n", arg);
  136.         return(1);
  137.     }
  138.     return(headers(cur));
  139. }
  140.  
  141. /*
  142.  * Compute screen size.
  143.  */
  144. screensize()
  145. {
  146.     int s;
  147.     char *cp;
  148.  
  149.     if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
  150.         return s;
  151.     return screenheight - 4;
  152. }
  153.  
  154. /*
  155.  * Print out the headlines for each message
  156.  * in the passed message list.
  157.  */
  158.  
  159. from(msgvec)
  160.     int *msgvec;
  161. {
  162.     register int *ip;
  163.  
  164.     for (ip = msgvec; *ip != NULL; ip++) {
  165.         printhead(*ip);
  166.         sreset();
  167.     }
  168.     if (--ip >= msgvec)
  169.         dot = &message[*ip - 1];
  170.     return(0);
  171. }
  172.  
  173. /*
  174.  * Print out the header of a specific message.
  175.  * This is a slight improvement to the standard one.
  176.  */
  177.  
  178. printhead(mesg)
  179. {
  180.     struct message *mp;
  181.     char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
  182.     char pbuf[BUFSIZ];
  183.     struct headline hl;
  184.     int subjlen;
  185.  
  186.     mp = &message[mesg-1];
  187.     readline(setinput(mp), headline);
  188.     if ((subjline = hfield("subject", mp)) == NOSTR)
  189.         subjline = hfield("subj", mp);
  190.     /*
  191.      * Bletch!
  192.      */
  193.     curind = dot == mp ? '>' : ' ';
  194.     dispc = ' ';
  195.     if (mp->m_flag & MSAVED)
  196.         dispc = '*';
  197.     if (mp->m_flag & MPRESERVE)
  198.         dispc = 'P';
  199.     if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
  200.         dispc = 'N';
  201.     if ((mp->m_flag & (MREAD|MNEW)) == 0)
  202.         dispc = 'U';
  203.     if (mp->m_flag & MBOX)
  204.         dispc = 'M';
  205.     parse(headline, &hl, pbuf);
  206.     sprintf(wcount, "%3d/%-4ld", mp->m_lines, mp->m_size);
  207.     subjlen = screenwidth - 50 - strlen(wcount);
  208.     if (subjline == NOSTR || subjlen < 0)        /* pretty pathetic */
  209.         printf("%c%c%3d %-20.20s  %16.16s %s\n",
  210.             curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount);
  211.     else
  212.         printf("%c%c%3d %-20.20s  %16.16s %s \"%.*s\"\n",
  213.             curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount,
  214.             subjlen, subjline);
  215. }
  216.  
  217. /*
  218.  * Print out the value of dot.
  219.  */
  220.  
  221. pdot()
  222. {
  223.     printf("%d\n", dot - &message[0] + 1);
  224.     return(0);
  225. }
  226.  
  227. /*
  228.  * Print out all the possible commands.
  229.  */
  230.  
  231. pcmdlist()
  232. {
  233.     register struct cmd *cp;
  234.     register int cc;
  235.     extern struct cmd cmdtab[];
  236.  
  237.     printf("Commands are:\n");
  238.     for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
  239.         cc += strlen(cp->c_name) + 2;
  240.         if (cc > 72) {
  241.             printf("\n");
  242.             cc = strlen(cp->c_name) + 2;
  243.         }
  244.         if ((cp+1)->c_name != NOSTR)
  245.             printf("%s, ", cp->c_name);
  246.         else
  247.             printf("%s\n", cp->c_name);
  248.     }
  249.     return(0);
  250. }
  251.  
  252. /*
  253.  * Paginate messages, honor ignored fields.
  254.  */
  255. more(msgvec)
  256.     int *msgvec;
  257. {
  258.     return (type1(msgvec, 1, 1));
  259. }
  260.  
  261. /*
  262.  * Paginate messages, even printing ignored fields.
  263.  */
  264. More(msgvec)
  265.     int *msgvec;
  266. {
  267.  
  268.     return (type1(msgvec, 0, 1));
  269. }
  270.  
  271. /*
  272.  * Type out messages, honor ignored fields.
  273.  */
  274. type(msgvec)
  275.     int *msgvec;
  276. {
  277.  
  278.     return(type1(msgvec, 1, 0));
  279. }
  280.  
  281. /*
  282.  * Type out messages, even printing ignored fields.
  283.  */
  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.  
  296. type1(msgvec, doign, page)
  297.     int *msgvec;
  298. {
  299.     register *ip;
  300.     register struct message *mp;
  301.     register int mesg;
  302.     register char *cp;
  303.     int nlines;
  304.     int brokpipe();
  305.     FILE *obuf;
  306. #ifndef NOMETAMAIL
  307.     int PipeToMore = 0;
  308. #endif
  309.  
  310.     obuf = stdout;
  311.     if (setjmp(pipestop)) {
  312.         if (obuf != stdout) {
  313.             pipef = NULL;
  314.             pclose(obuf);
  315.         }
  316.         signal(SIGPIPE, SIG_DFL);
  317.         return(0);
  318.     }
  319.     if (intty && outtty && (page || (cp = value("crt")) != NOSTR)) {
  320.         nlines = 0;
  321.         if (!page) {
  322.             for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
  323.                 nlines += message[*ip - 1].m_lines;
  324.         }
  325.         if (page || nlines > atoi(cp)) {
  326. #ifndef NOMETAMAIL
  327.                     PipeToMore = 1;
  328. #else
  329.             cp = value("PAGER");
  330.             if (cp == NULL || *cp == '\0')
  331.                 cp = MORE;
  332.             obuf = popen(cp, "w");
  333.             if (obuf == NULL) {
  334.                 perror(cp);
  335.                 obuf = stdout;
  336.             } else {
  337.                 pipef = obuf;
  338.                 signal(SIGPIPE, brokpipe);
  339.             }
  340. #endif
  341.         }
  342.     }
  343.     for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
  344.         mesg = *ip;
  345.         touch(mesg);
  346.         mp = &message[mesg-1];
  347.         dot = mp;
  348.         if (value("quiet") == NOSTR)
  349.             fprintf(obuf, "Message %d:\n", mesg);
  350. #ifndef NOMETAMAIL
  351. #include <sgtty.h>
  352.         if (!getenv("NOMETAMAIL") && nontext(mp)) {
  353.             char Fname[100], Cmd[120];
  354.             FILE *fp;
  355.             int code;
  356.             struct sgttyb ttystatein, ttystateout;
  357.  
  358.             sprintf(Fname, "/tmp/mail-metamail.%d.%d", getpid(), getuid());
  359.             fp = fopen(Fname, "w");
  360.             if (!fp) {
  361.             perror(Fname);
  362.             } else {
  363.             send(mp, fp, 0);
  364.             fclose(fp);
  365.             sprintf(Cmd, "metamail -z %s -m Mail %s", (PipeToMore) ? "-p" : "", Fname);
  366.             if (obuf != stdout) {
  367.                 pipef = NULL;
  368.                 pclose(obuf);
  369.                 obuf = stdout;
  370.             }
  371.             gtty(fileno(stdin), &ttystatein);
  372.             gtty(fileno(stdout), &ttystateout);
  373.             code = system(Cmd);
  374.             stty(fileno(stdin), &ttystatein);
  375.             stty(fileno(stdout), &ttystateout);
  376. /*            The following line would cause the raw mail to print out if metamail failed */
  377. /*            if (code) print(mp, obuf, doign); */
  378.             }
  379.         } else {
  380.             if (PipeToMore && stdout == obuf) {
  381.             obuf = popen(MORE, "w");
  382.             if (obuf == NULL) {
  383.                 perror(MORE);
  384.                 obuf = stdout;
  385.             }
  386.             else {
  387.                 pipef = obuf;
  388.                 signal(SIGPIPE, brokpipe);
  389.             }
  390.             }
  391.             send(mp, obuf, doign);
  392.         }
  393. #else
  394.         send(mp, obuf, doign);
  395. #endif
  396. /*        send(mp, obuf, doign);*/
  397.     }
  398.     if (obuf != stdout) {
  399.         pipef = NULL;
  400.         pclose(obuf);
  401.     }
  402.     signal(SIGPIPE, SIG_DFL);
  403.     return(0);
  404. }
  405.  
  406. /*
  407.  * Respond to a broken pipe signal --
  408.  * probably caused by using quitting more.
  409.  */
  410.  
  411. brokpipe()
  412. {
  413.     longjmp(pipestop, 1);
  414. }
  415.  
  416. /*
  417.  * Print the top so many lines of each desired message.
  418.  * The number of lines is taken from the variable "toplines"
  419.  * and defaults to 5.
  420.  */
  421.  
  422. top(msgvec)
  423.     int *msgvec;
  424. {
  425.     register int *ip;
  426.     register struct message *mp;
  427.     register int mesg;
  428.     int c, topl, lines, lineb;
  429.     char *valtop, linebuf[LINESIZE];
  430.     FILE *ibuf;
  431.  
  432.     topl = 5;
  433.     valtop = value("toplines");
  434.     if (valtop != NOSTR) {
  435.         topl = atoi(valtop);
  436.         if (topl < 0 || topl > 10000)
  437.             topl = 5;
  438.     }
  439.     lineb = 1;
  440.     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  441.         mesg = *ip;
  442.         touch(mesg);
  443.         mp = &message[mesg-1];
  444.         dot = mp;
  445.         if (value("quiet") == NOSTR)
  446.             printf("Message %2d:\n", mesg);
  447.         ibuf = setinput(mp);
  448.         c = mp->m_lines;
  449.         if (!lineb)
  450.             printf("\n");
  451.         for (lines = 0; lines < c && lines <= topl; lines++) {
  452.             if (readline(ibuf, linebuf) < 0)
  453.                 break;
  454.             puts(linebuf);
  455.             lineb = blankline(linebuf);
  456.         }
  457.     }
  458.     return(0);
  459. }
  460.  
  461. /*
  462.  * Touch all the given messages so that they will
  463.  * get mboxed.
  464.  */
  465.  
  466. stouch(msgvec)
  467.     int msgvec[];
  468. {
  469.     register int *ip;
  470.  
  471.     for (ip = msgvec; *ip != 0; ip++) {
  472.         dot = &message[*ip-1];
  473.         dot->m_flag |= MTOUCH;
  474.         dot->m_flag &= ~MPRESERVE;
  475.     }
  476.     return(0);
  477. }
  478.  
  479. /*
  480.  * Make sure all passed messages get mboxed.
  481.  */
  482.  
  483. mboxit(msgvec)
  484.     int msgvec[];
  485. {
  486.     register int *ip;
  487.  
  488.     for (ip = msgvec; *ip != 0; ip++) {
  489.         dot = &message[*ip-1];
  490.         dot->m_flag |= MTOUCH|MBOX;
  491.         dot->m_flag &= ~MPRESERVE;
  492.     }
  493.     return(0);
  494. }
  495.  
  496. /*
  497.  * List the folders the user currently has.
  498.  */
  499. folders()
  500. {
  501.     char dirname[BUFSIZ];
  502.     int pid, e;
  503.     union wait s;
  504.  
  505.     if (getfold(dirname) < 0) {
  506.         printf("No value set for \"folder\"\n");
  507.         return(-1);
  508.     }
  509.     switch ((pid = fork())) {
  510.     case 0:
  511.         execlp("ls", "ls", dirname, 0);
  512.         _exit(1);
  513.  
  514.     case -1:
  515.         perror("fork");
  516.         return(-1);
  517.  
  518.     default:
  519.         while ((e = wait(&s)) != -1 && e != pid)
  520.             ;
  521.     }
  522.     return(0);
  523. }
  524. #ifndef NOMETAMAIL
  525. #include <ctype.h>
  526.  
  527. nontext(mp) 
  528. struct message *mp;
  529. {
  530.     long c;
  531.     FILE *ibuf;
  532.     char line[LINESIZE], *s, *t;
  533.  
  534.     ibuf = setinput(mp);
  535.     c = mp->m_size;
  536.     while (c > 0L) {
  537.     fgets(line, LINESIZE, ibuf);
  538.     c -= (long) strlen(line);
  539.     if (line[0] == '\n') return(0);
  540.     for (s=line; *s; ++s) if (isupper(*s)) *s = tolower(*s);
  541.     if (!strncmp(line, "content-type:", 13) && notplain(line+13)) return(1);
  542.     }
  543.     return(0);
  544. }
  545. notplain(s)
  546. char *s;
  547. {
  548.     char *t;
  549.     if (!s) return(1);
  550.     while (*s && isspace(*s)) ++s;
  551.     for(t=s; *t; ++t) if (isupper(*t)) *t = tolower(*t);
  552.     while (t > s && isspace(*--t)) {;}
  553.     if (((t-s) == 3) && !strncmp(s, "text", 4)) return(0);
  554.     if (strncmp(s, "text/plain", 10)) return(1);
  555.     t = (char *) index(s, ';');
  556.     while (t) {
  557.         ++t;
  558.         while (*t && isspace(*t)) ++t;
  559.         if (!strncmp(t, "charset", 7)) {
  560.             s = (char *) index(t, '=');
  561.             if (s) {
  562.                 ++s;
  563.                 while (*s && isspace(*s)) ++s;
  564.                 if (!strncmp(s, "us-ascii", 8)) return(0);
  565.             }
  566.             return(1);
  567.         }
  568.         t = (char *) index(t, ';');
  569.     }
  570.     return(0); /* no charset, was text/plain */
  571. }
  572. #endif
  573.