/* pcprint.c -- Print files on a printer which is locally attached to a DEC * VT102, VT200, VT300, or compatible, or to a PC that emulates them (e.g. IBM * PC with Kermit 2.31 or later). * * Usage: * command | pcprint * pcprint < file * pcprint file(s) * and in MM, "set print-filter pcprint", then use MM's "print" command. * * "pcprint" allows printing of text files and binary files with no parity. * To do this, the terminal has to be put in "raw mode", in which none of its * other functions work. Therefore, the terminal is periodically restored to * normal so that it can be interrupted with Ctrl-C, do Xon/Xoff, etc. * * Authors: Christine Gianone and Frank da Cruz, CUCCA, March 14, 1989 */ /* Preprocessor includes and defines */ #include /* Standard i/o */ #include /* Set/Get terminal modes */ #include /* For keyboard interrupts */ #include /* For stat.h... */ #include /* For file status queries */ #define BUFL 1000 /* Input buffer length */ /* Global Declarations */ static struct sgttyb old, new; /* Terminal modes structure */ static struct stat statbuf; /* File status structure */ int fd; /* Input file descriptor */ int doexit(); /* Forward declaration of doexit() */ /* Main function */ main(argc,argv) int argc; char *argv[]; { int nf; /* File number from command line. */ int x; /* Temporary variable. */ /* Find out the current terminal settings from Unix */ gtty(1,&old); /* For restoring tty to how it was. */ gtty(1,&new); /* Plus a new copy, */ new.sg_flags |= RAW; /* for putting tty in "raw mode" */ /* to allow 8-bit data output */ /* with no parity. */ /* Send the ANSI "begin transparent print" sequence, "ESC [ 5 i". This */ /* makes the terminal send its input to the printer instead of the screen. */ printf("%c[5i",'\033'); /* Print the escape sequence. */ fflush(stdout); /* Make sure it goes out */ /* before we change tty modes. */ /* Since programs can be halted by users typing Ctrl-C or other keyboard */ /* interrupt characters, we must catch these interrupts in order to restore */ /* the terminal to normal (non-printing, non-raw) mode before exiting. */ signal(SIGINT,doexit); /* Control-C */ signal(SIGQUIT,doexit); /* Control-\ */ /* Input can either be from standard input (redirected stdin, pipe, or MM */ /* PRINT command), or else from a list of files given on the command line. */ /* Case 1: Print from Standard Input, e.g. "pcprint < test.txt". */ if (argc == 1) { /* If printing from standard input */ fd = 0; /* File descriptor 0 = stdin */ dofile(); /* Print until no more data */ doexit(); /* Done */ } /* Case 2: Filename(s) specified on command line, e.g. "pcprint x.a x.b". */ /* Each file must be opened, printed, & closed. Skip over directory files. */ nf = 0; /* Current file number. */ while (++nf < argc) { /* Start with file 1, if any .*/ if (stat(argv[nf],&statbuf) < 0) /* First see if the file exists. */ continue; /* Doesn't exist, try next one. */ x = statbuf.st_mode & S_IFMT; /* Check file format. */ if ((x != 0) && (x != S_IFREG)) /* If not a regular file, */ continue; /* try the next file. */ if ((fd = open(argv[nf],0)) < 0) /* Try to open the file read-only. */ continue; /* On failure, try next file. */ dofile(); /* Opened OK, call printing function */ close(fd); /* and after printing close the file */ } doexit(); /* No more files, clean up and exit. */ } /* Function to print one file */ dofile() { char buf[BUFL]; /* Input buffer */ int i; /* Input buffer counter */ int n; /* Input character EOF indicator */ char c; /* Input character itself */ int done; /* Flag for done */ done = 0; /* Initial condition for loop. */ while (!done) { /* While not done... */ stty(1,&old); /* Put terminal in normal mode */ /* to catch terminal interrupts. */ for (i = 0; i < BUFL-1; i++) { /* Loop to fill the input buffer. */ n = read(fd,&c,1); /* Read one character. */ if (n == 0) { /* If no more, */ done = 1; /* we're done! */ break; /* Break out of this for-loop. */ } if (c == '\n') /* If character is a newline, */ buf[i++] = '\r'; /* supply a carriage return. */ buf[i] = c; /* Deposit character in buffer. */ } stty(1,&new); /* Put tty in raw (no-parity) mode. */ write(1,buf,i); /* Request UNIX write the buffer. */ fflush(stdout); /* Now make UNIX really do it. */ } } /* Exit function. Leave user's terminal the way it was upon entry. */ /* Turn off transparent print by sending the escape sequence "ESC [ 4 i". */ doexit() { /* Program exit. */ if (fd != 0) close(fd); /* Close any open input file. */ signal(SIGINT,SIG_DFL); /* Return keyboard interrupts */ signal(SIGQUIT,SIG_DFL); /* to normal. */ printf("%c[4i",'\033'); /* Turn off transparent print. */ fflush(stdout); /* Make sure it goes out. */ stty(1,&old); /* Restore terminal to normal. */ exit(0); /* And exit. */ }