home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  8.4 KB  |  311 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/print.c,v 2.1 90/10/04 18:25:35 melissa Exp $";
  10. #endif
  11.  
  12. #include "mm.h"
  13. #include "parse.h"
  14. #include "cmds.h"
  15.  
  16. #define NULLSWIT 0
  17. #define HEADERS_ONLY 1
  18. #define SEPARATE_PAGES 2
  19.  
  20.  
  21. /*
  22.  * cmd_list:
  23.  * list messages to file or pipe.
  24.  * a combination of the MM-20 LIST and FILE-LIST commands.
  25.  */
  26.  
  27. int
  28. cmd_list (n)
  29. int n;
  30. {
  31.     int sw = NULLSWIT;
  32.     static char *listdest = NULL;
  33.     char *parse_listfile();
  34.     FILE *od, *mm_popen(), *fopen();
  35.     int pipep;
  36.     int last_message;
  37.     message *m;
  38.     char *msgtxt, *fmt_message();
  39.     keylist only, dont;
  40.     int seq;
  41.  
  42.     if (listdest != NULL) {        /* catch the memory leak */
  43.     free (listdest);
  44.     listdest = NULL;
  45.     }
  46.  
  47.     if (!check_cf(O_RDONLY))        /* have to have a current file */
  48.     return;
  49.     noise ("to");
  50.     listdest = parse_listfile(&sw);    /* get destination file/pipe */
  51.     seq = parse_sequence("current",NULL,NULL); /* get a sequence */
  52.  
  53.     /*
  54.      * NOTE:
  55.      * If seq is TRUE (we parsed a sequence from the top level)
  56.      * then we want to check that there is something in the sequence,
  57.      * so we call sequence_start.
  58.      * If seq is FALSE we want to print the current message and DO NOT
  59.      * want to call sequence_start or sequence_next down in the while().
  60.      */
  61.     if (!seq || sequence_start(cf->sequence)) {    /* do we have a sequence? */
  62.     last_message = sequence_last (cf->sequence); /* remember last msg */
  63.  
  64.     if (listdest == NULL) {        /* /print */
  65.         pipep = true;
  66.         if (strlen(print_filter) == 0)
  67.         cmerr ("no print filter - use SET PRINT-FILTER to define one");
  68.         od = mm_popen (print_filter, "w");
  69.     }
  70.     else if (listdest[0] == '|' && listdest[1] == ' ') { /* pipe */
  71.         pipep = true;
  72.         od = mm_popen (listdest+2, "w"); /* open the pipe */
  73.     }
  74.     else {
  75.         pipep = false;
  76.         od = fopen (listdest, "w");    /* open the output file */
  77.     }
  78.  
  79.     if (od == NULL) {        /* do we have an output descriptor */
  80.         if (pipep)
  81.         cmxeprintf ("?could not start process %s\n", listdest+2);
  82.         else
  83.         perror (listdest);
  84.         free (listdest);        /* clean up */
  85.         listdest = NULL;
  86.         return false;
  87.     }
  88.  
  89.     /* title (filename and date of listing) */
  90.     fprintf (od, "-- Messages from file: %s --\n", cf->filename);
  91.     fprintf (od, "   %s\n\n", daytime(0));
  92.  
  93.     if ((sw == HEADERS_ONLY) || list_include_headers) {
  94.         do {            /* pass one for headers */
  95.         header_summary (cf->current, od); /* ta da! */
  96.         } while (seq && sequence_next (cf->sequence));
  97.     }
  98.  
  99.     if (sw != HEADERS_ONLY) {    /* message bodies too */
  100.         dont = (n == CMD_LITERAL) ? nil : dont_print_headers;
  101.         only = (n == CMD_LITERAL) ? nil : only_print_headers;
  102.         if (seq)
  103.             sequence_start (cf->sequence); /* same sequence */
  104.         fputc ('\n', od);        /* separate headers from messages */
  105.         fputc ('\f', od);        /* with a formfeed */
  106.         fputc ('\n', od);
  107.         do {            /* pass 2 for message body */
  108.         m = &cf->msgs[cf->current];
  109.         fprintf(od, "Message %d -- *********************\n",
  110.             cf->current);
  111.         if ((msgtxt = fmt_message(m, only, dont)) == NULL)
  112.             fputc ('\n', od);
  113.         else {
  114.             fwrite (msgtxt, sizeof(char), strlen(msgtxt), od);
  115.             fputc('\n', od);
  116.             free (msgtxt);
  117.         }
  118.         if (((sw == SEPARATE_PAGES) || list_on_separate_pages)
  119.             && (cf->current != last_message)) {
  120.             fputc ('\f', od);
  121.             fputc ('\n', od);
  122.         }
  123.         } while (seq && sequence_next (cf->sequence));
  124.     }
  125.     
  126.     if (pipep)            /* close up */
  127.         mm_pclose (od);
  128.     else
  129.         fclose (od);
  130.     if (mode == MM_TOP_LEVEL)    /* print that sequence so they */
  131.         seq_print (true);        /* know we did something */
  132.  
  133.     }
  134.  
  135.     if (listdest != NULL) {        /* clean up */
  136.     free (listdest);
  137.     listdest = NULL;
  138.     }
  139.     return true;            /* done! */
  140. }
  141.  
  142.  
  143. /*
  144.  * parse_listfile:
  145.  * parse for optional switches followed by a filename or '|' and command
  146.  * on return, the return value is either a filename or a command starting
  147.  * with "| ".
  148.  * Or, if it returns NULL, then the /print switch was parsed instead of
  149.  * a filename or command.
  150.  * sw may also be set.
  151.  * Note:
  152.  * caller is responsible of freeing the return value when done.
  153.  */
  154.  
  155. char *
  156. parse_listfile (sw)
  157. int *sw;                /* switch parsed if any */
  158. {
  159.     static keywrd swkeys[] = {
  160.     { "headers-only", 0, HEADERS_ONLY },
  161.     { "separate-pages", 0, SEPARATE_PAGES }
  162.     };
  163.     static keytab swtab = { sizeof(swkeys) / sizeof (keywrd), swkeys };
  164.     static fdb switches = { _CMSWI, 0, NULL, (pdat) &swtab, NULL, NULL, NULL };
  165.     static keywrd prkey[] = {
  166.     { "print", 0, 0 }
  167.     };
  168.     static keytab prtab = { sizeof(prkey) /sizeof (keywrd), prkey };
  169.     static fdb prfdb = { _CMSWI, 0, NULL, (pdat) &prtab, NULL, NULL, NULL };
  170.     static fdb filnam = { _CMFIL, CM_SDH|FIL_PO|FIL_VAL|FIL_NODIR, NULL, NULL, 
  171.                 "file to list to", NULL, NULL };
  172.     static fdb pipe = { _CMTOK, CM_SDH, NULL, (pdat) "|", 
  173.               "\"|\" followed by a quoted command line", 
  174.               NULL, NULL };
  175.     static fdb comm = { _CMQST, CM_SDH, NULL, NULL, "quoted command line",
  176.               NULL, NULL };
  177.     pval parseval;
  178.     fdb *used;
  179.     char *ret;
  180.  
  181.     *sw = NULLSWIT;
  182. #ifdef undef
  183.     pipe._cmdef = list_destination;    /* XXX add this var sometime */
  184. #endif /* undef */
  185.     parse (fdbchn(&switches, &prfdb, &pipe, &filnam, NULL), &parseval, &used);
  186.     if (used == &switches) {
  187.     *sw = parseval._pvint;
  188.     parse (fdbchn(&prfdb, &pipe, &filnam, NULL), &parseval, &used);
  189.     }
  190.  
  191.     if (used == &prfdb) {
  192.     return (NULL);
  193.     }
  194.     else if (used == &filnam) {
  195.     if (*parseval._pvfil[0] == '\0')
  196.         cmerr ("destination for output not specified");
  197.     ret = (char *) malloc (strlen(parseval._pvfil[0])+1);
  198.     strcpy (ret, parseval._pvfil[0]);
  199.     return (ret);
  200.     }
  201.     else {                /* if (used == &pipe)  */
  202.     parse (&comm, &parseval, &used);
  203.     ret = (char *) malloc (strlen(parseval._pvstr)+3);
  204.     sprintf (ret, "| %s", parseval._pvstr);
  205.     return (ret);
  206.     }
  207. }
  208.  
  209.  
  210. /*
  211.  * cmd_print:
  212.  */
  213.  
  214. int
  215. cmd_print (n)
  216. int n;
  217. {
  218.     static keywrd swkeys[] = {
  219.     { "separate-pages", 0, SEPARATE_PAGES }
  220.     };
  221.     static keytab swtab = { sizeof(swkeys) / sizeof (keywrd), swkeys };
  222.     static fdb switches = { _CMSWI, 0, NULL, (pdat) &swtab, NULL, NULL, NULL };
  223.     fdb *u;
  224.     FILE *pp, *mm_popen();
  225.     message *m;
  226.     char *msgtxt, *fmt_message();
  227.     keylist only, dont;
  228.     int seq;
  229.     int last_message;
  230.     int sw = NULLSWIT;
  231.  
  232.     if (!check_cf(O_RDONLY))        /* need a file of messages */
  233.     return;
  234.  
  235.     seq = parse_sequence("current", fdbchn(&switches,NULL), &u);
  236.     if (u != NULL) {
  237.     sw = pv._pvint;
  238.     seq = parse_sequence("current", NULL, NULL);
  239.     }
  240.  
  241.  
  242.     /*
  243.      * NOTE:  See NOTE in cmd_list
  244.      */
  245.     if (!seq || sequence_start(cf->sequence)) {    /* got a sequence? */
  246.     last_message = sequence_last (cf->sequence); /* remember last msg */
  247.  
  248.     if (strlen(print_filter) == 0)
  249.         cmerr ("no print filter - use SET PRINT-FILTER to define one");
  250.     if ((pp = mm_popen (print_filter, "w")) == NULL) {
  251.         cmxeprintf ("?could not start process %s\n", print_filter);
  252.         return false;
  253.     }
  254.     
  255.     dont = (n == CMD_LITERAL) ? nil : dont_print_headers;
  256.     only = (n == CMD_LITERAL) ? nil : only_print_headers;
  257.     do {
  258.         m = &cf->msgs[cf->current];
  259.         if ((msgtxt = fmt_message(m, only, dont)) == NULL)
  260.         fputc ('\n', pp);
  261.         else {
  262.         fwrite(msgtxt, sizeof(char), strlen(msgtxt), pp);
  263.         fputc('\n', pp);
  264.         free (msgtxt);
  265.         }
  266.         if (((sw == SEPARATE_PAGES) || list_on_separate_pages)
  267.         && (cf->current != last_message)) {
  268.         fputc ('\f', pp);
  269.         fputc ('\n', pp);
  270.         }
  271.     } while (seq && sequence_next (cf->sequence));
  272.     
  273.     mm_pclose (pp);
  274.     if (mode == MM_TOP_LEVEL)
  275.         seq_print (true);
  276.     }
  277.     return true;
  278. }
  279.  
  280.  
  281. /*
  282.  * cmd_literal:
  283.  * parse for type/print/list (default type) and call appropriate command
  284.  */
  285.  
  286. cmd_literal(n)
  287. int n;
  288. {
  289.     static keywrd litkeys[] = {
  290.     { "list", 0, CMD_LIST },
  291.     { "print", 0, CMD_PRINT },
  292.     { "type", 0, CMD_TYPE }
  293.     };
  294.     static keytab littab = { sizeof(litkeys) / sizeof (keywrd), litkeys };
  295.     static fdb litfdb = { _CMKEY, 0, NULL, (pdat) &littab, NULL,
  296.                   "type", NULL };
  297.     int seq;
  298.     fdb *u;
  299.  
  300.     if (!check_cf (O_RDONLY))        /* since we call parse_sequence */
  301.     return;
  302.     seq = parse_sequence ("current", fdbchn(&litfdb,NULL), &u);
  303.     if (u != NULL) {            /* parsed a command */
  304.     (void) (*mm_cmds[pv._pvkey]) (CMD_LITERAL);
  305.     }
  306.     else {                /* got a sequence */
  307.     check_mark();            /* default TYPE */
  308.     real_type (CMD_LITERAL, seq);
  309.     }
  310. }
  311.