lprps: use lpr with a PostScript printer, Part01/01

James Clark jjc at jclark.UUCP
Tue Dec 18 22:48:19 AEST 1990


Archive-name: lprps-0.1/part01

This is lprps version 0.1.

This is a collection of programs for using lpr with a PostScript laser
printer.  I have used it for about a year on a Sun 4 running SunOS
4.0.3 with a QMS-PS 800+ printer.  It has not been tested on any other
systems.

It contains the following programs:

lprps	handles communication with the printer
psif	allows separate filters to be used for text and PostScript
textps	simple text to PostScript filter (in case you don't already have one)
psrev	PostScript page reversal filter

Some features are:
 
* Deals intelligently with output generated by the printer: printer
  errors (such as ``out of paper'') are logged using syslog; other
  errors and output generated by the user's job are mailed back to the
  user.

* Performs printer accounting.

* Ensures that the printer is ready to receive the job.

* Determines whether file is PostScript or text (by looking at the
  first 2 bytes), and uses the appropriate filter; this is done
  cleanly so that you can use your favourite text-to-PostScript
  filter.

See the file INSTALL for installation information.

There aren't any man pages.

There is no copyright on lprps.

I would appreciate hearing about any improvements that you make to
lprps.

James Clark
jjc at jclark.uucp
jjc%jclark at relay.eu.net

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README INSTALL Makefile psrev.c lprps.c psif.c textps.c
# Wrapped by jjc at jclark on Tue Dec 18 11:38:59 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1351 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis is lprps version 0.1.
X
XThis is a collection of programs for using lpr with a PostScript laser
Xprinter.  I have used it for about a year on a Sun 4 running SunOS
X4.0.3 with a QMS-PS 800+ printer.  It has not been tested on any other
Xsystems.
X
XIt contains the following programs:
X
Xlprps	handles communication with the printer
Xpsif	allows separate filters to be used for text and PostScript
Xtextps	simple text to PostScript filter (in case you don't already have one)
Xpsrev	PostScript page reversal filter
X
XSome features are:
X 
X* Deals intelligently with output generated by the printer: printer
X  errors (such as ``out of paper'') are logged using syslog; other
X  errors and output generated by the user's job are mailed back to the
X  user.
X
X* Performs printer accounting.
X
X* Ensures that the printer is ready to receive the job.
X
X* Determines whether file is PostScript or text (by looking at the
X  first 2 bytes), and uses the appropriate filter; this is done
X  cleanly so that you can use your favourite text-to-PostScript
X  filter.
X
XSee the file INSTALL for installation information.
X
XThere aren't any man pages.
X
XThere is no copyright on lprps.
X
XI would appreciate hearing about any improvements that you make to
Xlprps.
X
XJames Clark
Xjjc at jclark.uucp
Xjjc%jclark at relay.eu.net
X
X$Header: /usr/jjc/lprps/RCS/README,v 1.3 90/12/18 11:13:49 jjc Rel $
END_OF_FILE
if test 1351 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'INSTALL'\"
else
echo shar: Extracting \"'INSTALL'\" \(2742 characters\)
sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
XYou will need to edit the Makefile. The comments should make it clear
Xwhat needs changing. Do a make; then do a make install as root.
X
XYou need to decide what baud rate you are going to use. If you have a
Xvery old Laserwriter (not a plus), you will have to use 9600;
Xotherwise you should be able to use 38400.
X
XYou need to add an entry in /etc/printcap.  Here's the entry I use:
X
Xlp|ps:\
X	:br#38400:lp=/dev/ttya:mx#0:sf:sh:rw:\
X	:fc#0177777:fs#003:ms=-isig,igncr,cstopb,-echok:\
X	:af=/usr/adm/psacct:lf=/usr/adm/pslog:sd=/usr/spool/pslpd:\
X	:if=/usr/local/lib/psif:
X
XThis entry would be appropriate if you were using /dev/ttya and a baud
Xrate of 38400.  You need to create the spool directory
X(/usr/spool/pslpd), the accounting file (/usr/adm/psacct), and the log
Xfile (/usr/adm/pslog).  The spool directory and the accounting file
Xshould be owned by daemon, the log file by root. You can use other
Xnames if you want.  I believe the `ms' capabability is a Sun
Xextension, so if you're not using a Sun you'll have to remove it.
X
XYou can add easily add other filters. For example, suppose you
Xwant to add a filter for dvi files. Then add an entry to /etc/printcap:
X
X  :df=/usr/local/lib/psdf:
X
XThen create a shell script /usr/local/lib/psdf
X
X#!/bin/sh
X/usr/local/bin/dvitops | /usr/local/lib/lprps $*
X
XReplace `/usr/local/bin/dvitops' by the name of your favourite dvi to
Xps program (it must be able to read from the standard input). Then you
Xcan print dvi files with `lpr -d'.
X
XYou must also set the printer's communication parameters. Make sure
Xyou have an entry like this in /etc/remote:
X
X  ttya:dv=/dev/ttya:br#1200:el=^D:
X
XSet the switch on your printer to position labelled 1200 or 0. Then 
X
X  tip ttya
X
X(*)Now carefully type
X
X  executive
X
Xand then RETURN. The printer will not echo this while you are typing.
XIf you typed it correctly, the printer will print a banner and a
Xprompt.  If you get an error message from the printer, type CTRL-D and
Xtry again.  If you don't get any response at all, you probably have a
Xcable problem. Then type
X
X  serverdict begin 0 exitserver
X
Xand RETURN. The printer should say something like
X
X  %%[ exitserver: permanent state may be changed ]%%
X
XThen type
X
X  statusdict begin 25 38400 3 setsccbatch end
X
Xand RETURN. The printer will not echo this. If you get an error message,
Xtype CTRL-D and go back to (*). Otherwise type CTRL-D.
X
XNow check to see that this worked. Type
X
X  executive 
X
Xagain. Then
X
X  statusdict begin 25 sccbatch end = = 
X
XThe printer should say
X
X  3
X  38400
X
XIf it does, type CTRL-D, exit tip, and set the switch on the printer
Xback to the position labelled 9600 or 1.  If not, type CTRL-D and try
Xagain from (*).
X
X$Header: /usr/jjc/lprps/RCS/INSTALL,v 1.4 90/12/18 11:33:19 jjc Rel $
END_OF_FILE
if test 2742 -ne `wc -c <'INSTALL'`; then
    echo shar: \"'INSTALL'\" unpacked with wrong size!
fi
# end of 'INSTALL'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1645 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# $Header: /usr/jjc/lprps/RCS/Makefile,v 1.3 90/12/18 10:07:22 jjc Rel $
X# Define A4 if you use A4 rather than letter size paper.
XDEFINES=-DA4
X# Where to install public executables.
XBINDIR=/usr/local/bin
X# Where to install private executables.
XLIBDIR=/usr/local/lib
X# Define REV_COMMAND to be empty if documents don't need to
X# be printed in reverse order.
XREV_COMMAND=$(BINDIR)/psrev |
X# Where to install the filter for text files.
XTEXT_FILTER=$(LIBDIR)/psif-text
X# Where to install the filter for PostScript files.
XPS_FILTER=$(LIBDIR)/psif-ps
X# Filter to convert text to PostScript.  You can use your own instead.
X# It must be able to read from standard input.
XTEXT_TO_PS=$(BINDIR)/textps
XCC=cc
XCFLAGS=-g -Bstatic $(DEFINES)
XINSTALL=install
X
XSOURCES=README INSTALL Makefile psrev.c lprps.c psif.c textps.c
X
Xall: psrev psif lprps textps psif-text psif-ps
X
Xinstall: all
X	$(INSTALL) psif lprps $(LIBDIR)
X	$(INSTALL) textps psrev $(BINDIR)
X	$(INSTALL) psif-text $(TEXT_FILTER)
X	$(INSTALL) psif-ps $(PS_FILTER)
X	@echo Now edit /etc/printcap
X
Xlprps: lprps.c
X	$(CC) $(CFLAGS) -o $@ $<
X
Xpsif: psif.c
X	$(CC) $(CFLAGS) -DTEXT_FILTER=\"$(TEXT_FILTER)\" \
X	-DPS_FILTER=\"$(PS_FILTER)\" -o $@ $<
X
Xtextps: textps.c
X	$(CC) $(CFLAGS) -o $@ $<
X
Xpsrev: psrev.c
X	$(CC) $(CFLAGS) -o $@ $<
X
Xpsif-text: Makefile
X	@echo Creating $@
X	@echo "#! /bin/sh" > $@
X	@echo "$(TEXT_TO_PS) | $(REV_COMMAND) $(LIBDIR)/lprps \$$*" >>$@
X	@chmod +x $@
X
Xpsif-ps: Makefile
X	@echo Creating $@
X	@echo "#! /bin/sh" > $@
X	@echo "$(REV_COMMAND) $(LIBDIR)/lprps \$$*" >>$@
X	@chmod +x $@
X
Xlprps.shar: $(SOURCES)
X	shar $(SOURCES) >$@
X
Xclean:
X	rm -f psrev psif lprps textps psif-text psif-ps
END_OF_FILE
if test 1645 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'psrev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'psrev.c'\"
else
echo shar: Extracting \"'psrev.c'\" \(6626 characters\)
sed "s/^X//" >'psrev.c' <<'END_OF_FILE'
X/* psrev.c */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /usr/jjc/lprps/RCS/psrev.c,v 1.2 90/12/18 09:58:35 jjc Rel $";
X#endif
X
X#include <stdio.h>
X#include <ctype.h>
X
Xchar *malloc();
Xchar *realloc();
X
Xchar *xmalloc();
Xchar *xrealloc();
Xchar *prog;
X
Xtypedef struct line_buf {
X  char *buf;
X  int len;
X  int size;
X} line_buf;
X
Xint get_line(lb, fp)
Xline_buf *lb;
XFILE *fp;
X{
X  int left;
X  char *ptr;
X  if (lb->buf == NULL) {
X    lb->size = 16;
X    lb->buf = xmalloc(16);
X  }
X  ptr = lb->buf;
X  left = lb->size - 1;
X  for (;;) {
X    int c = getc(fp);
X    if (c == EOF) {
X      if (ferror(fp))
X	return 0;
X      if (ptr == lb->buf)
X	return 0;
X      lb->len = ptr - lb->buf;
X      *ptr++ = '\0';
X      return 1;
X    }
X    if (left <= 0) {
X      int n = ptr - lb->buf;
X      lb->size *= 2;
X      lb->buf = xrealloc(lb->buf, lb->size);
X      left = lb->size - n - 1;
X      ptr = lb->buf + n;
X    }
X    *ptr++ = c;
X    left -= 1;
X    if (c == '\n') {
X      lb->len = ptr - lb->buf;
X      *ptr++ = '\0';
X      return 1;
X    }
X  }
X}
X
Xvoid put_line(lb, fp)
Xline_buf *lb;
XFILE *fp;
X{
X  fwrite(lb->buf, 1, lb->len, fp);
X}
X
X/* is s2 a prefix of s1? */
Xint strprefix(s1, s2)
Xchar *s1, *s2;
X{
X  for (; *s1 != '\0' && *s1 == *s2; s1++, s2++)
X    ;
X  return *s2 == '\0';
X}
X
Xvoid copy_and_exit(fp)
XFILE *fp;
X{
X  int c;
X  while ((c = getc(fp)) != EOF)
X    putchar(c);
X  exit(0);
X}
X
Xtypedef struct page_list {
X  long pos;
X  struct page_list *next;
X} page_list;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int dont_reverse = 0;
X  int pageno;
X  int pending_line = 0;
X  int had_pages_comment = 0;
X  int pages_comment_atend = 0;
X  int npages = -1;
X  int page_order;
X  int had_page_order;
X  FILE *tempfp = NULL;
X  page_list *pl = 0;
X  long trailer_pos = -1;
X  long prev_pos;
X  int level = 0;
X  line_buf lb;
X  prog = argv[0];
X  lb.buf = 0;
X  if (!get_line(&lb, stdin))
X    exit(0);
X  put_line(&lb, stdout);
X  if (!strprefix(lb.buf, "%!PS-Adobe-"))
X    copy_and_exit(stdin);
X
X  /* process the header section */
X  while (get_line(&lb, stdin)) {
X    int suppress = 0;
X    if (!strprefix(lb.buf, "%%")) {
X      pending_line = 1;
X      break;
X    }
X    else if (strprefix(lb.buf, "%%Pages:")) {
X      suppress = 1;		/* don't print it yet */
X      /* the first %%Pages comment is the significant one */
X      if (!had_pages_comment) {
X	char *ptr = lb.buf + 8;
X	while (*ptr == ' ')
X	  ptr++;
X	had_pages_comment = 1;
X	if (strprefix(ptr, "(atend)"))
X	  pages_comment_atend = 1;
X	else {
X	  if (sscanf(ptr, "%d %d", &npages, &page_order) == 2)
X	    had_page_order = 1;
X	}
X      }
X    }
X    if (strprefix(lb.buf, "%%EndComments"))
X      break;
X    if (!suppress)
X      put_line(&lb, stdout);
X  }
X
X  if (had_pages_comment) {
X    if (pages_comment_atend)
X      printf("%%%%Pages: (atend)\n");
X    else if (had_page_order) {
X      switch (page_order) {
X      case 1:
X	printf("%%%%Pages: %d -1\n", npages);
X	break;
X      case -1:
X	dont_reverse = 1;
X	printf("%%%%Pages: %d -1\n", npages);
X	break;
X      case 0:
X	/* what should we do here? */
X      default:
X	printf("%%%%Pages: %d %d\n", npages, page_order);
X	break;
X      }
X    }
X    else if (npages >= 0)
X      printf("%%%%Pages: %d\n", npages);
X  }
X  else
X    dont_reverse = 1;
X  
X  printf("%%%%EndComments\n");
X
X  if (dont_reverse)
X    copy_and_exit(stdin);
X
X  /* process the prologue */
X  while (pending_line || get_line(&lb, stdin)) {
X    pending_line = 0;
X    if (strprefix(lb.buf, "%%BeginDocument"))
X      ++level;
X    else if (strprefix(lb.buf, "%%EndDocument")) {
X      if (level > 0)
X	--level;
X    }
X    else if (level == 0 && strprefix(lb.buf, "%%Page:")) {
X      pending_line = 1;
X      break;
X    }
X    put_line(&lb, stdout);
X  }
X
X  /* if we didn't find any %%Page comments, we're done */
X  if (!pending_line)
X    exit(0);
X
X  /* open a temporary file if necessary */
X  if (ftell(stdin) == -1) {
X    tempfp = tmpfile();
X    clearerr(stdin);
X  }
X
X  /* process the body */
X  while (pending_line || get_line(&lb, stdin)) {
X    pending_line = 0;
X    if (strprefix(lb.buf, "%%BeginDocument"))
X      ++level;
X    else if (strprefix(lb.buf, "%%EndDocument")) {
X      if (level > 0)
X	--level;
X    }
X    else if (level == 0) {
X      if (strprefix(lb.buf, "%%Page:")) {
X	page_list *tem = (page_list *)xmalloc(sizeof(page_list));
X	tem->next = pl;
X	tem->pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
X	pl = tem;
X      }
X      else if (strprefix(lb.buf, "%%Trailer")) {
X	pending_line = 1;
X	break;
X      }
X    }
X    if (tempfp != NULL)
X      put_line(&lb, tempfp);
X  }
X
X  /* process the trailer */
X  if (pending_line) {
X    trailer_pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
X    while (pending_line || get_line(&lb, stdin)) {
X      pending_line = 0;
X      if (pages_comment_atend && strprefix(lb.buf, "%%Pages:")) {
X	int npages, page_order;
X	if (sscanf(lb.buf + 8, "%d %d", &npages, &page_order) == 2
X	    && page_order == -1)
X	  dont_reverse = 1;
X	else
X	  dont_reverse = 0;
X      }
X      if (tempfp != NULL)
X	put_line(&lb, tempfp);
X    }
X  }
X
X  if (tempfp == NULL)
X    tempfp = stdin;
X
X  if (dont_reverse) {
X    long first_page_pos;
X    if (pl == NULL)
X      abort();
X    /* find the position of the first page */
X    while (pl != NULL) {
X      page_list *tem = pl;
X      first_page_pos = pl->pos;
X      pl = pl->next;
X      free((char *)tem);
X    }
X    fseek(tempfp, first_page_pos, 0);
X    copy_and_exit(tempfp);
X  }
X
X  /* output each page */
X  prev_pos = trailer_pos == -1 ? ftell(tempfp) : trailer_pos;
X  pageno = 1;
X  while (pl != NULL) {
X    char *ptr, *label;
X    int count = prev_pos - pl->pos;
X    fseek(tempfp, pl->pos, 0);
X    if (!get_line(&lb, tempfp))
X      abort();
X    if (!strprefix(lb.buf, "%%Page:"))
X      abort();
X    ptr = lb.buf + 7;
X    while (*ptr == ' ')
X      ptr++;
X    label = ptr;
X    while (*ptr != '\0' && !(isascii(*ptr) && isspace(*ptr)))
X      ptr++;
X    *ptr = '\0';
X    if (*label == '\0')
X      label = "?";
X    printf("%%%%Page: %s %d\n", label, pageno);
X    pageno += 1;
X    count -= lb.len;
X    while (--count >= 0) {
X      int c = getc(tempfp);
X      if (c == EOF)
X	abort();
X      putc(c, stdout);
X    }
X    prev_pos = pl->pos;
X    pl = pl->next;
X  }
X
X  /* output the trailer if there is one */
X  if (trailer_pos != -1) {
X    fseek(tempfp, trailer_pos, 0);
X    copy_and_exit(tempfp);
X  }
X
X  exit(0);
X}
X
Xchar *xmalloc(size)
Xint size;
X{
X  char *tem;
X  if ((tem = malloc(size)) == NULL) {
X    fprintf(stderr, "%s: out of memory\n", prog);
X    exit(1);
X  }
X  return tem;
X}
X
Xchar *xrealloc(ptr, size)
Xchar *ptr;
Xint size;
X{
X  char *tem;
X  if ((tem = realloc(ptr, size)) == NULL) {
X    fprintf(stderr, "%s: out of memory\n", prog);
X    exit(1);
X  }
X  return tem;
X}
END_OF_FILE
if test 6626 -ne `wc -c <'psrev.c'`; then
    echo shar: \"'psrev.c'\" unpacked with wrong size!
fi
# end of 'psrev.c'
fi
if test -f 'lprps.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lprps.c'\"
else
echo shar: Extracting \"'lprps.c'\" \(12676 characters\)
sed "s/^X//" >'lprps.c' <<'END_OF_FILE'
X/* lprps.c */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /usr/jjc/lprps/RCS/lprps.c,v 1.7 90/12/18 10:07:24 jjc Rel $";
X#endif
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#include <sys/file.h>
X#include <fcntl.h>
X#include <sys/time.h>
X#include <signal.h>
X#include <syslog.h>
X#include <errno.h>
X
X#define EXIT_SUCCESS 0
X#define EXIT_REPRINT 1
X#define EXIT_THROW_AWAY 2
X
X#define OBSIZE 1024
X#define IBSIZE 1024
X
Xchar *mktemp();
Xchar *sprintf(); /* sigh */
X
Xchar *login;
Xchar *host;
Xchar *accounting_file;
XFILE *mailfp;
Xint interrupt_flag = 0;
Xint timeout_flag = 0;
Xint psfd;
X/* number of 004s received from printer */
Xint eof_count = 0;
X/* if non-zero ignore all input from printer other than 004s */
Xint ignore_input = 0;
X/* are we currently printing the users job */
Xint in_job = 0;
X
Xenum {
X  NORMAL,
X  HAD_ONE_PERCENT,
X  HAD_TWO_PERCENT,
X  IN_MESSAGE,
X  HAD_RIGHT_BRACKET,
X  HAD_RIGHT_BRACKET_AND_PERCENT
X  } parse_state;
X
Xenum {
X  INVALID,
X  UNKNOWN,
X  IDLE,
X  BUSY,
X  WAITING
X  } status = INVALID;
X
Xint start_pagecount = -1;
Xint end_pagecount = -1;
X
Xstruct {
X  char *ptr;
X  int count;
X  char buf[OBSIZE];
X} out = { out.buf, OBSIZE };
X
X#define MBSIZE 1024
X
Xchar message_buf[MBSIZE];
Xint message_buf_i;
X
Xstatic char temp_file[] = "/tmp/lprpsXXXXXX";
X
Xstatic char pagecount_string[] = "(%%[ pagecount: ) print \
Xstatusdict begin pagecount end 20 string cvs print \
X( ]%%) print flush\n";
X
Xvoid process_input_char();
Xvoid printer_flushing();
Xvoid handle_interrupt();
Xvoid do_exit();
X
Xvoid handle_timeout()
X{
X  syslog(LOG_ERR, "printer not responding");
X  sleep(60);		/* it will take at least this long to warm up */
X  do_exit(EXIT_REPRINT);
X}
X
Xvoid sys_error(s)
Xchar *s;
X{
X  syslog(LOG_ERR, "%s: %m", s);
X  exit(EXIT_THROW_AWAY);
X}
X
Xint blocking_flag = 1;
X
Xvoid set_blocking()
X{
X  if (!blocking_flag) {
X    if (fcntl(psfd, F_SETFL, 0) == -1)
X      sys_error("fcntl");
X    blocking_flag = 1;
X  }
X}
X
Xvoid set_non_blocking()
X{
X  if (blocking_flag) {
X    if (fcntl(psfd, F_SETFL, FNDELAY) == -1)
X      sys_error("fcntl");
X    blocking_flag = 0;
X  }
X}
X
Xvoid blocking_write(s, n)
Xchar *s;
Xint n;
X{
X  set_blocking();
X  if (write(psfd, s, n) == -1)
X    sys_error("write");
X}
X
Xvoid ioflush()
X{
X  int rw = FREAD|FWRITE;
X  if (ioctl(psfd, TIOCFLUSH, &rw) == -1)
X    sys_error("ioctl(TIOCFLUSH)");
X}
X
Xvoid open_mailfp()
X{
X  if (mailfp == 0) {
X    (void)mktemp(temp_file);
X    if ((mailfp = fopen(temp_file, "w")) == NULL)
X      sys_error("open");
X  }
X}
X
Xvoid user_char(c)
Xchar c;
X{
X  static int done_intro = 0;
X  if (in_job && (done_intro || c != '\n')) {
X    if (mailfp == 0)
X      open_mailfp();
X    if (!done_intro) {
X      fputs("Your PostScript printer job produced the following output:\n", 
X	    mailfp);
X      done_intro = 1;
X    }
X    (void)putc(c, mailfp);
X  }
X}
X
X#if 0
Xvoid init_tty()
X{
X  struct termios t;
X  psfd = open("/dev/ttya", O_RDWR);
X  if (psfd == -1)
X    sys_error("open");
X  if (ioctl(psfd, TCGETS, &t) == -1)
X    sys_error("ioctl(TCGETS)");
X  t.c_cflag = B38400|CS7|CSTOPB|CREAD|CLOCAL|PARENB;
X  t.c_oflag &= ~OPOST;
X  t.c_iflag = IXON|IXOFF|IGNBRK|ISTRIP|IGNCR;
X  t.c_lflag = 0;
X  t.c_cc[VMIN] = 1;
X  t.c_cc[VTIME] = 0;
X  if (ioctl(psfd, TCSETS, &t) == -1)
X    sys_error("ioctl(TCSETS)");
X}
X
Xvoid debug_tty()
X{
X  struct termios t;
X  if (ioctl(psfd, TCGETS, &t) == -1)
X    sys_error("ioctl(TCGETS)");
X  syslog(LOG_ERR, "cflag = %o", t.c_cflag);
X  syslog(LOG_ERR, "oflag = %o", t.c_oflag);
X  syslog(LOG_ERR, "lflag = %o", t.c_lflag);
X  syslog(LOG_ERR, "iflag = %o", t.c_iflag);
X}
X#endif
X
Xvoid do_exit(exit_code)
Xint exit_code;
X{
X  if (mailfp != NULL) {
X    char command[1024];
X    if (fclose(mailfp) == EOF)
X      sys_error("fclose");
X    (void)sprintf(command, "/usr/ucb/mail -s \"printer job\" %s@%s <%s",
X	    login, host, temp_file);
X    (void)system(command);
X    (void)unlink(temp_file);
X  }
X  exit(exit_code);
X}
X  
Xvoid flush_output()
X{
X  char ibuf[IBSIZE];
X  char *p = out.buf;
X  int n = out.ptr - p;
X  /* we daren't block on writes */
X  set_non_blocking();
X  while (n > 0) {
X    fd_set rfds, wfds;
X    FD_ZERO(&wfds);
X    FD_ZERO(&rfds);
X    FD_SET(psfd, &wfds);
X    FD_SET(psfd, &rfds);
X    if (interrupt_flag)
X      handle_interrupt();
X    while (select(psfd + 1, &rfds, &wfds, (fd_set *)NULL, (struct timeval *)NULL)
X	   == -1)
X      if (errno == EINTR) {
X	if (timeout_flag)
X	  handle_timeout();
X	else if (interrupt_flag)
X	  handle_interrupt();
X      }
X      else
X	sys_error("select");
X    if (FD_ISSET(psfd, &rfds)) {
X      char *q = ibuf;
X      int nread = read(psfd, ibuf, IBSIZE);
X      if (nread == -1)
X	sys_error("read");
X      while (--nread >= 0)
X	process_input_char(*q++);
X    }
X    else if (FD_ISSET(psfd, &wfds)) {
X      int nwritten = write(psfd, p, n);
X      if (nwritten == -1)
X	sys_error("write");
X      n -= nwritten;
X      p += nwritten;
X    }
X  }
X  out.ptr = out.buf;
X  out.count = OBSIZE;
X}
X
X  
Xvoid output_char(c)
Xchar c;
X{
X  if (out.count <= 0)
X    flush_output();
X  *out.ptr = c;
X  out.ptr += 1;
X  out.count -= 1;
X}
X
Xvoid message_char(c)
Xchar c;
X{
X  if (c != '\0' && message_buf_i < MBSIZE - 1)
X    message_buf[message_buf_i++] = c;
X}
X
Xvoid process_message()
X{
X  char *p;
X  message_buf[message_buf_i] = 0;
X  for (p = strtok(message_buf, ";"); p != NULL; p = strtok((char *)NULL, ";")) {
X    char *key;
X    while (isspace(*p))
X      p++;
X    key = p;
X    p = strchr(p, ':');
X    if (p != NULL) {
X      char *q;
X      *p++ = '\0';
X      while (isspace(*p))
X	p++;
X      q = strchr(p, '\0');
X      while (q > p && isspace(q[-1]))
X	--q;
X      *q = '\0';
X      if (strcmp(key, "Flushing") == 0)
X	printer_flushing();
X      else if (strcmp(key, "PrinterError") == 0) {
X	syslog(LOG_ERR, "printer error: %s", p);
X      }
X      else if (strcmp(key, "exitserver") == 0) {
X      }
X      else if (strcmp(key, "Error") == 0) {
X	if (in_job) {
X	  if (mailfp == 0)
X	    open_mailfp();
X	  (void)fprintf(mailfp, 
X			"Your PostScript printer job produced the error `%s'.\n",
X			p);
X	}
X      }
X      else if (strcmp(key, "status") == 0) {
X	if (strcmp(p, "idle") == 0)
X	  status = IDLE;
X	else if (strcmp(p, "busy") == 0)
X	  status = BUSY;
X	else if (strcmp(p, "waiting") == 0)
X	  status = WAITING;
X	else
X	  status = UNKNOWN;
X      }
X      else if (strcmp(key, "OffendingCommand") == 0) {
X	if (in_job) {
X	  if (mailfp == 0)
X	    open_mailfp();
X	  (void)fprintf(mailfp, "The offending command was `%s'.\n", p);
X	}
X      }
X      else if (strcmp(key, "pagecount") == 0) {
X	int n;
X	if (sscanf(p, "%d", &n) == 1 && n >= 0) {
X	  if (start_pagecount < 0)
X	    start_pagecount = n;
X	  else
X	    end_pagecount = n;
X	}
X      }
X    }
X  }
X}
X
X
Xvoid process_input_char(c)
Xchar c;
X{
X  if (c == '\004')
X    ++eof_count;
X  else if (ignore_input) {
X  }
X  else {
X    switch (parse_state) {
X    case NORMAL:
X      if (c == '%')
X	parse_state = HAD_ONE_PERCENT;
X      else
X	user_char(c);
X      break;
X    case HAD_ONE_PERCENT:
X      if (c == '%')
X	parse_state = HAD_TWO_PERCENT;
X      else {
X	user_char('%');
X	user_char(c);
X	parse_state = NORMAL;
X      }
X      break;
X    case HAD_TWO_PERCENT:
X      if (c == '[') {
X	message_buf_i = 0;
X	parse_state = IN_MESSAGE;
X      }
X      else {
X	user_char('%');
X	user_char('%');
X	user_char(c);
X	parse_state = NORMAL;
X      }
X      break;
X    case IN_MESSAGE:
X      if (c == ']')
X	parse_state = HAD_RIGHT_BRACKET;
X      else
X	message_char(c);
X      break;
X    case HAD_RIGHT_BRACKET:
X      if (c == '%')
X	parse_state = HAD_RIGHT_BRACKET_AND_PERCENT;
X      else {
X	message_char(']');
X	message_char(c);
X	parse_state = IN_MESSAGE;
X      }
X      break;
X    case HAD_RIGHT_BRACKET_AND_PERCENT:
X      if (c == '%') {
X	parse_state = NORMAL;
X	process_message();
X      }
X      else {
X	message_char(']');
X	message_char('%');
X	message_char(c);
X	parse_state = IN_MESSAGE;
X      }
X      break;
X    default:
X      abort();
X    }
X  }
X}
X
X
Xvoid process_some_input()
X{
X  char ibuf[IBSIZE];
X  char *p = ibuf;
X  int nread;
X  fd_set rfds, wfds;
X  set_non_blocking();
X  FD_ZERO(&wfds);
X  FD_ZERO(&rfds);
X  FD_SET(psfd, &rfds);
X  if (interrupt_flag)
X    handle_interrupt();
X  if (timeout_flag)
X    handle_timeout();
X  /* select is not restarted if interrupted, whereas read is */
X  while (select(psfd + 1, &rfds, &wfds, (fd_set *)NULL, (struct timeval *)NULL) 
X	 == -1)
X    if (errno == EINTR) {
X      if (timeout_flag)
X	handle_timeout();
X      else if (interrupt_flag)
X	handle_interrupt();
X    }
X    else
X      sys_error("select");
X  nread = read(psfd, ibuf, IBSIZE);
X  if (nread == -1)
X    sys_error("read");
X  if (nread == 0)
X    sys_error("read returned 0");
X  while (--nread >= 0)
X    process_input_char(*p++);
X}
X
X
Xvoid do_accounting()
X{
X  FILE *fp;
X  if (end_pagecount > start_pagecount
X      && accounting_file != NULL
X      && (fp = fopen(accounting_file, "a")) != NULL) {
X    (void)fprintf(fp,
X	    "%7.2f %s:%s\n", 
X	    (double)(end_pagecount - start_pagecount),
X	    host,
X	    login);
X    if (fclose(fp) == EOF)
X      sys_error("fclose");
X  }
X}
X
Xvoid set_timeout_flag()
X{
X  timeout_flag = 1;
X}
X
Xvoid get_end_pagecount()
X{
X  char c;
X  int ec;
X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
X    sys_error("signal");
X  (void)alarm(30);
X  ioflush();
X  blocking_write(pagecount_string, sizeof(pagecount_string) - 1);
X  end_pagecount = -1;
X  ignore_input = 0;
X  in_job = 0;
X  parse_state = NORMAL;
X  while (end_pagecount < 0)
X    process_some_input();
X  c = '\004';
X  blocking_write(&c, 1);
X  ec = eof_count;
X  while (ec == eof_count)
X    process_some_input();
X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
X    sys_error("signal");
X}
X
Xvoid get_start_pagecount()
X{
X  char c;
X  int ec;
X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
X    sys_error("signal");
X  (void)alarm(30);
X  ioflush();
X  blocking_write(pagecount_string, sizeof(pagecount_string) - 1);
X  start_pagecount = -1;
X  parse_state = NORMAL;
X  in_job = 0;
X  ignore_input = 0;
X  while (start_pagecount < 0)
X    process_some_input();
X  c = '\004';
X  blocking_write(&c, 1);
X  ec = eof_count;
X  while (ec == eof_count)
X    process_some_input();
X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
X    sys_error("signal");
X}
X
Xvoid set_interrupt_flag()
X{
X  interrupt_flag = 1;
X}
X
Xvoid handle_interrupt()
X{
X  static char interrupt_string[] = "\003\004";
X  int ec;
X  interrupt_flag = 0;
X  if (signal(SIGINT, SIG_IGN) == BADSIG)
X    sys_error("signal");
X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
X    sys_error("signal");
X  (void)alarm(30);
X  ioflush();
X  blocking_write(interrupt_string, sizeof(interrupt_string)-1);
X  ignore_input = 1;
X  ec = eof_count;
X  while (eof_count == ec)
X    process_some_input();
X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
X    sys_error("signal");
X  get_end_pagecount();
X  do_accounting();
X  do_exit(EXIT_SUCCESS);
X}
X
Xvoid printer_flushing()
X{
X  int ec;
X  char c = '\004';
X  if (signal(SIGINT, SIG_IGN) == BADSIG)
X    sys_error("signal");
X  ioflush();
X  blocking_write(&c, 1);
X  ignore_input = 1;
X  ec = eof_count;
X  while (eof_count == ec)
X    process_some_input();
X  get_end_pagecount();
X  do_accounting();
X  do_exit(EXIT_SUCCESS);
X}
X
Xvoid send_file()
X{
X  char c;
X  int ec;
X  in_job = 1;
X  parse_state = NORMAL;
X  ignore_input = 0;
X  if (signal(SIGINT, set_interrupt_flag) == BADSIG)
X    sys_error("signal");
X  while ((c = getchar()) != EOF)
X    output_char(c);
X  flush_output();
X  c = '\004';
X  blocking_write(&c, 1);
X  ec = eof_count;
X  while (ec == eof_count)
X    process_some_input();
X}
X
Xvoid get_status()
X{
X  char c = '\024';
X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
X    sys_error("signal");
X  ioflush();
X  (void)alarm(5);
X  blocking_write(&c, 1);
X  in_job = 0;
X  parse_state = NORMAL;
X  ignore_input = 0;
X  while (status == INVALID)
X    process_some_input();
X  switch (status) {
X  case IDLE:
X    break;
X  case WAITING:
X    c = '\004';
X    blocking_write(&c, 1);
X    sleep(5);
X    exit(EXIT_REPRINT);
X  case BUSY:
X  case UNKNOWN:
X    sleep(15);
X    exit(EXIT_REPRINT);
X  }
X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
X    sys_error("signal");
X}
X
Xvoid usage()
X{
X  syslog(LOG_ERR, "usage");
X  exit(EXIT_THROW_AWAY);
X}
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int i = 1;
X  openlog("lprps", LOG_PID, LOG_LPR);
X  while (i < argc && argv[i][0] == '-') {
X    switch (argv[i][1]) {
X    case 'c':
X      break;
X    case 'x':
X    case 'y':
X    case 'w':
X    case 'l':
X    case 'i':
X      break;
X    case 'n':
X      if (++i == argc)
X	usage();
X      else
X	login = argv[i];
X      break;
X    case 'h':
X      if (++i == argc)
X	usage();
X      else
X	host = argv[i];
X
X      break;
X    default:
X      usage();
X    }
X    ++i;
X  }
X  if (i < argc)
X    accounting_file = argv[i];
X  psfd = 1;
X  get_status();
X  get_start_pagecount();
X  send_file();
X  get_end_pagecount();
X  do_accounting();
X  do_exit(EXIT_SUCCESS);
X}
X
END_OF_FILE
if test 12676 -ne `wc -c <'lprps.c'`; then
    echo shar: \"'lprps.c'\" unpacked with wrong size!
