/* program for passthru print */
/* To compile, use the command:
      cc -o passthru passthru.c -lcurses
   or
      cc -o passthru passthru.c -ltermcap
   whichever works
/* This is Version 1.1
   Changes in 1.1 (8-14-97):
      * If TERM undefined, assume VT220
      * If mc5, mc4 undefined, or terminfo entry not found, use VT codes
   Options:
      -r = raw mode. Turns off output post-processing - would affect
           tab expansion, CR/LF.
      -t TERMNAME = specify TERM type.
   Needs:
      * Don't set raw until we need it.
      * Is there some way to block parent process from writing to CRT
        during our interval?
      * Do we want to limit the number of characters we'll write in a
        chunk, so parent process can run?
      * Option to specify mc4, mc5
      * How to run if invoked not as a pipe
*/
#include <stdlib.h>
#include <poll.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <curses.h>
#include <term.h>
#include <termio.h>
 
#define BOOL int
#define BUFFSZ 256
 
struct pollfd fds[1];
static unsigned long nfds = 1;
int    poll_timeout;
int    r;
BOOL char_avail(void);
BOOL char_avail(void)
{
   fds[0].fd = 0;
   fds[0].events = POLLIN;
   nfds = 1;
   poll_timeout = 0;
   r = poll(fds, nfds, poll_timeout);
   if (r < 0) {
      fprintf(stderr, "POLL error %d\n\r", errno);
      return(errno);
   }
   return(r > 0);
}
 
int main(int argc, char *argv[])
{
   char ch;
   struct stat sb;
   int    g;
   int    u;
   char   buf[BUFFSZ];
   int    bytes_read;
   int    bytes_written;
   char   *term_name = 0;
   char   *my_prtr_on = 0;
   char   *my_prtr_off = 0;
   int    errret;
   struct termio tbuf;
   struct termio tbuf_save;
   BOOL   ioctl_ok;
   int    i;
   BOOL   use_raw = FALSE;
   extern char *optarg;
#define VT_PRTR_ON  "\033[?5i"
#define VT_PRTR_OFF "\033[?4i"
 
#ifdef DEBUG
   FILE *log;
 
   log = fopen("/usr/rmcobol/passthru.log", "w");
   fprintf(log, "Into passthru\n");
#endif
 
   while ((i = getopt(argc, argv, "rt:")) != EOF)           /* process options*/
      switch (i) {
      case 'r' : use_raw = TRUE;                              /* r = raw      */
                 break;
      case 't' : term_name = malloc(strlen(optarg));          /* t = TERM     */
                 strcpy(term_name, optarg);
                 break;
      }
   if (!term_name) {
      term_name = getenv("TERM");                           /* get TERM       */
      if (!term_name) {
         /* fprintf(stderr, "TERM not set\n");
         return(1);  */
         term_name = "vt220";                      /* 1.1 */
      }
   }
#ifdef DEBUG
   fprintf(log, "TERM variable = %s\n", term_name);
   if (use_raw)
      fprintf(log, "in raw mode\n");
#endif
   if (setupterm(term_name, 1, &errret) == ERR) {           /* setupterm      */
      /* if (errret == 0)
         fprintf(stderr, "Can't find terminfo entry for %s\n", term_name);
      else
         fprintf(stderr, "Can't find terminfo database\n");
      return(1);  */
      my_prtr_on = VT_PRTR_ON;  /* 1.1 */
      my_prtr_off = VT_PRTR_OFF;
   }                                                        /* get mc4, mc5   */
   if (!prtr_on || !prtr_off) {
      /* fprintf(stderr, "terminfo entry must have 'mc4' and 'mc5' defined for passthru print\n");
      return(1);  */
      my_prtr_on = VT_PRTR_ON;
      my_prtr_off = VT_PRTR_OFF;
   } else {
      my_prtr_on = prtr_on;
      my_prtr_off = prtr_off;
   }
   if (!use_raw)
      ioctl_ok = FALSE;
   else {
      if (ioctl(1, TCGETA, &tbuf) == -1) /* may be pipe */
         ioctl_ok = FALSE;
      else {
         ioctl_ok = TRUE;
         tbuf_save = tbuf;
         tbuf.c_oflag &= ~OPOST;   /* turn off output post-processing */
         ioctl(1, TCSETAW, &tbuf);                          /* set raw        */
      }
   }
   while (1) {                                              /* main loop      */
      fds[0].fd = 0;
      fds[0].events = POLLIN;
      poll_timeout = -1;  /* wait until ready */
      r = poll(fds, nfds, poll_timeout);                    /* wait until ready */
      if (r < 0) {
         fprintf(stderr, "POLL error %d\n", errno);
#ifdef DEBUG
         fprintf(log, "POLL error %d\n", errno);
#endif
         return(errno);
      }
      /* write(1, PASS_ON, strlen(PASS_ON)); */
      if (ioctl_ok)
         ioctl(1, TCSETAW, &tbuf);                          /* set raw        */
      putp(my_prtr_on);                                     /* send prtr_on   */
      fflush(stdout);                                       /* flush          */
      while (char_avail()) {                                /* while there's data */
/*         ch = getchar();
         if (ch == EOF) {
            printf(PASS_OFF);
            fflush(stdout);
            return(0);
         }
         putchar(ch);   */
         bytes_read = read(0, buf, BUFFSZ);                   /* read a chunk */
         if (bytes_read == 0) {
            putp(my_prtr_off);
            fflush(stdout);
            if (ioctl_ok)
               ioctl(1, TCSETAW, &tbuf_save);
            return(0);
         }
         while (bytes_read > 0) {
            bytes_written = write(1, buf, bytes_read);        /* write it     */
            bytes_read -= bytes_written;
         }
      }
      putp(my_prtr_off);                                    /* send prtr_off  */
      fflush(stdout);                                       /* flush          */
      if (ioctl_ok)
         ioctl(1, TCSETAW, &tbuf_save);                     /* restore tty    */
   }
}
