From pa.dec.com!decwrl!uunet!sparky!kent Thu Jul 25 08:56:18 PDT 1991 Article: 2525 of comp.sources.misc Newsgroups: comp.sources.misc Path: pa.dec.com!decwrl!uunet!sparky!kent From: James Clark Subject: v21i025: lprps - interface lpr to a PostScript printer, Part01/01 Message-ID: <1991Jul21.232155.4967@sparky.IMD.Sterling.COM> X-Md4-Signature: 921cc1cc7fd3f3a327f22caa14c24810 Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: Sterling Software, IMD Date: Sun, 21 Jul 1991 23:21:55 GMT Approved: kent@sparky.imd.sterling.com Lines: 2477 Submitted-by: James Clark Posting-number: Volume 21, Issue 25 Archive-name: lprps/part01 Environment: SunOS, BSD UNIX This is lprps version 1.1. lprps is a collection of programs for using lpr with a PostScript printer connected by a serial channel. It has been tested mainly with Suns running various versions of SunOS (4.0.3, 4.1 and 4.1.1). It should be easy to port to other 4.3 BSD based systems. It is not intended for use with System V. 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 psrev PostScript page reversal filter See the README for more information. James Clark jjc@jclark.uucp jjc%jclark@uunet.uu.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 'README' <<'END_OF_FILE' XThis is lprps version 1.1. X Xlprps is a collection of programs for using lpr with a PostScript Xprinter connected by a serial channel. It has been tested mainly with XSuns running various versions of SunOS (4.0.3, 4.1 and 4.1.1). It Xshould be easy to port to other 4.3 BSD based systems. It is not Xintended for use with System V. 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 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 in X such a way that you can easily use your favourite text-to-PostScript X filter. X X* Can automatically perform page reversal for the benefit of printers X that stack face-up. X X* Can easily add your own output filters for TeX, troff or any of the X other formats supported by lpr. X X* Page reversal filter supports version 3.0 of Document Structuring X Conventions. X X* Text to PostScript filter supports ISO Latin-1. X XThere is no copyright on lprps. X XSee the file INSTALL for installation information. X XPlease report any bugs to me. X XJames Clark Xjjc@jclark.uucp Xjjc%jclark@uunet.uu.net X X$Id: README,v 1.8 91/07/18 10:48:48 jjc Exp $ END_OF_FILE if test 1645 -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'\" \(2721 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$Id: INSTALL,v 1.6 91/07/14 14:21:37 jjc Exp $ END_OF_FILE if test 2721 -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'\" \(2488 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# $Id: Makefile,v 1.9 91/07/15 18:27:27 jjc Exp $ 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 XMANROOT=/usr/local/man X# Manual section for user commands. XMAN1EXT=1 XMAN1DIR=$(MANROOT)/man$(MAN1EXT) X# Manual section for system maintenance and operation commands. XMAN8EXT=8 XMAN8DIR=$(MANROOT)/man$(MAN8EXT) X XCC=cc XCFLAGS=-O $(DEFINES) X#CFLAGS=-g -Bstatic $(DEFINES) XINSTALL=install X# Command for installing man pages. XMANINSTALL=install -m 0444 X XSOURCES=README INSTALL Makefile psrev.c lprps.c psif.c textps.c \ X textps.man psrev.man lprps.man psif.man XPROGS=psrev psif lprps textps X X.SUFFIXES: .man .n X X.man.n: X @echo Making $@ from $< X @-rm -f $@ X @sed -e "s;@MAN1EXT@;$(MAN1EXT);" \ X -e "s;@MAN8EXT@;$(MAN8EXT);" \ X -e "s;@PS_FILTER@;$(PS_FILTER);" \ X -e "s;@TEXT_FILTER@;$(TEXT_FILTER);" \ X $< >$@ X @chmod 444 $@ X Xall: psif-text psif-ps $(PROGS) textps.n psrev.n lprps.n psif.n 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 $(MANINSTALL) textps.n $(MAN1DIR)/textps.$(MAN1EXT) X $(MANINSTALL) psrev.n $(MAN1DIR)/psrev.$(MAN1EXT) X $(MANINSTALL) lprps.n $(MAN8DIR)/lprps.$(MAN8EXT) X $(MANINSTALL) psif.n $(MAN8DIR)/psif.$(MAN8EXT) X @echo Now edit /etc/printcap X Xlprps: lprps.c X $(CC) $(CFLAGS) -o $@ lprps.c X Xpsif: psif.c X $(CC) $(CFLAGS) -DTEXT_FILTER=\"$(TEXT_FILTER)\" \ X -DPS_FILTER=\"$(PS_FILTER)\" -o $@ psif.c X Xtextps: textps.c X $(CC) $(CFLAGS) -o $@ textps.c X Xpsrev: psrev.c X $(CC) $(CFLAGS) -o $@ psrev.c X Xpsif-text: Makefile X @echo Creating $@ X @-rm -f $@ X @echo "#! /bin/sh" > $@ X @echo "$(TEXT_TO_PS) | $(REV_COMMAND) $(LIBDIR)/lprps \"\$$@\"" >>$@ X @chmod +x $@ X Xpsif-ps: Makefile X @echo Creating $@ X @-rm -f $@ 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 $(PROGS) psif-text psif-ps *.n END_OF_FILE if test 2488 -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'\" \(7541 characters\) sed "s/^X//" >'psrev.c' <<'END_OF_FILE' X/* psrev.c */ X X#ifndef lint Xstatic char rcsid[] = "$Id: psrev.c,v 1.3 91/07/14 14:11:01 jjc Exp $"; X#endif X X#include X#include X#include X#include X#include X Xchar *malloc(); Xchar *realloc(); X Xchar *xmalloc(); Xchar *xrealloc(); Xchar *prog; X Xvoid sys_error(message, arg) Xchar *message, *arg; X{ X extern char *sys_errlist[]; X extern int sys_nerr; X int en; X X en = errno; X fprintf(stderr, "%s: ", prog); X fprintf(stderr, message, arg); X if (en > 0 && en < sys_nerr) X fprintf(stderr, ": %s\n", sys_errlist[en]); X else X putc('\n', stderr); X exit(1); X} 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 sys_error("read error", (char *)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 if (fwrite(lb->buf, 1, lb->len, fp) != lb->len) X sys_error("write error", (char *)0); 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 if (putchar(c) == EOF) X sys_error("write error", (char *)0); X exit(0); X} X Xtypedef struct page_list { X long pos; X struct page_list *next; X} page_list; X Xvoid usage() X{ X fprintf(stderr, "usage: %s [file]\n", prog); X exit(1); X} 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_page_order = 0; X int page_order_atend = 0; 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 struct stat sb; X X prog = argv[0]; X lb.buf = 0; X if (argc > 2) X usage(); X if (argc == 2) { X errno = 0; X if (!freopen(argv[1], "r", stdin)) X sys_error("can't open `%s'", argv[1]); X } 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, "%%PageOrder:")) { X /* the first %%PageOrder comment is the significant one */ X if (had_page_order) X suppress = 1; X else { X char *ptr = lb.buf + sizeof("%%PageOrder:") - 1; X X had_page_order = 1; X while (*ptr == ' ') X ptr++; X if (strprefix(ptr, "(atend)")) X page_order_atend = 1; X else if (strprefix(ptr, "Ascend")) { X fputs("%%PageOrder: Descend\n", stdout); X suppress = 1; X } X else X dont_reverse = 1; X } X } X if (strprefix(lb.buf, "%%EndComments")) X break; X if (!suppress) X put_line(&lb, stdout); X } X X if (!had_page_order) X fputs("%%PageOrder: Descend\n", stdout); 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 (fstat(fileno(stdin), &sb) < 0) X sys_error("cannot stat stdin", (char *)0); X if ((sb.st_mode & S_IFMT) != S_IFREG) { X tempfp = tmpfile(); X if (!tempfp) X sys_error("can't open temporary file", (char *)0); 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 (page_order_atend && strprefix(lb.buf, "%%PageOrder:")) { X char *p = lb.buf + sizeof("%%PageOrder:") - 1; X while (*p == ' ') X p++; X dont_reverse = !strprefix(p, "Ascend"); 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 if (fseek(tempfp, first_page_pos, 0) < 0) X sys_error("seek error", (char *)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 if (fseek(tempfp, pl->pos, 0) < 0) X sys_error("seek error", (char *)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 if (putc(c, stdout) == EOF) X sys_error("write error", (char *)0); 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 if (fseek(tempfp, trailer_pos, 0) < 0) X sys_error("seek error", (char *)0); X if (page_order_atend) { X /* we need to change the %%PageOrder comment */ X while (get_line(&lb, tempfp)) { X if (page_order_atend && strprefix(lb.buf, "%%PageOrder:")) X fputs("%%PageOrder: Descend\n", stdout); X else X put_line(&lb, stdout); X } X } X else X copy_and_exit(tempfp); X } X X if (ferror(stdout)) X sys_error("write error", (char *)0); 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 7541 -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'\" \(12795 characters\) sed "s/^X//" >'lprps.c' <<'END_OF_FILE' X/* lprps.c */ X X#ifndef lint Xstatic char rcsid[] = "$Id: lprps.c,v 1.9 91/07/14 14:12:46 jjc Exp $"; X#endif X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#ifdef ultrix X#include X#endif /* ultrix */ 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, "invalid arguments"); 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 /* no interested in these */ 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 (!host || !login) X usage(); 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 12795 -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'\" \(2035 characters\) sed "s/^X//" >'psif.c' <<'END_OF_FILE' X/* psif.c */ X X#ifndef lint Xstatic char rcsid[] = "$Id: psif.c,v 1.6 91/07/18 10:47:15 jjc Exp $"; X#endif X X#include X#include X#include X Xoff_t 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 == 1) { X if ((nread = read(0, buf + 1, 1)) < 0) X sys_error("read"); X nread += 1; X } 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)-nread, 1) < 0) X sys_error("lseek"); X } X execv(command, argv); X sys_error("execv"); X} END_OF_FILE if test 2035 -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'\" \(11465 characters\) sed "s/^X//" >'textps.c' <<'END_OF_FILE' X/* textps.c */ X X#ifndef lint Xstatic char rcsid[] = "$Id: textps.c,v 1.6 91/07/14 14:18:43 jjc Exp $"; X#endif X X#include X#include X#include 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 Xdouble page_length = 842.0; /* in points */ X#else Xdouble page_length = 792.0; /* in points */ X#endif X Xdouble baseline_offset = 8.0; /* distance in points from top of page to */ X /* first baseline */ X Xdouble vertical_spacing = 12.0; /* in points */ X Xdouble left_margin = 18.0; /* in points */ Xdouble 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, X "usage: %s [-c n] [-l n] [-m n] [-t n] [-v n] [files ...]\n", X prog); X exit(1); X} X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int bad_files = 0; X double cpi = 12.0; /* characters per inch */ X int opt; X X prog = argv[0]; X X while ((opt = getopt(argc, argv, "c:l:m:t:v:")) != EOF) X switch (opt) { X case 'c': X if (sscanf(optarg, "%lf", &cpi) != 1) X usage(); X break; X case 'l': X if (sscanf(optarg, "%d", &lines_per_page) != 1) X usage(); X break; X case 'm': X if (sscanf(optarg, "%lf", &left_margin) != 1) X usage(); X break; X case 't': X if (sscanf(optarg, "%lf", &baseline_offset) != 1) X usage(); X break; X case 'v': X if (sscanf(optarg, "%lf", &vertical_spacing) != 1) X usage(); X break; X case '?': X usage(); X default: X abort(); X } X X char_width = 72.0/cpi; 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 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 Xvoid psnum(f) Xdouble f; X{ X static char buf[100]; X char *p; X sprintf(buf, "%f", f); X for (p = buf + strlen(buf) - 1; *p != '.'; --p) X if (*p != '0') { X p++; X break; X } X *p = '\0'; X fputs(buf, stdout); 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 psnum(left_margin + start_pos*char_width); X putchar(' '); X psnum(page_length - baseline_offset - vpos*vertical_spacing); X fputs(" L\n", stdout); X } X} X Xvoid page_start() X{ X printf("%%%%Page: ? %d\n%%%%BeginPageSetup\nPS\n%%%%EndPageSetup\n", X ++pageno); X current_font = NONE; X} X Xvoid page_end() X{ X printf("PE\n"); X} X Xchar *defs[] = { X "/L { moveto show } bind def", X "/PS { /level0 save def } bind def", X "/PE { level0 restore showpage } bind def", X "/RE {", X "\tfindfont", X "\tdup maxlength dict begin", X "\t{", X "\t\t1 index /FID ne { def } { pop pop } ifelse", X "\t} forall", X "\t/Encoding exch def", X "\tdup /FontName exch def", X "\tcurrentdict end definefont pop", X "} bind def", X}; X Xchar *latin1[] = { X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X "space", X "exclam", X "quotedbl", X "numbersign", X "dollar", X "percent", X "ampersand", X "quoteright", X "parenleft", X "parenright", X "asterisk", X "plus", X "comma", X "hyphen", X "period", X "slash", X "zero", X "one", X "two", X "three", X "four", X "five", X "six", X "seven", X "eight", X "nine", X "colon", X "semicolon", X "less", X "equal", X "greater", X "question", X "at", X "A", X "B", X "C", X "D", X "E", X "F", X "G", X "H", X "I", X "J", X "K", X "L", X "M", X "N", X "O", X "P", X "Q", X "R", X "S", X "T", X "U", X "V", X "W", X "X", X "Y", X "Z", X "bracketleft", X "backslash", X "bracketright", X "asciicircum", X "underscore", X "quoteleft", X "a", X "b", X "c", X "d", X "e", X "f", X "g", X "h", X "i", X "j", X "k", X "l", X "m", X "n", X "o", X "p", X "q", X "r", X "s", X "t", X "u", X "v", X "w", X "x", X "y", X "z", X "braceleft", X "bar", X "braceright", X "asciitilde", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X ".notdef", X "dotlessi", X "grave", X "acute", X "circumflex", X "tilde", X "macron", X "breve", X "dotaccent", X "dieresis", X ".notdef", X "ring", X "cedilla", X ".notdef", X "hungarumlaut", X "ogonek", X "caron", X ".notdef", X "exclamdown", X "cent", X "sterling", X "currency", X "yen", X "brokenbar", X "section", X "dieresis", X "copyright", X "ordfeminine", X "guilsinglleft", X "logicalnot", X "registered", X "minus", X "macron", X "degree", X "plusminus", X "twosuperior", X "threesuperior", X "acute", X "mu", X "paragraph", X "periodcentered", X "cedilla", X "onesuperior", X "ordmasculine", X "guilsinglright", X "onequarter", X "onehalf", X "threequarters", X "questiondown", X "Agrave", X "Aacute", X "Acircumflex", X "Atilde", X "Adieresis", X "Aring", X "AE", X "Ccedilla", X "Egrave", X "Eacute", X "Ecircumflex", X "Edieresis", X "Igrave", X "Iacute", X "Icircumflex", X "Idieresis", X "Eth", X "Ntilde", X "Ograve", X "Oacute", X "Ocircumflex", X "Otilde", X "Odieresis", X "multiply", X "Oslash", X "Ugrave", X "Uacute", X "Ucircumflex", X "Udieresis", X "Yacute", X "Thorn", X "germandbls", X "agrave", X "aacute", X "acircumflex", X "atilde", X "adieresis", X "aring", X "ae", X "ccedilla", X "egrave", X "eacute", X "ecircumflex", X "edieresis", X "igrave", X "iacute", X "icircumflex", X "idieresis", X "eth", X "ntilde", X "ograve", X "oacute", X "ocircumflex", X "otilde", X "odieresis", X "divide", X "oslash", X "ugrave", X "uacute", X "ucircumflex", X "udieresis", X "yacute", X "thorn", X "ydieresis", X}; X Xvoid prologue() X{ X int col, i; X X printf("%%!PS-Adobe-3.0\n"); X printf("%%%%DocumentNeededResources: font %s\n", font); X printf("%%%%+ font %s\n", bold_font); X printf("%%%%Pages: (atend)\n"); X printf("%%%%EndComments\n"); X printf("%%%%BeginProlog\n"); X printf("/textps 10 dict def textps begin\n"); X for (i = 0; i < sizeof(defs)/sizeof(defs[0]); i++) X printf("%s\n", defs[i]); X printf("/ISOLatin1Encoding where{pop}{/ISOLatin1Encoding[\n"); X X col = 0; X for (i = 0; i < 256; i++) { X int len = strlen(latin1[i]) + 1; X col += len; X if (col > 79) { X putchar('\n'); X col = len; X } X printf("/%s", latin1[i]); X } X printf("\n] def}ifelse\nend\n"); X printf("%%%%BeginSetup\n"); X printf("%%%%IncludeResource: font %s\n", font); X printf("%%%%IncludeResource: font %s\n", bold_font); X printf("textps begin\n"); X printf("/__%s ISOLatin1Encoding /%s RE\n", font, font); X printf("/R [ /__%s findfont %f scalefont /setfont load ] cvx def\n", X font, char_width/.6); X printf("/__%s ISOLatin1Encoding /%s RE\n", bold_font, bold_font); X printf("/B [ /__%s findfont %f scalefont /setfont load ] cvx def\n", X bold_font, char_width/.6); X printf("%%%%EndSetup\n"); X printf("%%%%EndProlog\n"); X} X Xvoid trailer() X{ X printf("%%%%Trailer\nend\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 11465 -ne `wc -c <'textps.c'`; then echo shar: \"'textps.c'\" unpacked with wrong size! fi # end of 'textps.c' fi if test -f 'textps.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'textps.man'\" else echo shar: Extracting \"'textps.man'\" \(1110 characters\) sed "s/^X//" >'textps.man' <<'END_OF_FILE' X.\" -*- nroff -*- X.TH TEXTPS @MAN1EXT@ X.\" $Id: textps.man,v 1.1 91/07/14 14:04:40 jjc Exp $ X.SH NAME Xtextps \- text to PostScript filter X.SH SYNOPSIS X.B textps X[ X.BI \-c n X] X[ X.BI \-l n X] X[ X.BI \-m n X] X[ X.BI \-t n X] X[ X.BI \-v n X] X[ X.I filename\|.\|.\|. X] X.SH DESCRIPTION X.B textps Xis a simple text to PostScript filter. XIt is usually invoked automatically by a spooler. XInput files can use ISO Latin-1. XTwo or more identical overstruck characters are rendered using a bold font. XTabs are assumed to be set every 8 character positions. X.SH OPTIONS XThe arguments for all options except X.B \-l Xare floating-point numbers. XThe argument for X.B \-l Xmust be a positive integer. X.TP X.BI \-c n XUse X.I n Xcharacters to the inch. X.TP X.BI \-l n XUse X.I n Xlines per page. X.TP X.BI \-m n XUse a left margin of X.I n Xpoints. X.TP X.BI \-t n XPosition the baseline of the first line of text X.I n Xpoints below the top of the page. X.TP X.BI \-v n XUse a vertical spacing of X.I n Xpoints. X.LP XThe default behaviour is X.BR \-c12\ \-l66\ \-m18\ \-t8\ \-v12 . X.SH "SEE ALSO" X.BR psrev (@MAN1EXT@), X.BR lprps (@MAN8EXT@), X.BR psif (@MAN8EXT@) END_OF_FILE if test 1110 -ne `wc -c <'textps.man'`; then echo shar: \"'textps.man'\" unpacked with wrong size! fi # end of 'textps.man' fi if test -f 'psrev.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psrev.man'\" else echo shar: Extracting \"'psrev.man'\" \(776 characters\) sed "s/^X//" >'psrev.man' <<'END_OF_FILE' X.\" -*- nroff -*- X.\" $Id: psrev.man,v 1.1 91/07/14 14:05:28 jjc Exp $ X.TH PSREV @MAN1EXT@ X.SH NAME Xpsrev \- PostScript page reversal filter X.SH SYNOPSIS X.B psrev X[ X.I filename X] X.SH DESCRIPTION X.B psrev Xreverses the order of the pages of a PostScript document. XUsually X.B psrev Xis used with printers that stack face up Xand is run automatically by the spooler. XThe document must conform to the Adobe Document Structuring Conventions, Xpreferably version 3.0. X.LP X.B psrev Xrespects the X.B %%PageOrder: Xcomment: Xif this comment is present and has an argument other than X.B Ascend Xthe document will not be reversed. XA document reversed by X.B psrev Xwill contain a X.B %%PageOrder:\ Descend Xcomment. X.SH "SEE ALSO" X.BR textps (@MAN1EXT@), X.BR lprps (@MAN8EXT@), X.BR psif (@MAN8EXT@) END_OF_FILE if test 776 -ne `wc -c <'psrev.man'`; then echo shar: \"'psrev.man'\" unpacked with wrong size! fi # end of 'psrev.man' fi if test -f 'lprps.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lprps.man'\" else echo shar: Extracting \"'lprps.man'\" \(2148 characters\) sed "s/^X//" >'lprps.man' <<'END_OF_FILE' X.\" -*- nroff -*- X.\" $Id: lprps.man,v 1.2 91/07/14 15:55:35 jjc Exp $ X.TH LPRPS @MAN8EXT@ X.SH NAME Xlprps \- lpr PostScript communication filter X.SH SYNOPSIS X.B lprps X[ X.B \-c X] X[ X.BI \-w n X] X[ X.BI \-l n X] X[ X.BI \-x n X] X[ X.BI \-y n X] X[ X.BI \-i n X] X[ X.BI \-n \ login_name X] X[ X.BI \-h \ host X] X[ X.I accounting_file X] X.SH DESCRIPTION X.B lprps Xhandles communication with a PostScript printer for lpr output filters. XThe PostScript printer must be connected using a serial channel. XEach output filter should be a pipeline with X.B lprps\ "$@" Xas the last command. XThe other commands in the pipeline should handle conversion into PostScript Xand possibly page reversal. XThe command-line syntax of X.B lprps Xis such that any argument vector Xwhich X.B lpd Xmight pass to an output file is a legal argument vector for X.BR lprps . XNo X.B of Xoutput filter should be used. X.LP XOutput generated by the PostScript document and errors caused by Xdefects in the PostScript file are mailed back to the user X(identified by the X.B \-n Xand X.B \-h Xoptions). XOther errors X(such as `out of paper' errors) Xare logged using syslog with the X.B LOG_LPR Xfacility. X.LP X.B lprps Xsupports printer accounting. XIf this facility is required, Xa file to contain the accounting information must be specified in X.B af Xcapability in the printcap file. XThis file should exist, have mode 644 and be owned by daemon. XThe name of this file will be passed to X.B lprps Xin the X.I accounting_file Xargument. XFor each job, X.B lprps Xwill append to this file an accounting record specifying the user's name Xand host together with the number of pages used. XThe X.BR pac (8) Xcommand can then be used to generate an accounting report. XThe accounting information should be reliable except when Xthe printer has been turned off or disconnected in the middle of a job. X.SH OPTIONS XThe X.B \-n Xand X.B \-h X`options' are required. XAll other options are ignored. X.TP \w'\fB\-n\ \fIname'u+3n X.BI \-n \ name XThe user's login name is X.IR name . X.TP X.BI \-h \ host XThe user's host machine is X.IR host . X.SH "SEE ALSO" X.BR textps (@MAN1EXT@), X.BR psrev (@MAN1EXT@), X.BR syslog.conf (5), X.BR psif (@MAN8EXT@), X.BR pac (8) END_OF_FILE if test 2148 -ne `wc -c <'lprps.man'`; then echo shar: \"'lprps.man'\" unpacked with wrong size! fi # end of 'lprps.man' fi if test -f 'psif.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psif.man'\" else echo shar: Extracting \"'psif.man'\" \(1269 characters\) sed "s/^X//" >'psif.man' <<'END_OF_FILE' X.\" -*- nroff -*- X.\" $Id: psif.man,v 1.1 91/07/14 14:05:13 jjc Exp $ X.TH PSIF @MAN8EXT@ X.SH NAME Xpsif \- PostScript input filter splitter for lpr X.SH SYNOPSIS X.B psif X[ X.I args\|.\|.\|. X] X.SH DESCRIPTION X.B psif Xexecutes either X.B @PS_FILTER@ Xor X.B @TEXT_FILTER@ Xaccording to whether or not the first two characters of its standard Xinput are X.BR %! . X.B psif Xwill arrange that the process that it executes sees the same standard Xinput that it did, Xand will pass the process the same arguments that it received. X.LP XUsually X.B psif Xwill be specified as the value of X.B if Xcapability in the printcap entry for a PostScript printer; X.B @TEXT_FILTER@ Xwill be a shell script that runs a text to PostScript filter Xsuch as X.BR textps (@MAN1EXT@), Xfollowed by a PostScript page reversal filter such as X.BR psrev (@MAN1EXT@) X(only needed for PostScript printers that stack face up), Xfollowed by PostScript communication filter such as X.BR lprps (@MAN8EXT@); X.B @PS_FILTER@ Xwill be similar except that it will not run the text to PostScript filter. X.SH FILES X.TP \w'\fB@TEXT_FILTER@'u+3n X.B @TEXT_FILTER@ XFilter for text files. X.TP X.B @PS_FILTER@ XFilter for PostScript files. X.SH "SEE ALSO" X.BR textps (@MAN1EXT@), X.BR psrev (@MAN1EXT@), X.BR printcap (5), X.BR lprps (@MAN8EXT@) END_OF_FILE if test 1269 -ne `wc -c <'psif.man'`; then echo shar: \"'psif.man'\" unpacked with wrong size! fi # end of 'psif.man' fi echo shar: End of shell archive. exit 0 exit 0 # Just in case...