fi
# end of 'lprps.c'
fi
if test -f 'psif.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'psif.c'\"
else
echo shar: Extracting \"'psif.c'\" \(2010 characters\)
sed "s/^X//" >'psif.c' <<'END_OF_FILE'
X/* psif.c */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /usr/jjc/lprps/RCS/psif.c,v 1.2 90/12/18 09:59:45 jjc Rel $";
X#endif
X
X#include <stdio.h>
X#include <string.h>
X#include <memory.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X
Xlong lseek();
X
X#ifndef TEXT_FILTER
X#define TEXT_FILTER "/usr/local/lib/psif-text"
X#endif /* not TEXT_FILTER */
X
X#ifndef PS_FILTER
X#define PS_FILTER "/usr/local/lib/psif-ps"
X#endif /* not PS_FILTER */
X
X#ifndef ERROR_EXIT_CODE
X#define ERROR_EXIT_CODE 1
X#endif /* not ERROR_EXIT_CODE */
X
Xchar *prog;
X
Xvoid sys_error(s)
Xchar *s;
X{
X  if (prog)
X    (void)fprintf(stderr, "%s: ", prog);
X  perror(s);
X  exit(ERROR_EXIT_CODE);
X}
X
X/* ARGSUSED */
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X  char buf[BUFSIZ];
X  char *command;
X  int nread;
X  struct stat statb;
X  prog = argv[0];
X  if ((nread = read(0, buf, 2)) < 0)
X    sys_error("read");
X  if (nread != 2 || buf[0] != '%' || buf[1] != '!')
X    command = TEXT_FILTER;
X  else
X    command = PS_FILTER;
X  if (fstat(0, &statb) < 0)
X    sys_error("fstat");
X  if ((statb.st_mode & S_IFMT) != S_IFREG) {
X    /* this happens with lpr -p */
X    int pid;
X    int fd[2];
X    if (pipe(fd) < 0)
X      sys_error("pipe");
X    if ((pid = fork()) < 0)
X      sys_error("fork");
X    else if (pid == 0) {
X      /* in the child */
X      int d;
X      if (close(fd[0]) < 0)
X	sys_error("close");
X      d = fd[1];
X      if (nread != 0) {
X	if (write(d, buf, nread) < 0)
X	  sys_error("write");
X	while ((nread = read(0, buf, sizeof(buf))) > 0)
X	  if (write(d, buf, nread) < 0)
X	    sys_error("write");
X	if (nread < 0)
X	  sys_error("read");
X      }
X      if (close(d) < 0)
X	sys_error("close");
X      exit(0);
X    }
X    if (close(fd[1]) < 0)
X      sys_error("close");
X    if (close(0) < 0)
X      sys_error("close");
X    if (dup(fd[0]) < 0)
X      sys_error("dup");
X    if (close(fd[0]) < 0)
X      sys_error("close");
X  }
X  else {
X    if (lseek(0, (off_t)0, L_SET) < 0)
X      sys_error("lseek");
X  }
X  execv(command, argv);
X  sys_error("execv");
X}
END_OF_FILE
if test 2010 -ne `wc -c <'psif.c'`; then
    echo shar: \"'psif.c'\" unpacked with wrong size!
fi
# end of 'psif.c'
fi
if test -f 'textps.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'textps.c'\"
else
echo shar: Extracting \"'textps.c'\" \(6635 characters\)
sed "s/^X//" >'textps.c' <<'END_OF_FILE'
X/* textps.c */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /usr/jjc/lprps/RCS/textps.c,v 1.2 90/12/18 10:01:58 jjc Rel $";
X#endif
X
X#include <stdio.h>
X#include <ctype.h>
X
Xextern char *malloc();
Xextern char *optarg;
Xextern int optind;
X
Xtypedef struct output_char {
X  struct output_char *next;
X  char c;
X  char is_bold;
X  int pos;
X} output_char;
X
Xoutput_char *free_output_char_list = 0;
X
Xint tab_width = 8;
Xint lines_per_page = 66;
X#ifdef A4
Xint page_length = 842;		/* in points */
X#else
Xint page_length = 792;		/* in points */
X#endif
X
Xint baseline_offset = 8;	/* distance in points from top of page to */
X				/* first baseline */
X
Xint line_spacing;		/* in points */
X
Xint left_margin = 18;		/* in points */
Xint char_width;
X
Xint pageno = 0;
X
Xchar *font = "Courier";
Xchar *bold_font = "Courier-Bold";
Xenum { NONE, ROMAN, BOLD } current_font;
X
Xvoid do_file();
Xvoid prologue();
Xvoid trailer();
Xchar *prog;
X
Xvoid usage()
X{
X  fprintf(stderr, "usage: %s [-l n] [ files ... ]\n", prog);
X  exit(1);
X}
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int bad_files = 0;
X  int cpi = 12;			/* characters per inch */
X  int lpi = 6;			/* lines per inch */
X  int opt;
X
X  prog = argv[0];
X
X  while ((opt = getopt(argc, argv, "l:")) != EOF)
X    switch (opt) {
X    case 'l':
X      if (sscanf(optarg, "%d", &lines_per_page) != 1)
X	usage();
X      break;
X    case '?':
X      usage();
X    default:
X      abort();
X    }
X
X  char_width = 72/cpi;
X  line_spacing = 72/lpi;
X  prologue();
X  if (optind >= argc)
X    do_file(stdin);
X  else {
X    int i;
X    for (i = optind; i < argc; i++)
X      if (strcmp(argv[i], "-") == 0)
X	do_file(stdin);
X      else {
X	FILE *fp;
X	if ((fp = fopen(argv[i], "r")) == NULL) {
X	  perror(argv[i]);
X	  bad_files++;
X	}
X	else {
X	  do_file(fp);
X	  fclose(fp);
X	}
X      }
X  }
X  trailer();
X  exit(bad_files);
X}
X
X
Xoutput_char *new_output_char()
X{
X  if (free_output_char_list) {
X    output_char *tem = free_output_char_list;
X    free_output_char_list = free_output_char_list->next;
X    return tem;
X  }
X  else {
X    output_char *tem;
X    if ((tem = (output_char *)malloc(sizeof(output_char))) == NULL) {
X      fprintf(stderr, "%s: out of memory\n", prog);
X      exit(1);
X    }
X    return tem;
X  }
X}
X
Xvoid delete_output_char(p)
Xoutput_char *p;
X{
X  p->next = free_output_char_list;
X  free_output_char_list = p;
X}
X
X
Xvoid pschar(c)
Xint c;
X{
X  if (!isascii(c) || iscntrl(c))
X    printf("\\%03o", c &0377);
X  else if (c == '(' || c == ')' || c == '\\') {
X    putchar('\\');
X    putchar(c);
X  }
X  else
X    putchar(c);
X}
X
X/* output_line is ordered greatest position first */
X
Xvoid print_line(output_line, vpos)
Xoutput_char *output_line;
Xint vpos;
X{
X  output_char *rev = output_line;
X  output_line = 0;
X  while (rev != 0) {
X    output_char *tem = rev;
X    rev = rev->next;
X    tem->next = output_line;
X    output_line = tem;
X  }
X  while (output_line != NULL) {
X    output_char *tem;
X    output_char **p = &output_line;
X    int start_pos = output_line->pos;
X    int is_bold = output_line->is_bold;
X    int pos;
X    if (is_bold) {
X      if (current_font != BOLD) {
X	printf("B");
X	current_font = BOLD;
X      }
X    }
X    else {
X      if (current_font != ROMAN) {
X	printf("R");
X	current_font = ROMAN;
X      }
X    }
X    putchar('(');
X    pschar(output_line->c);
X    pos = output_line->pos + 1;
X    tem = output_line;
X    output_line = output_line->next;
X    delete_output_char(tem);
X    for (;;) {
X      while (*p != NULL
X	     && ((*p)->pos < pos || (*p)->is_bold != is_bold))
X	p = &(*p)->next;
X      if (*p == NULL)
X	break;
X      while (pos < (*p)->pos) {
X	pschar(' ');
X	pos++;
X      }
X      pschar((*p)->c);
X      pos++;
X      tem = *p;
X      *p = tem->next;
X      delete_output_char(tem);
X    }
X    putchar(')');
X    printf("%d %d L\n",
X	   left_margin + start_pos*char_width, 
X	   page_length - baseline_offset - vpos*line_spacing);
X  }
X}
X
Xvoid page_start()
X{
X  printf("%%%%Page: ? %d\nPS\n", ++pageno);
X  current_font = NONE;
X}
X
Xvoid page_end()
X{
X  printf("PE\n");
X}
X
Xvoid prologue()
X{
X  printf("%%!PS-Adobe-2.0\n");
X  printf("%%%%DocumentFonts: %s %s\n", font, bold_font);
X  printf("%%%%Pages: (atend)\n");
X  printf("%%%%EndComments\n");
X  printf("/L { moveto show } bind def\n");
X  printf("/R [ /%s findfont %d 6 div scalefont /setfont load ] cvx def\n",
X	 font, char_width*10);
X  printf("/B [ /%s findfont %d 6 div scalefont /setfont load ] cvx def\n", 
X	 bold_font, char_width*10);
X  printf("/PS { /level0 save def } bind def\n");
X  printf("/PE { level0 restore showpage } bind def\n");
X  printf("%%%%EndProlog\n");
X}
X
Xvoid trailer()
X{
X  printf("%%%%Trailer\n%%%%Pages: %d\n", pageno);
X}
X
X/* p is ordered greatest position first */
X
Xvoid add_char(c, pos, p)
Xint c;
Xint pos;
Xoutput_char **p;
X{
X  for (;; p = &(*p)->next) {
X    if (*p == NULL || (*p)->pos < pos) {
X      output_char *tem = new_output_char();
X      tem->next = *p;
X      *p = tem;
X      tem->c = c;
X      tem->is_bold = 0;
X      tem->pos = pos;
X      break;
X    }
X    else if ((*p)->pos == pos) {
X      if (c == (*p)->c) {
X	(*p)->is_bold = 1;
X	break;
X      }
X    }
X  }
X}
X
Xvoid do_file(fp)
XFILE *fp;
X{
X  int c;
X  int vpos = 0;
X  int hpos = 0;
X  int page_started = 0;
X  int esced = 0;
X  output_char *output_line = 0;
X  while ((c = getc(fp)) != EOF)
X    if (esced)
X      switch(c) {
X      case '7':
X	if (vpos > 0) {
X	  if (output_line != NULL) {
X	    if (!page_started) {
X	      page_started = 1;
X	      page_start();
X	    }
X	    print_line(output_line, vpos);
X	    output_line = 0;
X	  }
X	  vpos -= 1;
X	}
X	/* hpos = 0; */
X	esced = 0;
X	break;
X      default:
X	/* silently ignore */
X	esced = 0;
X	break;
X      }
X    else
X      switch (c) {
X      case '\033':
X	esced = 1;
X	break;
X      case '\b':
X	if (hpos > 0)
X	  hpos--;
X	break;
X      case '\f':
X	if (!page_started)
X	  page_start();
X	print_line(output_line, vpos);
X	output_line = 0;
X	page_end();
X	hpos = 0;		/* ?? */
X	vpos = 0;
X	page_started = 0;
X	break;
X      case '\r':
X	hpos = 0;
X	break;
X      case '\n':
X	if (output_line != NULL) {
X	  if (!page_started) {
X	    page_started = 1;
X	    page_start();
X	  }
X	  print_line(output_line, vpos);
X	  output_line = 0;
X	}
X	vpos += 1;
X	if (vpos >= lines_per_page) {
X	  if (!page_started)
X	    page_start();
X	  page_end();
X	  page_started = 0;
X	  vpos = 0;
X	}
X	hpos = 0;
X	break;
X      case ' ':
X	hpos++;
X	break;
X      case '\t':
X	hpos = ((hpos + tab_width)/tab_width)*tab_width;
X	break;
X      default:
X	if (!(isascii(c) && iscntrl(c))) {
X	  add_char(c, hpos, &output_line);
X	  hpos++;
X	}
X	break;
X      }
X  if (output_line != NULL) {
X    if (!page_started) {
X      page_started = 1;
X      page_start();
X    }
X    print_line(output_line, vpos);
X    output_line = 0;
X  }
X  if (page_started)
X    page_end();
X}
END_OF_FILE
if test 6635 -ne `wc -c <'textps.c'`; then
    echo shar: \"'textps.c'\" unpacked with wrong size!
fi
# end of 'textps.c'
fi
echo shar: End of shell archive.
exit 0



More information about the Alt.sources mailing list