[net.sources] LPR/LPD hacks for 4.2BSD

david@ukma.UUCP (David Herron, NPR Lover) (12/19/84)

#! /bin/sh
# ------------------------>Cut Here<--------------------------
# This is a shell archive.  To extract the files, save the 
# following text to a seperate file and type "sh filename" 
#
# DO NOT RUN CSH ON THIS! 
#
echo x - README '		' '-rw-r--r--  1 david        3137 Dec 18 21:32 README'
sed 's/^X//' > README <<'EOF-OF-THIS-FILE'
X		LPR/LPD HACKS FOR 4.2BSD
X
X	Here are my modifications for lpr from 4.2BSD.  The diff
Xlistings are context diffs using the distributed software as the
Xbase file.  As usual, line numbers may vary with local patching
Xconditions.
X
X	There are 4 major groups of changes here:
X
X	1: Allowing the lpr command to select print density and
X	   format by way of command line options.
X	2: Added an environment variable LPR.  This gets scanned
X	   by lpr after reading the system default parameters and
X	   before the command line parameters.  It is meant to
X	   be used for user default settings.  (The inspiration
X	   is the similar variable for more).
X	3: Bug fixes.  I found a number of bugs in lpf.c.  Look
X	   at the diff's for it to find out what.
X	4: Support for our LN01.  As you can tell from the comments
X	   in lpf.c and nrpf.c, I had many many troubles with that
X	   beast.  May she rest in peace.
X
X	One thing the LPR variable doesn't do that I would like to do
Xis specify files to print.  I envision that being useful in a class
Xsituation.  The instructor may want to have a file somewhere that
Xgets printed out with each students print job.  Or a user might want
Xto have his own banner page rather than the standard one.  Anything
Xalong those lines would be reasonable.  It would take a major rewrite
Xof the command parser in lpr.....
X
Xflpf.c
X	Generic filter for output with fortran-type carraige control.
X	Supports the LN01 and LA120.  Written by me.
X
Xlpd.c.diff
X	Changes to lpd.c.  Simple.  We were having response problems
X	when printing things.  Raise the nice to 9 and it becomes
X	less of a problem.  Now though the printers stop occasionally. 
X
Xlpf.c.diff
X	Changes to lpf.c.  Including a couple of rather serious bugs.
X	Supports the LN01 and LA120.
X
Xlpr.c.diff
X	Changes to lpr.c.  New command parser looks at the LPR variable
X	(almost) as if it were a command line.  Almost because it doesn't
X	pick up any files to print from here.
X
Xnrpf.c
X	A filter for nroff output.  It reads the cursor-up and
X	cursor-down commands that nroff outputs, stores the text
X	at appropriate places in a buffer, then outputs the buffer
X	when nroff tries to go off the page.  This was written 
X	instead of an nroff table because there isn't any documentation
X	on the values to be put into one of those tables.  I took
X	one stab at reading nroff and said FORGET IT!  Especially
X	since we are getting ditroff sometime Real Soon Now.
X	It was easier to guess at nroff's output than read nroff.
X
X	At any rate.  This program is currently specific to
X	the LN01 and it's peculiarities.  But it was written
X	with the SPECIFIC intent of making it work for LA120's
X	and LA100's at some time in the future.  (i.e. Real Soon Now).
X
X	Written by me.
X
Xprintjob.c.diff
X	Changes to printjob.c.  Two changes.  One to recognize a
X	new control card which selects the page length of the printer.
X	The other gives the filter an indent flag ONLY if there was 
X	an indent card in the control file.
X
Xscanargs.c
Xstringop.c
X	Seperate files containing routines added to lpr.c so it would
X	scan the LPR environment variable.
X
Xlpr.1
X	Lpr manual page reflecting most of these changes.
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l README
echo x - lpr.1 '		' '-rw-r--r--  1 david        6639 Dec 18 21:36 lpr.1'
sed 's/^X//' > lpr.1 <<'EOF-OF-THIS-FILE'
X.TH LPR 1 "28 July 1983"
X.UC 4
X.SH NAME
Xlpr \- off line print
X.SH SYNOPSIS
X.B lpr
X[
X.BI \-P printer
X] [
X.BI \-# num
X] [
X.B \-C
X.I class
X] [
X.B \-J
X.I job
X] [
X.B \-T
X.I title
X] [
X.B \-i
X[
X.I numcols
X]] [
X.B \-1234
X.I font
X] [
X.B \-L
X.I length
X] [
X.BI \-w num
X] [
X.B \-pltndgvcfrmhs
X] [
Xname ...
X]
X.SH DESCRIPTION
X.B Lpr
Xuses a spooling daemon to print the named files when facilities
Xbecome available.  If no names appear, the standard input is assumed.
XThe
X.B \-P
Xoption may be used to force output to a specific printer.  Normally,
Xthe default printer is used (site dependent), or the value of the
Xenvironment variable PRINTER is used.
X.PP
XA customized set of defaults may be given in the environment variable
XLPR.
XThis variable is scanned by lpr(1) before the command line is scanned,
Xallowing the command line to overide the customized defaults.
XSyntax for options in LPR are exactly the same as for the command line,
Xwith only one exception, files to print may not be given in LPR.
X.PP
XThe following single letter options are used to notify the line printer
Xspooler that the files are not standard text files. The spooling daemon
Xwill use the appropriate filters to print the data accordingly.
X.IP \fB\-p\fP 5
XUse
X.IR pr (1)
Xto format the files (equivalent to
X.IR print ).
X.IP \fB\-l\fP 5
XUse a filter which allows control characters to be printed and
Xsuppresses page breaks.
X.IP \fB\-t\fP 5
XThe files are assumed to contain data from
X.IR troff (1)
X(cat phototypesetter commands).
X.IP \fB\-n\fP 5
XThe files are assumed to contain data from
X.I ditroff
X(device independent troff).
X.IP \fB\-d\fP 5
XThe files are assumed to contain data from
X.IR tex (l)
X(DVI format from Stanford).
X.IP \fB\-g\fP 5
XThe files are assumed to contain standard plot data as produced by the
X.IR plot (3X)
Xroutines (see also
X.IR plot (1G)
Xfor the filters used by the printer spooler).
X.IP \fB\-v\fP 5
XThe files are assumed to contain a raster image for devices like the
XBenson Varian.
X.IP \fB\-c\fP 5
XThe files are assumed to contain data produced by
X.IR cifplot (l).
X.IP \fB\-f\fP 5
XUse a filter which interprets the first character of each line as a
Xstandard FORTRAN carriage control character.
X.PP
XThe remaining single letter options have the following meaning.
X.IP \fB\-r\fP 5
XRemove the file upon completion of spooling or upon completion of
Xprinting (with the \fB\-s\fP option).
X.IP \fB\-m\fP 5
XSend mail upon completion.
X.IP \fB\-h\fP 5
XSuppress the printing of the burst page.
X.IP \fB\-s\fP 5
XUse symbolic links.  Usually files are copied to the spool directory.
X.PP 
XThe
X.B \-C
Xoption takes the following argument as a job classification
Xfor use on the burst page.  For example,
X.PP
X.ti +0.5i
Xlpr \-C EECS foo.c
X.PP
Xcauses the system name (the name returned by
X.IR hostname (1))
Xto be replaced on the burst page by EECS,
Xand the file foo.c to be printed.
X.PP
XThe
X.B \-J
Xoption takes the following argument as the job name to print on the
Xburst page.
XNormally, the first file's name is used.
X.PP
XThe
X.B \-T
Xoption uses the next argument as the title used by
X.IR pr (1)
Xinstead of the file name.
X.PP
XTo get multiple copies of output, use the
X.BI \-# num
Xoption,
Xwhere
X.I num
Xis the number of copies desired of each file named.  For example,
X.PP
X.ti +0.5i
Xlpr \-#3 foo.c bar.c more.c
X.PP
Xwould result in 3 copies of the file foo.c, followed by 3 copies
Xof the file bar.c, etc.  On the other hand, 
X.PP
X.ti +0.5i
Xcat foo.c bar.c more.c | lpr \-#3
X.PP
Xwill give three copies of the concatenation of the files.
X.PP
XThe
X.B \-i
Xoption causes the output to be indented. If the next argument
Xis numeric, it is used as the number of blanks to be printed before each
Xline; otherwise, 8 characters are printed.
X.PP
XThe
X.B \-L
Xoption takes the immediately following number to be the page length.
XThe number specified is for a number of lines on the entire form.
XFor the LA-120 the spacing per inch is as follows:
X.nf
X
X	Characters per form	Lines per inch
X                  22                 2
X                  33                 3
X                  44                 4
X                  66 (default)       6
X                  88                 8
X                 132                12
X
X.fi
XThe numbers assume that the form length is 11 inches.
X.PP
XThe
X.B \-w
Xoption takes the immediately following number to be
Xthe page width for
X.IR pr .
XOn LA-120's the width is set as follows:
X.nf
X
X	Chars/inch	# chars 8 inch	    # chars 14 inch
X
X            5                 40                    66
X            6                 48                    79
X            6.6	              52                    87
X            8.25              66                   108
X           10                 80                   132
X           12                 96                   158
X           13.2              105                   174
X           16.5 (default)    132                   217
X
X.fi
XThe number specified is the one in the 14 inch column.
XFor instance, if you want to print using 80 columns on narrow paper,
Xuse "-w132".
XThe only (minor) problem with this is that printing longer
Xthan 80 columns will not wrap to the next line, but will keep on printing
Xuntil it reaches the 132'd column.
XThe default print size was set to 16.5 characters per inch.
X.PP
XThe
X.B \-s
Xoption will use
X.IR symlink (2)
Xto link data files rather than trying to copy them so large files can be
Xprinted.  This means the files should
Xnot be modified or removed until they have been printed.
X.PP
XThe option
X.B \-1234
XSpecifies a font to be mounted on font position \fIi\fR.  The daemon
Xwill construct a \fI.railmag\fR file referencing
X\fI/usr/lib/vfont/name.size\fR.
X.SH FILES
X.nf
X.ta \w'/usr/spool/*/cf*       'u
X/etc/passwd	personal identification
X/etc/printcap	printer capabilities data base
X/usr/lib/lpd*	line printer daemons
X/usr/spool/*	directories used for spooling
X/usr/spool/*/cf*	daemon control files
X/usr/spool/*/df*	data files specified in "cf" files
X/usr/spool/*/tf*	temporary copies of "cf" files
X.fi
X.SH "SEE ALSO"
Xlpq(1),
Xlprm(1),
Xpr(1),
Xsymlink(2),
Xprintcap(5),
Xlpc(8),
Xlpd(8)
X.SH DIAGNOSTICS
XIf you try to spool too large a file, it will be truncated.
X.I Lpr
Xwill object to printing binary files.
XIf a user other than root prints a file and spooling is disabled,
X.I lpr
Xwill print a message saying so and will not put jobs in the queue.
XIf a connection to
X.I lpd
Xon the local machine cannot be made,
X.I lpr
Xwill say that the daemon cannot be started.
XDiagnostics may be printed in the daemon's log file
Xregarding missing spool files by
X.IR lpd .
X.SH BUGS
XFonts for
X.I troff
Xand
X.I tex
Xreside on the host with the printer. It is currently not possible to
Xuse local font libraries.
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l lpr.1
echo x - flpf.c '		' '-rw-r--r--  1 david        6939 Dec  6 19:54 flpf.c'
sed 's/^X//' > flpf.c <<'EOF-OF-THIS-FILE'
X/* flpf.c -- Fortran Line Printer Filter for Fortran-style carraige control.
X *
X * Column 1 of stdin contains the carraige control characters as follows:
X *
X *	'1':	skip to beginning of next page.
X *	'+':	do a carraige return, but no line feed.
X *	' ':	skip to next line.
X *	'0':	skip to line following next line (inserts a blank line).
X *	'-':	leave two blank lines.
X *
X * [dsh 17JAN84]
X *
X * CHANGE:
X *--	added code to set form sizes on LA-120 (dsh 19JAN84).
X *--	fixed bug mentioned in lpf.c about changing print sizes unexpectadly 
X *	[dsh 24JAN84]
X *--	Added strict limiting of length and width to be less than
X *	MAXLENGTH and MAXWIDTH respectively.
X *	[dsh 18MAR84]
X *--	Problem: After advancing to new form, the output is at the
X *	very top of the page.  It should be two lines down.
X *	Fix: Have it advance two lines.
X *	[8-Jun-84 dsh]
X *--- [1-Nov-84 dsh]:  Added buffering for stdout (see comment in nrpf.c).
X */
X
X#include <stdio.h>
X#include <signal.h>
X
X#ifdef LA120
X#define MAXWIDTH	217
X#define MAXLENGTH	132
X#else
X#define MAXWIDTH	80
X#define MAXLENGTH	66
X#endif
X
Xchar buffer[BUFSIZ];	/* CHANGE [1-Nov-84 dsh] */
Xint width = MAXWIDTH;	/* default number of columns. */
Xint length = MAXLENGTH;	/* default number of lines. */
Xint indent;		/* how far to indent output. */
Xint literal;		/* flag to pass all control characters literally */
Xchar *name;		/* user id of user. */
Xchar *host;		/* where he lives */
Xchar *acctfile;		/* accounting file. */
X
Xint lineno,colno;	/* where we are on the page. */
Xint npages = 1;		/* how many pages were printed. */
X
X#ifdef LA120
Xstruct sztosp { /* form size to spacing. */
X	int size;		/* number of positions in dimension. */
X	int spacing;		/* number of positions per inch. */
X	char *string;		/* string to set that mode. */
X};
X
Xstruct sztosp flength[] = { /* for 11 inch long forms. */
X	 22, 2,"\033[4z",
X	 33, 3,"\033[5z",
X	 44, 4,"\033[6z",
X	 66, 6,"\033[1z",
X	 88, 8,"\033[2z",
X	132,12,"\033[3z",
X	-1,0,"\033[1z"		/* default: 66 lines/page */
X};
X#define FINALENGTH	"\033[3z\033[66t"
X
Xstruct sztosp fwidth[] = { /* for 13.2 inch wide forms. */
X				/* number of spaces on 8 inch wide forms. */
X	 66, 5,"\033[5w",	/*  40 */
X	 79, 6,"\033[6w",	/*  48 */
X	 87, 7,"\033[7w",	/*  52 */
X	108, 8,"\033[8w",	/*  66 */
X	132,10,"\033[1w",	/*  80 */
X	158,12,"\033[2w",	/*  96 */
X	174,13,"\033[3w",	/* 105 */
X	217,16,"\033[4w",	/* 132 */
X	-1,0,"\033[4w"		/* default: 16 chars/inch */
X};
X#define FINALWIDTH	"\033[1w"	/* set it to this when done. */
X#endif /* LA120 */
X
X/* ndent() -- space over indent # of spaces.
X */
Xndent()
X{
X	register int i;
X
X	for(i=indent; i>0; i--)
X		pchar(' ');
X}
X
X/* pchar() -- output the char, go to next line if we run out of room on this one
X */
Xpchar(c)
Xchar c;
X{
X	putchar(c);
X	if(++colno >= width) {
X		if(++lineno >= length)
X			ff();
X		else
X			nl();
X		ndent();
X	}
X}
X
X/* ff() -- put out a form feed, set lineno and colno to 0, increment npages.
X */
Xff()
X{
X	putchar('\r');
X	putchar('\f');
X	putchar('\n');
X	putchar('\n');
X	lineno = 3; colno = 0;
X	npages++;
X}
X
X/* nl() -- put out a new line.  use ff() if past page boundry.
X */
Xnl()
X{
X	if(++lineno >= length)
X		ff();
X	else
X		putchar('\n');
X	colno = 0;
X}
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	register char *cp;
X	register int i;
X	char *widthstring,*lengthstring; /* CHANGE [dsh 24JAN84] */
X	register char c;
X	register struct sztosp *p;
X#ifdef LA120
X	int actualength;
X#endif
X
X	setbuf(stdout, buffer);	/* CHANGE [1-Nov-84 dsh] */
X	while (--argc) {
X		if (*(cp = *++argv) == '-') {
X			switch (cp[1]) {
X			    case 'n':	/* users name. */
X				argc--;
X				name = *++argv;
X				break;
X
X			    case 'h':	/* where he lives. */
X				argc--;
X				host = *++argv;
X				break;
X
X			    case 'w':	/* how wide this printer is. */
X				if ((i=atoi(&cp[2]))>0 && i<=MAXWIDTH)
X					width = i;
X				break;
X
X			    case 'l':	/* how long it is. */
X				if((i=atoi(&cp[2]))>0 && i<=MAXLENGTH)
X					length = i;
X				break;
X
X			    case 'i':	/* how far to indent output. */
X				indent = atoi(&cp[2]);
X				break;
X
X			    case 'c':	/* Print control chars */
X				literal++;
X				break;
X			}
X		} else
X			acctfile = cp;
X	}
X
X#ifdef LA120
X	for(p = &flength[0]; length>p->size && p->size!=-1; p++)
X		/* null */;
X	printf("%s",p->string);
X	actualength = p->size;
X	lengthstring = p->string; /* CHANGE [dsh 24JAN84] */
X	for(p = &fwidth[0]; width>p->size && p->size!=-1; p++)
X		/* null */;
X	printf("%s",p->string);
X	widthstring = p->string; /* CHANGE [dsh 24JAN84] */
X#endif
X
X	/* Ready to print the file.  The text is coming in on stdin,
X	 * and should leave via stdout.
X	 * The special characters are the ones just after a '\n'(colno==0),
X	 * '\f', '\t' and '\n' (to set colno==0).
X	 */
X
X	lineno = 1; colno = 0;
X
X	while((c=getchar()) != EOF) {
X		switch(c) {
X		    case '1':	/* advance to new page. */
X			if(colno == 0)
X				{ ff(); colno = 1; ndent(); }
X			else
X				pchar('1');
X			break;
X
X		    case '+':	/* no advance. */
X			if(colno == 0)
X				{ putchar('\r'); colno = 1; ndent(); }
X			else
X				pchar('+');
X			break;
X
X		    case ' ':	/* single advance. */
X			if(colno == 0)
X				{ nl(); colno = 1; ndent(); }
X			else
X				pchar(' ');
X			break;
X
X		    case '0':	/* double advance. */
X			if(colno == 0)
X				{ nl(); nl(); colno = 1; ndent(); }
X			else
X				pchar('0');
X			break;
X
X		    case '-':	/* triple advance. */
X			if(colno == 0)
X				{ nl(); nl(); nl(); colno = 1; ndent(); }
X			else
X				pchar('-');
X			break;
X
X		    case '\031': /* MAYBE the daemon wants us to stop */
X			if((c=getchar()) == '\1') {
X				/* magic sequence is "\031\1". */
X				fflush(stdout);
X				kill(getpid(),SIGSTOP);
X				/* return after parent sends SIGCONT. */
X#ifdef LA120
X				printf(widthstring); /* CHANGE [dsh 24JAN84] */
X				printf(lengthstring); /* CHANGE [dsh 24JAN84] */
X				printf("\033[%dt",actualength);
X#endif
X			}
X			else {
X				/* not proper sequence. */
X				ungetc(c,stdin);
X				pchar('\031');
X			}
X			break;
X
X		    case '\f':	/* REAL form feed. */
X			if(colno == 0) nl();
X			ff();
X			ndent();
X			break;
X
X		    case '\n':	/* set flag that we saw a '\n'. */
X			if(colno == 0) nl(); /* if last had been a '\n'. */
X			colno = 0;
X			break;
X
X		    case '\t':	/* tab.  have to increment colno properly. */
X			if(colno == 0) { nl(); ndent(); }
X			i = 8 - (colno&07);	/* get increment to next tab stop. */
X			colno += i;
X			if(colno > width)
X				/* next tab stop at beg. of next line. */
X				{ nl(); colno = 1; ndent(); }
X			else
X				while(i--) putchar(' ');
X			break;
X
X		    default:
X			if(colno == 0) { nl(); ndent(); }
X			pchar(c);
X			break;
X		}
X	}
X
X
X	/* End-Of-File recieved.  Finish everything up, make sure that
X	 * the printer ends up at the top of a page.
X	 */
X	if(lineno != 0) {
X		while(lineno++ < length)
X			putchar('\n');
X		ff();
X	}
X	fflush(stdout);
X
X#ifdef LA120
X	printf("%s",FINALWIDTH);
X	printf("%s",FINALENGTH);
X#endif
X
X	if(name!=0 && acctfile!=0 && access(acctfile,02)>=0 &&
X		freopen(acctfile,"a",stdout)!=NULL) {
X			printf("%7.2f\t%s:%s\n",(float)npages,host,name);
X	}
X	exit(0);
X}
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l flpf.c
echo x - nrpf.c '		' '-rw-r--r--  1 david       11939 Dec  6 19:54 nrpf.c'
sed 's/^X//' > nrpf.c <<'EOF-OF-THIS-FILE'
X/* nrpf.c -- filters up and down line motions into something reasonable.
X *
X *	The standard forward and backward motion commands are:
X *
X *		'\0337'		back one full line.
X *		'\0338'		back one-half line.
X *		'\0339'		forward one-half line.
X *		'\n'		forward one full line.
X *		'\t'		stay on same line, move tab to
X *				next mult of 8 column.
X *		'\b'		stay on same line, move back one space.
X *		'\r'		stay on same line, but move to the
X *				beginning of the line.
X *
X * CHANGES
X *--	[15-Sep-84 dsh]: Made some changes corresponding to changes in
X *	lpf.c.  As follows:
X *	1) Added flag for specifying an indent.  This controls selection
X *	   of portrait or nportrait when width is <= 80.
X *	2) Added code to select landscape when width > 80.
X *	3) Placed some printer dependant items under conditional
X *	   compilation.  The idea is to eventually have a nrpf120 and
X *	   nrpf100 as well as nrpf01.
X *	4) Padded all output lines to NCOLS columns. (HUGE kludge!)
X *---	[6-Oct-84 dsh]:  Applied KISS principle.  Took out those complicated
X *	doubly linked list....  (noticed that nroff was putting out
X *	appropriate cursor motions for the text to fit together as it
X *	was....So the filter didn't have to check that nroff wasn't
X *	overlaying text on us.)
X *	Still have a problem with the title page of the lex manual.  The
X *	first paragraph has Half-Line-Reverse motions at the beginning
X *	of every line, and a new-line at the end.  This SHOULD come out
X *	correctly!  However, the paragraph is coming out with all the
X *	lines 1/2 line apart.....  Whats the problem?????
X *--- [1-Nov-84 dsh]:
X *	Problem:  System load is high during print jobs.
X *	Diagnosis:  Watching vmstat during a print job shows that the
X *		system time percentage is highest.
X *	Fix:  Give stdout a buffer.  The reasoning is that since output
X *		is done with putchar() then stdout isn't buffered very
X *		nicely.  (A nice buffering being one 512 characters wide)
X */
X
X#include <stdio.h>
X
X#ifdef LN01
X#define NROWS	(66*2)		/* 66 lines per page plus a superscript
X				 * for each line.
X				 */
X#define NREPS	10
X#define NCOLS	132
X#define DEFWIDTH 80
X#define MAXWIDTH 132
X#define DEFLENGTH 66
X#define MAXLENGTH 66
X#endif
X
X
X#ifdef LA120
X#define NROWS	(66*2)		/* 66 lines per page, plus a superscript
X				 * for each line.
X				 */
X#define NREPS	(10)		/* maximum number of rep's of each line */
X#define NCOLS	(217)		/* maximum width of page (for LA-120) */
X#define DEFWIDTH 132
X#define MAXWIDTH 217
X#define DEFLENGTH 66
X#define MAXLENGTH 66		/* This filter is for nroff output. */
X#endif
X
X
X#if !defined(LN01) && !defined(LA120) && !defined(LA100)
X#define NROWS	(66*2)
X#define NREPS	10
X#define NCOLS	132
X#define DEFWIDTH 80
X#define MAXWIDTH 132
X#define DEFLENGTH 66
X#define MAXLENGTH 66
X#endif
X
X
X
Xchar buffer[BUFSIZ];		/* CHANGE [1-Nov-84 dsh] */
X
Xchar *page[NROWS][NREPS];	/* NREPS "layers" of pages. */
Xint lastcol[NROWS][NREPS];	/* counter of last used columns on each
X				 * row of the page.
X				 */
X
X
Xint width = DEFWIDTH;
Xint length = DEFLENGTH;
Xint irow, col;
X
Xint  Vpixels;		/* 1/2 character sizes in Vert dir's (LN01) 
X			 * It is 1/2 because each *real* line is counted 
X			 * as 2.  
X			 */
X
Xint indent = 0;		/* indentation. */
Xint literal = (1==0);	/* flag for passing characters literally */
Xint npages = 0;		/* count of number of pages printed */
Xchar *name;		/* users login name */
Xchar *host;		/* his host system name */
Xchar *acctfile;		/* accounting information file */
X
Xextern char *calloc();
X
X/* put_a_char(c, row, col) -- put c into appropriate rep of (row,col)
X *	of page[].  (for output buffering).
X */
Xput_a_char(c, row, col)
Xregister char c;
Xregister int row, col;
X{
X	register int rep, i;
X	
X	for (rep=0; rep<NREPS; rep++) {
X		if (page[row][rep] == (char *)0)
X			page[row][rep] = calloc(sizeof(char), NCOLS);
X		if (page[row][rep][col] == '\0') {
X			for (i=lastcol[row][rep]; i<col && i<(NCOLS-1); i++)
X				page[row][rep][i+1]=' ';
X			lastcol[row][rep] = i;
X			page[row][rep][col] = c;
X/*  fprintf(stderr, "DBG1:%c:col=%d,row=%d,rep=%d\n",page[row][rep][col],col,row,rep);/* DEBUG */
X			break;
X		}
X	}
X}
X
X
X
X
X/* prtpage() -- print the contents of page[]. */
Xprtpage()
X{
X	register int row, rep;
X
X	for (row=1; row<NROWS; row++) {
X		if (page[row][0] == 0)
X			continue;
X		/* Move the cursor to the beginning of the row */
X		printf("\033[%dd", row*Vpixels);
X
X		/* Print the row */
X		for (rep = 0; page[row][rep]!=0 && rep<NREPS; rep++) {
X			printf("%-132s\r", page[row][rep]);
X			free(page[row][rep]);
X			page[row][rep] = 0;
X			lastcol[row][rep] = -1;
X		}
X	}
X	putchar('\f');
X}
X
X
Xspecial()
X{
X	register char c;
X
X	while((c=getchar()) != EOF && c != '\017') {
X		switch(c) {
X		case 'O': /* little theta */
X			put_a_char('0', irow, col);
X			put_a_char('-', irow, col);
X			col++;
X			break;
X		case 'T': /* Big Theta */
X			put_a_char('O', irow, col);
X			put_a_char('=', irow, col);
X			col++;
X			break;
X		case 'D': /* little delta */
X			put_a_char('o', irow, col);
X			put_a_char('`', irow, col);
X			put_a_char('-', irow-1, col);
X			col++;
X			break;
X		case 'Y': /* little sigma */
X			put_a_char('o', irow, col);
X			put_a_char('_', irow-1, col);
X			col++;
X			break;
X		case 'R': /* Big Sigma */
X			put_a_char(')', irow, col);
X			put_a_char('_', irow, col);
X			put_a_char('_', irow-2, col);
X			col++;
X			break;
X		case 'U': /* little phi */
X			put_a_char('o', irow, col);
X			put_a_char('/', irow, col);
X			col++;
X			break;
X		case 'F': /* Big Phi */
X			put_a_char('O', irow, col);
X			put_a_char('|', irow, col);
X			put_a_char('_', irow, col);
X			put_a_char('_', irow-2, col);
X			col++;
X			break;
X		case 'V': /* little psi */
X			put_a_char('u', irow, col);
X			put_a_char('/', irow, col);
X			col++;
X			break;
X		case 'H': /* Big Psi */
X			put_a_char('u', irow, col);
X			put_a_char('|', irow, col);
X			put_a_char('_', irow, col);
X			put_a_char('_', irow-2, col);
X			col++;
X			break;
X#ifdef HARVEYSLOANE
X		/* This one is impossible, but is a pseudo close approximation.
X		 */
X		case 'X': /* little xi */
X			put_a_char('<', irow, col);
X			put_a_char('-', irow, col);
X			put_a_char('`', irow, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		/* Can't make a big Xi even though the printer can make
X		 * a believable one.  (nroff doesn't put anything out for
X		 * big Xi.
X		 */
X#endif
X		case 'J': /* little pi */
X			put_a_char('"', irow-1, col);	
X			put_a_char('_', irow-1, col);
X			col++;
X			break;
X		case 'P': /* Big Pi */
X			put_a_char('(', irow, col);
X			put_a_char(')', irow, col);
X			put_a_char('_', irow-2, col);
X			col++;
X			break;
X		case 'K': /* little rho */
X			put_a_char('p', irow, col);
X			col++;
X			break;
X		case 'I': /* little tau */
X			put_a_char('_', irow-1, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		case 'C': /* little omega */
X			put_a_char('w', irow, col++);
X			break;
X		case 'Z': /* Big Omega */
X			put_a_char('Q', irow, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		case '\\': /* little gamma */
X			put_a_char('/', irow, col);
X			put_a_char('\'', irow, col);
X			col++;
X			break;
X		case 'G': /* Big Gamma */
X			put_a_char('(', irow, col);
X			put_a_char('_', irow-2, col);
X			col++;
X			break;
X#ifdef HARVEYSLOANE
X		case 'A': /* little alpha */
X			put_a_char('o', irow, col);
X			put_a_char('<', irow, col);
X			col++;
X			break;
X#endif
X		case 'B': /* little beta */
X			put_a_char('B', irow, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		case 'L': /* little lambda */
X			put_a_char('\\', irow, col);
X			put_a_char('^', irow+1, col);
X			col++;
X			break;
X		/* Can't make a believable Big Lambda with LN01 */
X		case 'M': /* little mu */
X			put_a_char('u', irow, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		case '@': /* little nu */
X			put_a_char('v', irow, col);
X			col++;
X			break;
X		case 'Q': /* little zeta */
X			put_a_char('(', irow, col);
X			put_a_char('c', irow+1, col);
X			col++;
X			break;
X		case 'N': /* little eta */
X			put_a_char('n', irow, col);
X			put_a_char(',', irow, col);
X			col++;
X			break;
X		case 'S': /* little epsilon */
X			put_a_char('<', irow, col);
X			put_a_char('-', irow, col);
X			col++;
X			break;
X		case '[': /* gradient */
X			put_a_char('v', irow, col);
X			put_a_char('_', irow-1, col);
X			col++;
X			break;
X		default:
X			put_a_char(c, irow, col);
X			col++;
X			break;
X		}
X	}
X}
X		
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register char c, *cp;
X	register int i, j;
X#ifdef LN01
X	int iflag;
X#endif
X
X#ifdef LN01
X	iflag = 0;
X#endif
X	
X	setbuf(stdout, buffer);
X	while (--argc) {
X		if (*(cp = *++argv) == '-') {
X			switch (cp[1]) {
X			case 'n':
X				argc--;
X				name = *++argv;
X				break;
X			case 'h':
X				argc--;
X				host = *++argv;
X				break;
X			case 'w':
X				width = atoi(&cp[2]);
X				break;
X			case 'l':
X				break;
X			case 'i':
X				indent = atoi(&cp[2]);
X#ifdef LN01
X				/* CHANGE [15-Sep-84 dsh]: detect if indent
X				 * actually specified.
X				 */
X				iflag++;
X#endif
X				break;
X			case 'c':
X				literal++;
X				break;
X			default:
X				break;
X			}
X		}
X		else
X			acctfile = cp;
X	}
X	
X	for (i=0; i<NROWS; i++) {
X		for (j=0; j<NREPS; j++) {
X			lastcol[i][j] = -1;
X			page[i][j] = 0;
X		}
X	}
X
X
X#ifdef LN01
X	/* CHANGE [15-Sep-84 dsh]: add initialization depending on width. */
X	/* CHANGE [6-Oct-84 dsh]:  Have it decide character cell sizes */
X	if (width > 80) {
X		/* landscape format */
X		printf("\033c");	/* reset */
X		printf("\033[10m");	/* landscape format */
X		Vpixels = 17;
X	}
X	else if (!iflag) {
X		/* nportrait format */
X		printf("\033c");	/* reset */
X		printf("\033[11m");	/* portrait format */
X		printf("\033[325s");	/* scooted over */
X		printf("\033[3300t");	/* 11 inch page */
X		printf("\033[0;3300r");/* and margins coincide with that */
X		Vpixels = 25;
X	}
X	else {
X		/* portrait format */
X		printf("\033c");	/* reset */
X		printf("\033[11m");	/* portrait format */
X		printf("\033[3300t");	/* 11 inch page */
X		printf("\033[0;3300r");/* and margins to match */
X					/* note that this isn't scooted over. */
X		Vpixels = 25;
X	}
X	printf("\033[0`");		/* set horizontal position absolute */
X	printf("\033[0d");		/* set vertical position absolute */
X#endif
X	col = indent;
X	irow = 1;
X
X
X	while ((c=getchar()) != EOF) {
X		switch (c) {
X		case '\r':
X			col = indent;
X			break;
X		case '\n':
X			col = indent;
X			irow += 2;
X			break;
X		case '\f':
X			col = indent;
X			irow = 1;
X			prtpage();
X			npages++;
X			break;
X		case '\b':
X			--col;
X			break;
X		case '\t':
X			for (i=col+(8-(col%8)); col<i; col++)
X				put_a_char(' ', irow, col);
X			break;
X		case '\016':	/* SO, start a funny character sequence */
X			special();
X			break;
X		case '\033':
X			switch (c=getchar()) {
X			case '7':
X				irow -= 2;
X				break;
X			case '8':
X				irow--;
X				break;
X			case '9':
X				irow++;
X				break;
X			default:
X				ungetc(c, stdin);
X				c = '\033';
X				goto putit;
X			}
X			break;
X		default:
Xputit:
X			if (c >= ' ') {
X				put_a_char(c, irow, col);
X				col++;
X			}
X			break;
X		} /* switch */
X		if (col < 0) col = indent;
X		if (col > NCOLS) col = NCOLS - 1;
X		if (irow < 0) irow = 0;
X		if (irow >= NROWS) {
X			prtpage();
X			col = indent;
X			irow = 1;
X			npages++;
X		}
X		
X	} /* while */
X	
X	
X	/* Flush any remaining output */
X	for (i=0; i<NROWS; i++)
X		if (page[i][0] != 0)
X			break;
X	if (i<NROWS) {
X		prtpage();
X		npages++;
X	}
X	
X#ifdef LN01
X	/* CHANGE [20-Sep-84 dsh]: Idea is to cause an orientation change
X	 * which SHOULD cause the last page to come out.
X	 */
X	sleep(2);
X	if (width <= 80) {
X		/* temporarily set landscape */
X		printf("\033c\033[10m");
X	}
X	else {
X		/* Set to nportrait. */
X		printf("\033c");	/* reset */
X		printf("\033[11m");	/* portrait font */
X		printf("\033[325s");	/* scooted over about 1.1 inches */
X		printf("\033[3300t");	/* length of page is 1100 inches */
X		printf("\033[0;3300r");/* top and bottom margins coincide with
X					 * top and bottom of page
X					 */
X	}
X#endif
X	fflush(stdout);
X	
X	if (name && acctfile && access(acctfile, 02) >= 0 &&
X		freopen(acctfile, "a", stdout) != NULL) {
X			printf("%7.2f\t%s:%s\n", (float)npages,
X				host, name);
X	}
X	exit(0);
X	/*NOTREACHED*/
X}
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l nrpf.c
echo x - scanargs.c '		' '-rw-r--r--  1 david        5107 Dec  6 19:55 scanargs.c'
sed 's/^X//' > scanargs.c <<'EOF-OF-THIS-FILE'
X/* scanargs() -- scan through a string for lpr command-line options.
X */
X
X#define iswhite(c)	((c) == ' ' || (c) == '\t')
X#define skipwhite(s)	for(; iswhite(*(s)); (s)++) /*NULL*/ ;
X
Xint scanargs (arg, nxtarg)
Xchar *arg, *nxtarg;
X{
X    int rv = 0;			/* flag to say that we "used" nxtarg */
X
X    skipwhite(arg);
X    while (*arg == '-') {
X	++arg;
X	switch (*arg) {
X
X	    case 'P': 		/* specifiy printer name */
X		stringop(&arg, nxtarg, printer, &rv);
X		break;
X
X	    case 'C': 		/* classification spec */
X		hdr++;
X		stringop (&arg, nxtarg, class, &rv);
X		break;
X
X	    case 'J': 		/* job name */
X		hdr++;
X		stringop(&arg, nxtarg, jobname, &rv);
X		break;
X
X	    case 'T': 		/* pr's title line */
X		stringop(&arg, nxtarg, title, &rv);
X		break;
X
X	    case 'l': 		/* literal output */
X	    case 'p': 		/* print using ``pr'' */
X	    case 't': 		/* print troff output (cat files) */
X	    case 'n': 		/* print ditroff output */
X	    case 'd': 		/* print tex output (dvi files) */
X	    case 'g': 		/* print graph(1G) output */
X	    case 'c': 		/* print cifplot output */
X	    case 'v': 		/* print vplot output */
X		format = *arg++;
X		break;
X
X	    case 'f': 		/* print fortran output */
X		format = 'r';
X		++arg;
X		break;
X
X	    case '4': 		/* troff fonts */
X	    case '3': 
X	    case '2': 
X	    case '1': 
X		c = *arg;
X		stringop(&arg, nxtarg, fonts[c - '1'], &rv);
X		break;
X
X	    case 'w': 		/* versatec page width */
X		stringop(&arg, nxtarg, width, &rv);
X		break;
X
X	    case 'L': 		/* page length (LA120) CHANGE: dsh 30JAN */
X		stringop(&arg, nxtarg, length, &rv);
X		break;
X
X	    case 'r': 		/* remove file when done */
X		rflag++;
X		++arg;
X		break;
X
X	    case 'm': 		/* send mail when done */
X		mailflg++;
X		++arg;
X		break;
X
X	    case 'h': 		/* toggle want of header page */
X		hdr = !hdr;
X		++arg;
X		break;
X
X	    case 's': 		/* try to link files */
X		sflag++;
X		++arg;
X		break;
X
X	    case 'q': 		/* just q job */
X		qflag++;
X		++arg;
X		break;
X
X	    case 'i': 		/* indent output */
X		iflag++;
X		indent = 8;	/* default value */
X		{
X			char is[15];
X			stringop(&arg, nxtarg, is, &rv);
X			if (isdigit(*is)) indent = atoi(is);
X		}
X		break;
X
X	    case '#': 		/* n copies */
X		{
X			char is[15];
X			stringop(&arg, nxtarg, is, &rv);
X			if (isdigit(*is)) i = atoi(is);
X		}
X		if (i > 0)
X		    ncopies = i;
X		break;
X	}
X	skipwhite(arg);
X    }
X}
X
X/* stringop() -- do scanning for options which take a string value.
X *
X * Syntax is scanned as follows:
X *
X *	1. already scanned is "-x" where "x" is an option letter.
X *	2. skip white space (if any)
X *	3. If this argument ran out (defined by seeing the "-" for
X *	   the start of the next option, or a '\0' for end-of-string),
X *	   goto 5.
X *	4. (found a value attached to this argument).  Move the pointer to
X *	   the end of the value, and copy it to the buffer pointed to by 
X *	   "option".  goto 6.
X *	5. (did not find a value attached to this argument, 
X *	    might be in "nxtarg").  If there is something in nxtarg, use
X *	    that for the value and set rv.  otherwise, nothing is changed
X *	   anywhere.
X *	6. done.  return.
X *
X * rg:		pointer to "arg" in scanargs().
X * nxarg:	same as "rg" but for "nxtarg".
X * option:	pointer to the buffer to store the value in.
X * rv:		pointer to "rv" in scanargs().
X */
Xstringop(rg, nxarg, option, rv)
Xchar **rg, *nxtarg, *option;
Xint *rv;
X{
X	char *arg = *rg;
X
X	*rv = 0;
X	for (++arg; *arg == ' ' || *arg == '\t'; ++arg)
X		/* NULL */
X		    ;
X	if (*arg == '-' || *arg == '\0')
X	    if (nxtarg) {
X		if(*nxtarg != '-')
X			option = nxtarg;
X		else
X			*option = '\0';
X		*rv = 1;
X	    }
X	    else {
X		/* NULL */
X	    }
X	else {	/* grab a token.  the token can be quoted and can
X		 * include backslashes to insert strange characters.
X		 */
X		char *cp = option, c;
X
X			/* start state. */
X		state1:	c = *arg++;
X			if (iswhite(c)) goto state1;
X			else if (c == '"') goto state2;
X			else if (c == '\'') goto state6;
X			else if (c == '\0' || c == '-') goto state5;
X			else goto state9;
X
X			/* scan a string quoted with double-quotes. */
X		state2:	c = *arg++;
X			if (c == '"' || c == '\0') goto state5;
X			else goto state3;
X
X			/* interior part of double-quoted string. */
X		state3:	*cp++ = c;
X			c = *arg++;
X			if (c == '"' || c == '\0') goto state5;
X			else if (c == '\\') goto state4;
X			else goto state3;
X
X			/* backslash handling for double-quoted string. */
X		state4:	c = *arg++;
X			goto state3;
X
X			/* general purpose done state. */
X		state5:	*cp++ = '\0';
X			goto done;
X
X			/* scan a string quoted with single-quotes. */
X		state6:	c = *arg++;
X			if (c == '\'' || c == '\0') goto state5;
X			else goto state7;
X
X			/* interior part of singly-quoted string. */
X		state7:	*cp++ = c;
X			c = *arg++;
X			if (c == '\'' || c == '\0') goto state5;
X			else if (c == '\\') goto state8;
X			else goto state7;
X
X			/* handle backslashes. */
X		state8:	c = *arg++;
X			goto state7;
X
X			/* token which is not quoted. */
X		state9:	*cp++ = c;
X			c = *arg++;
X			if (c == '\0' || iswhite(c)) goto state5;
X			else if (c == '\\') goto state10;
X			else goto state9;
X
X			/* handle backslashes for unquoted token. */
X		state10: c = *arg++;
X			goto state9;
X
X	}
Xdone:
X	*rg = arg;
X}
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l scanargs.c
echo x - stringop.c '		' '-rw-r--r--  1 david        2855 Dec  6 19:54 stringop.c'
sed 's/^X//' > stringop.c <<'EOF-OF-THIS-FILE'
X/* stringop() -- do scanning for options which take a string value.
X *
X * Syntax is scanned as follows:
X *
X *	1. already scanned is "-x" where "x" is an option letter.
X *	2. skip white space (if any)
X *	3. If this argument ran out (defined by seeing the "-" for
X *	   the start of the next option, or a '\0' for end-of-string),
X *	   goto 5.
X *	4. (found a value attached to this argument).  Move the pointer to
X *	   the end of the value, and copy it to the buffer pointed to by 
X *	   "option".  goto 6.
X *	5. (did not find a value attached to this argument, 
X *	    might be in "nxtarg").  If there is something in nxtarg, use
X *	    that for the value and set rv.  otherwise, nothing is changed
X *	   anywhere.
X *	6. done.  return.
X *
X * rg:		pointer to "arg" in scanargs().
X * nxarg:	same as "rg" but for "nxtarg".
X * option:	pointer to the buffer to store the value in.
X * rv:		pointer to "rv" in scanargs().
X */
Xstringop(rg, nxtarg, option)
Xchar **rg, *nxtarg, *option;
X{
X	char *arg = *rg;
X	int rv;
X
X	rv = 0;
X	for (++arg; *arg == ' ' || *arg == '\t'; ++arg)
X		/* NULL */
X		    ;
X	printf("arg:[%s], nxtarg:[%s]\n", arg, nxtarg);
X	if (*arg == '-' || *arg == '\0')
X	    if (nxtarg) {
X		if(*nxtarg != '-')
X			strcpy(option, nxtarg);
X		else
X			*option = '\0';
X		rv = 1;
X	    }
X	    else {
X		/* NULL */
X	    }
X	else {	/* grab a token.  the token can be quoted and can
X		 * include backslashes to insert strange characters.
X		 */
X		char *cp = option, c;
X
X			/* start state. */
X		state1:	c = *arg++;
X			if (iswhite(c)) goto state1;
X			else if (c == '"') goto state2;
X			else if (c == '\'') goto state6;
X			else if (c == '\0' || c == '-') goto state5;
X			else goto state9;
X
X			/* scan a string quoted with double-quotes. */
X		state2:	c = *arg++;
X			if (c == '"' || c == '\0') goto state5;
X			else goto state3;
X
X			/* interior part of double-quoted string. */
X		state3:	*cp++ = c;
X			c = *arg++;
X			if (c == '"' || c == '\0') goto state5;
X			else if (c == '\\') goto state4;
X			else goto state3;
X
X			/* backslash handling for double-quoted string. */
X		state4:	c = *arg++;
X			goto state3;
X
X			/* general purpose done state. */
X		state5:	*cp++ = '\0';
X			goto done;
X
X			/* scan a string quoted with single-quotes. */
X		state6:	c = *arg++;
X			if (c == '\'' || c == '\0') goto state5;
X			else goto state7;
X
X			/* interior part of singly-quoted string. */
X		state7:	*cp++ = c;
X			c = *arg++;
X			if (c == '\'' || c == '\0') goto state5;
X			else if (c == '\\') goto state8;
X			else goto state7;
X
X			/* handle backslashes. */
X		state8:	c = *arg++;
X			goto state7;
X
X			/* token which is not quoted. */
X		state9:	*cp++ = c;
X			c = *arg++;
X			if (c == '\0' || iswhite(c)) goto state5;
X			else if (c == '\\') goto state10;
X			else goto state9;
X
X			/* handle backslashes for unquoted token. */
X		state10: c = *arg++;
X			goto state9;
X
X	}
Xdone:
X	*rg = arg;
X	return(rv);
X}
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l stringop.c
echo x - lpd.c.diff '		' '-rw-r--r--  1 david        1512 Dec  6 19:51 lpd.c.diff'
sed 's/^X//' > lpd.c.diff <<'EOF-OF-THIS-FILE'
X*** lpd.c.orig	Mon Jul 23 20:25:04 1984
X--- lpd.c	Mon Jul 23 20:35:08 1984
X***************
X*** 33,42
X   *	3. Files in spooling area are owned by root, group spooling
X   *	   group, with mode 660.
X   *	4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
X   *	   access files and printer.  Users can't get to anything
X   *	   w/o help of lpq and lprm programs.
X   */
X  
X  #include "lp.h"
X  
X  static int	lflag;				/* log requests flag */
X
X--- 33,45 -----
X   *	3. Files in spooling area are owned by root, group spooling
X   *	   group, with mode 660.
X   *	4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
X   *	   access files and printer.  Users can't get to anything
X   *	   w/o help of lpq and lprm programs.
X+  *
X+  * CHANGES:
X+  *---	[23-Jul-84 dsh]: set nice level lower.
X   */
X  
X  #include "lp.h"
X  
X  static int	lflag;				/* log requests flag */
X***************
X*** 52,61
X  	int f, funix, finet, options, defreadfds, fromlen;
X  	struct sockaddr_un sun, fromunix;
X  	struct sockaddr_in sin, frominet;
X  	int omask, lfd;
X  
X  	gethostname(host, sizeof(host));
X  	name = argv[0];
X  
X  	while (--argc > 0) {
X  		argv++;
X
X--- 55,66 -----
X  	int f, funix, finet, options, defreadfds, fromlen;
X  	struct sockaddr_un sun, fromunix;
X  	struct sockaddr_in sin, frominet;
X  	int omask, lfd;
X  
X+ 	/* CHANGE [23-Jul-84 dsh]: set priority */
X+ 	setpriority(0 /*PRIO_PROCESS*/, getpid(), 9);
X  	gethostname(host, sizeof(host));
X  	name = argv[0];
X  
X  	while (--argc > 0) {
X  		argv++;
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l lpd.c.diff
echo x - lpf.c.diff '		' '-rw-r--r--  1 david       25158 Dec  6 19:52 lpf.c.diff'
sed 's/^X//' > lpf.c.diff <<'EOF-OF-THIS-FILE'
X*** lpf.c.orig	Sun Jul 17 02:53:21 1983
X--- lpf.c	Thu Nov  8 18:15:34 1984
X***************
X*** 9,18
X   *	and it is written with some style.
X   *	modified by kls to use register references instead of arrays
X   *	to try to gain a little speed.
X   */
X  
X  #include <stdio.h>
X  #include <signal.h>
X  
X  #define MAXWIDTH  132
X  #define MAXREP    10
X
X--- 9,96 -----
X   *	and it is written with some style.
X   *	modified by kls to use register references instead of arrays
X   *	to try to gain a little speed.
X   */
X  
X+ /* CHANGES:
X+  *--	changed MAXWIDTH to 217 (had been 200). (dsh 19JAN84)
X+  *--	Added code between "#ifdef LA120...#endif", which sets the form
X+  *	sizes on the LA-120 automatically. (dsh 19JAN84)
X+  *--	There had been a problem with print width changing.  It would
X+  *	happen when a filter got interupted in the middle to print
X+  *	someone elses job.  When it went back to the original job
X+  *	the printer would not have the proper spacing.  Fix is to
X+  *	have filter reset spacings after it starts back up again.
X+  *	[dsh 24JAN84]
X+  *--	Enforced strict checking of MAXWIDTH and MAXLENGTH.
X+  *	[dsh 19MAR84]
X+  *--	Problem: Sometimes the printer would end up in the middle of
X+  *	a page, causing problems for later print jobs.  This would
X+  *	only happen AFTER the end of a print job.  It was noticed 
X+  *	that this was happening for files which print more than 
X+  *	once on the same line (i.e. backspacing for bold print and
X+  *	underlining).
X+  *	Diagnosis: The loop which printed out each line executed once
X+  *	for each for each pass on the line required.  (i.e. bold face
X+  *	required 3 or 4 passes, the loop executed 3 or 4 times).  For
X+  *	each time through this loop, the line counter was incremented.
X+  *	So, anytime a line required overprinting it messed up the line
X+  *	count, causing lpf to think that the printer was in the middle
X+  *	of the page when it acually wasn't.
X+  *	Fix: move the increment outside of that loop.
X+  *	[7-Jun-84 dsh]
X+  *--	Problem: After fixing the above problem, it was noticed that
X+  *	the printout was being shorted by one line.
X+  *	This was happening with a file of exactly 132 lines.  The file
X+  *	was being given most of an extra page as if it had 133 lines.
X+  *	(the output was 197 lines, the last 65 being blank lines).
X+  *	Diagnosis: Lpf was acting as if EOF were a line.  Upon seeing
X+  *	EOF, it went ahead and incremented the line counter.  This was
X+  *	also messing up the line count (by 1), causing the filter to
X+  *	think that the printer was at a place that it wasn't at.
X+  *	Fix: When EOF is seen, decrement the line counter so that
X+  *	later when it is incremented it will have the proper value.
X+  *	[7-Jun-84 dsh]
X+  *--	Problem: The LN01 sometimes does not flush the last page
X+  *	of a print job.  Also, it would be nice to specify a wider
X+  *	width (for LN01) (say, 132 columns) and automatically have
X+  *	the printout come in landscape format instead of portrait.
X+  *	Fix: pull code from Brian's programs, and insert them at
X+  *	appropriate places.
X+  *	(Brians programs are "nportrait.c", "portrait.c", and "landscape.c")
X+  *	[9-Jul-84 dsh]
X+  *--	Problem: The LN01 still fails to flush the last page
X+  *	on occasion.
X+  *	Fix: Added a delay of 10 seconds between end of the
X+  *	print job and sending the portrait code.
X+  *--	[6-Sep-84 dsh]: Made program follow documentation (for LN01),
X+  *	i.e. change to portrait if indent==0.  Also added flag to show
X+  *	that the format WAS changed.
X+  *--	[12-Sep-84 dsh]: A copy of the LN01 manual was (finally) obtained
X+  *	from Brian.  The code to select portrait, nportrait and landscape
X+  *	was corrected.  In particular these sections were found to be
X+  *	the cause of the extra pages of printout.
X+  *--	[15-Sep-84 dsh]: Conclusion of the 12-Sep editing.  The following
X+  *	changes were made (all changes relate to LN01):
X+  *	1) Made portrait format the default.
X+  *	2) Removed the flag to show that the format was changed.  The reason
X+  *	   for this had been that a format change was printing out a page
X+  *	   of paper.  This was discovered to be caused by Brian's faulty
X+  *	   escape sequences.
X+  *	3) All lines going out to the laser printer get padded to the width
X+  *	   of the printout.  This more than any other factor made sure the
X+  *	   last page of a print job flushed properly.  The sleep was found
X+  *	   to (no longer anyway) have much if any effect.  The flushing
X+  * 	   was more dependant on the length of the lines of printout than
X+  *	   anything else.
X+  *	4) nportrait mode is being made the default for nrlp0. (nrpf.c)
X+  *--- [1-Nov-84 dsh]: Set buffering on stdout.  (See comment in nrpf.c)
X+  *--- [8-Nov-84 dsh]: Fix it for the spinwriter.  For the spinwriter
X+  *	we basically need to just let things through.  We need to count
X+  *	newlines for accounting, and set the tab stops.
X+  */
X+ 
X  #include <stdio.h>
X  #include <signal.h>
X  
X  
X  
X***************
X*** 12,22
X   */
X  
X  #include <stdio.h>
X  #include <signal.h>
X  
X! #define MAXWIDTH  132
X  #define MAXREP    10
X  
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X  int	lineno;
X
X--- 90,129 -----
X   */
X  
X  #include <stdio.h>
X  #include <signal.h>
X  
X! 
X! 
X! #ifdef LA120
X! #define MAXWIDTH  217	/* max. size of la120 (16 chr/in * 13.2 in). */
X! #define DEFWIDTH  217
X! #define MAXLENGTH 132	/* LA120 can print 132 lines on a page */
X! #define DEFLENGTH  66
X! #define DEFINDENT   0
X! #endif
X! #ifdef LN01
X! #define MAXWIDTH 132
X! #define DEFWIDTH  80
X! #define MAXLENGTH 66
X! #define DEFLENGTH 66
X! #define DEFINDENT  0
X! #endif
X! #ifdef SPINWRITER
X! #define MAXWIDTH 132
X! #define DEFWIDTH  80
X! #define MAXLENGTH 66
X! #define DEFLENGTH 66
X! #define DEFINDENT  0
X! #endif
X! #if !defined(LN01) && !defined(LA120) && !defined(LA100) && !defined(SPINWRITER)
X! #define MAXWIDTH 132
X! #define DEFWIDTH  80
X! #define MAXLENGTH 66
X! #define DEFLENGTH 66
X! #define DEFINDENT  0
X! #endif
X  #define MAXREP    10
X  
X  char	buffer[BUFSIZ];		/* CHANGE [1-Nov-84 dsh] */
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X***************
X*** 15,24
X  #include <signal.h>
X  
X  #define MAXWIDTH  132
X  #define MAXREP    10
X  
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X  int	lineno;
X  int	width = 132;	/* default line length */
X  int	length = 66;	/* page length */
X
X--- 122,132 -----
X  #define DEFLENGTH 66
X  #define DEFINDENT  0
X  #endif
X  #define MAXREP    10
X  
X+ char	buffer[BUFSIZ];		/* CHANGE [1-Nov-84 dsh] */
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X  int	lineno;
X  int	width = DEFWIDTH;   /* default line length */
X  int	length = DEFLENGTH; /* page length */
X***************
X*** 18,31
X  #define MAXREP    10
X  
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X  int	lineno;
X! int	width = 132;	/* default line length */
X! int	length = 66;	/* page length */
X! int	indent;		/* indentation length */
X! int	npages = 1;
X  int	literal;	/* print control characters */
X  char	*name;		/* user's login name */
X  char	*host;		/* user's machine name */
X  char	*acctfile;	/* accounting information file */
X  
X
X--- 126,139 -----
X  
X  char	buffer[BUFSIZ];		/* CHANGE [1-Nov-84 dsh] */
X  char	buf[MAXREP][MAXWIDTH];
X  int	maxcol[MAXREP] = {-1};
X  int	lineno;
X! int	width = DEFWIDTH;   /* default line length */
X! int	length = DEFLENGTH; /* page length */
X! int	indent = DEFINDENT; /* indentation length */
X! int	npages = 0;
X  int	literal;	/* print control characters */
X  char	*name;		/* user's login name */
X  char	*host;		/* user's machine name */
X  char	*acctfile;	/* accounting information file */
X  
X***************
X*** 27,36
X  int	literal;	/* print control characters */
X  char	*name;		/* user's login name */
X  char	*host;		/* user's machine name */
X  char	*acctfile;	/* accounting information file */
X  
X  main(argc, argv) 
X  	int argc;
X  	char *argv[];
X  {
X  	register FILE *p = stdin, *o = stdout;
X
X--- 135,182 -----
X  int	literal;	/* print control characters */
X  char	*name;		/* user's login name */
X  char	*host;		/* user's machine name */
X  char	*acctfile;	/* accounting information file */
X  
X+ 
X+ 
X+ #ifdef LA120
X+ struct sztosp { /* form size to spacing. */
X+ 	int size;		/* number of positions in dimension. */
X+ 	int spacing;		/* number of positions per inch. */
X+ 	char *string;		/* string to set that mode. */
X+ };
X+ 
X+ struct sztosp flength[] = { /* for 11 inch long forms. */
X+ 	 22, 2,"\033[4z\033[22t",
X+ 	 33, 3,"\033[5z\033[33t",
X+ 	 44, 4,"\033[6z\033[44t",
X+ 	 66, 6,"\033[1z\033[66t",
X+ 	 88, 8,"\033[2z\033[88t",
X+ 	132,12,"\033[3z\033[132t",
X+ 	-1,0,"\033[1z\033[66t"	/* default: 66 lines/page */
X+ };
X+ #define FINALENGTH	"\033[1z\033[66t"
X+ 
X+ struct sztosp fwidth[] = { /* for 13.2 inch wide forms. */
X+ 			/* number of spaces on 8 inch wide forms. */
X+ 	 66, 5,"\033[5w",	/*  40 */
X+ 	 79, 6,"\033[6w",	/*  48 */
X+ 	 87, 7,"\033[7w",	/*  52 */
X+ 	108, 8,"\033[8w",	/*  66 */
X+ 	132,10,"\033[1w",	/*  80 */
X+ 	158,12,"\033[2w",	/*  96 */
X+ 	174,13,"\033[3w",	/* 105 */
X+ 	217,16,"\033[4w",	/* 132 */
X+ 	-1,0,"\033[4w"		/* default: 16 chars/inch */
X+ };
X+ #define FINALWIDTH	"\033[1w"	/* set it to this when done. */
X+ #endif /* LA120 */
X+ 
X+ 
X+ 
X+ 
X  main(argc, argv) 
X  	int argc;
X  	char *argv[];
X  {
X  	register FILE *p = stdin, *o = stdout;
X***************
X*** 32,42
X  main(argc, argv) 
X  	int argc;
X  	char *argv[];
X  {
X  	register FILE *p = stdin, *o = stdout;
X! 	register int i, col;
X  	register char *cp;
X  	int done, linedone, maxrep;
X  	char ch, *limit;
X  
X  	while (--argc) {
X
X--- 178,188 -----
X  main(argc, argv) 
X  	int argc;
X  	char *argv[];
X  {
X  	register FILE *p = stdin, *o = stdout;
X! 	register int i, j, col;
X  	register char *cp;
X  	int done, linedone, maxrep;
X  	char ch, *limit;
X  	register struct sztosp *tblp;
X  #ifdef LA120
X***************
X*** 36,45
X  	register FILE *p = stdin, *o = stdout;
X  	register int i, col;
X  	register char *cp;
X  	int done, linedone, maxrep;
X  	char ch, *limit;
X  
X  	while (--argc) {
X  		if (*(cp = *++argv) == '-') {
X  			switch (cp[1]) {
X  			case 'n':
X
X--- 182,196 -----
X  	register FILE *p = stdin, *o = stdout;
X  	register int i, j, col;
X  	register char *cp;
X  	int done, linedone, maxrep;
X  	char ch, *limit;
X+ 	register struct sztosp *tblp;
X+ #ifdef LA120
X+ 	char *widthstring,*lengthstring; /* saves setting strings. CHANGE */
X+ 	int actualength;
X+ #endif
X  
X  	setbuf(stdout, buffer);		/* CHANGE [1-Nov-84 dsh] */
X  	while (--argc) {
X  		if (*(cp = *++argv) == '-') {
X  			switch (cp[1]) {
X***************
X*** 37,46
X  	register int i, col;
X  	register char *cp;
X  	int done, linedone, maxrep;
X  	char ch, *limit;
X  
X  	while (--argc) {
X  		if (*(cp = *++argv) == '-') {
X  			switch (cp[1]) {
X  			case 'n':
X  				argc--;
X
X--- 188,198 -----
X  #ifdef LA120
X  	char *widthstring,*lengthstring; /* saves setting strings. CHANGE */
X  	int actualength;
X  #endif
X  
X+ 	setbuf(stdout, buffer);		/* CHANGE [1-Nov-84 dsh] */
X  	while (--argc) {
X  		if (*(cp = *++argv) == '-') {
X  			switch (cp[1]) {
X  			case 'n':
X  				argc--;
X***************
X*** 56,66
X  				if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
X  					width = i;
X  				break;
X  
X  			case 'l':
X! 				length = atoi(&cp[2]);
X  				break;
X  
X  			case 'i':
X  				indent = atoi(&cp[2]);
X  				break;
X
X--- 208,223 -----
X  				if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
X  					width = i;
X  				break;
X  
X  			case 'l':
X! 				/* CHANGE: [dsh 18MAR84] make sure that
X! 				 * length stays within
X! 				 *	0 <= length <= MAXLENGTH.
X! 				 */
X! 				if ((i=atoi(&cp[2]))>0 && i<=MAXLENGTH)
X! 					length = i;
X  				break;
X  
X  			case 'i':
X  				indent = atoi(&cp[2]);
X  				break;
X***************
X*** 71,81
X  			}
X  		} else
X  			acctfile = cp;
X  	}
X  
X! 	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
X  	done = 0;
X  	
X  	while (!done) {
X  		col = indent;
X  		maxrep = -1;
X
X--- 228,241 -----
X  			}
X  		} else
X  			acctfile = cp;
X  	}
X  
X! #ifndef SPINWRITER
X! 	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ')
X! 			/* NULL */
X! 			    ;
X  	done = 0;
X  #endif
X  
X  #ifdef LA120	/* CHANGE */
X  	for(tblp= &flength[0];length>tblp->size&&tblp->size!=-1;tblp++)
X***************
X*** 73,82
X  			acctfile = cp;
X  	}
X  
X  	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
X  	done = 0;
X  	
X  	while (!done) {
X  		col = indent;
X  		maxrep = -1;
X  		linedone = 0;
X
X--- 233,317 -----
X  #ifndef SPINWRITER
X  	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ')
X  			/* NULL */
X  			    ;
X  	done = 0;
X+ #endif
X+ 
X+ #ifdef LA120	/* CHANGE */
X+ 	for(tblp= &flength[0];length>tblp->size&&tblp->size!=-1;tblp++)
X+ 		/* null */;
X+ 	printf("%s",tblp->string);
X+ 	actualength = tblp->size;
X+         lengthstring = tblp->string;
X+ 	for(tblp= &fwidth[0];width>tblp->size&&tblp->size!=-1;tblp++)
X+ 		/* null */;
X+ 	printf("%s",tblp->string);
X+         widthstring = tblp->string;
X+ #endif
X+ #ifdef LN01
X+ 	/* CHANGE [9-Jul-84 dsh]: from landscape.c */
X+ 	if (width > 80) {
X+ 		/* ESC c: Reset to Internal State.
X+ 		 * Landscape is font #10, and portrait is #11.
X+ 		 */
X+ 		printf("\033c");
X+ 		/* ESC [ # m.  Select Graphic Rendition. 
X+ 		 * #=10 means Invoke primary font (landscape).
X+ 		 */
X+ 		printf("\033[10m");
X+ 	}
X+ 	/* CHANGE [6-Sep-84 dsh]: from portrait.c */
X+ 	/* CHANGE [15-Sep-84 dsh]: make this the default */
X+ 	else {
X+ 		printf("\033c");
X+ 		printf("\033[11m"); /* Select font (portrait) */
X+ 		printf("\033[3300t"); /* Set Lines per Physical Page */
X+ 		printf("\033[0;3300r"); /* Select top and bottom margins
X+ 					 * to be the exact top and bottom
X+ 					 * of the page.
X+ 					 */
X+ 	}
X+ 	/* CHANGE [15-Sep-84 dsh]: make sure we start at the top of the page */
X+ 	printf("\033[0`");	/* Set Horizontal Position Absolute */
X+ 	printf("\033[0d");	/* Set Vertical Position Absolute */
X+ #endif LN01
X+ 
X+ #ifdef SPINWRITER
X+ 
X+ 	/* CHANGE [8-Nov-84 dsh]: initialize the printer */
X+ 	printf("\0337");	/* clear all tabs and FF length */
X+ 	printf("\0334");	/* print in black */
X+ 	printf("\033>");	/* forward print on */
X+ 	printf("\033?");	/* set format mode, inhibits paper movement */
X+ 	for (i=0; i<66; i++)
X+ 		putchar('\n');	/* set form length */
X+ 	printf("\033@\r");	/* reset format mode */
X+ 	printf("\033L\r");	/* establishes form length */
X+ 	for (i=0; i<width; i++)
X+ 		if ( (i%8) == 0 )
X+ 			printf("\0331 "); /* set all tab stops */
X+ 		else
X+ 			putchar(' ');
X+ 	printf("\0331\r");	/* Set a tab stop at the edge of the paper. */
X+ 	putchar('\017');	/* SI */
X+ 
X+ 	lineno = 0;
X+ 
X+ 	while ((ch=getchar()) != EOF) {
X+ 		putchar(ch);
X+ 		if (ch == '\n') {
X+ 			lineno++;
X+ 			for (i=0; i<indent; i++)
X+ 				putchar(' ');
X+ 		}
X+ 	}
X+ 	npages = (lineno/66) + 1;
X+ 
X+ #else /* i.e. not SPINWRITER */
X+ 
X+ 	lineno = 0;
X  	
X  	while (!done) {
X  		col = indent;
X  		maxrep = -1;
X  		linedone = 0;
X***************
X*** 83,92
X  		while (!linedone) {
X  			switch (ch = getc(p)) {
X  			case EOF:
X  				linedone = done = 1;
X  				ch = '\n';
X  				break;
X  
X  			case '\f':
X  				lineno = length;
X  			case '\n':
X
X--- 318,330 -----
X  		while (!linedone) {
X  			switch (ch = getc(p)) {
X  			case EOF:
X  				linedone = done = 1;
X  				ch = '\n';
X+ 				lineno--; /* CHANGE 7-Jun-84 dsh: had
X+ 					   * been counting too far.
X+ 					   */
X  				break;
X  
X  			case '\f':
X  				lineno = length;
X  			case '\n':
X***************
X*** 103,113
X  			case '\r':
X  				col = indent;
X  				break;
X  
X  			case '\t':
X! 				col = ((col - indent) | 07) + indent + 1;
X  				break;
X  
X  			case '\031':
X  				/*
X  				 * lpd needs to use a different filter to
X
X--- 341,351 -----
X  			case '\r':
X  				col = indent;
X  				break;
X  
X  			case '\t':
X! 				col = ((col-indent)|07) + indent + 1;
X  				break;
X  			
X  			case '\031':
X  				/*
X  				 * lpd needs to use a different filter
X***************
X*** 105,115
X  				break;
X  
X  			case '\t':
X  				col = ((col - indent) | 07) + indent + 1;
X  				break;
X! 
X  			case '\031':
X  				/*
X  				 * lpd needs to use a different filter to
X  				 * print data so stop what we are doing and
X  				 * wait for lpd to restart us.
X
X--- 343,353 -----
X  				break;
X  
X  			case '\t':
X  				col = ((col-indent)|07) + indent + 1;
X  				break;
X! 			
X  			case '\031':
X  				/*
X  				 * lpd needs to use a different filter
X  				 * to print data so stop what we are
X  				 * doing and wait for lpd to restart us.
X***************
X*** 108,120
X  				col = ((col - indent) | 07) + indent + 1;
X  				break;
X  
X  			case '\031':
X  				/*
X! 				 * lpd needs to use a different filter to
X! 				 * print data so stop what we are doing and
X! 				 * wait for lpd to restart us.
X  				 */
X  				if ((ch = getchar()) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					break;
X
X--- 346,358 -----
X  				col = ((col-indent)|07) + indent + 1;
X  				break;
X  			
X  			case '\031':
X  				/*
X! 				 * lpd needs to use a different filter
X! 				 * to print data so stop what we are
X! 				 * doing and wait for lpd to restart us.
X  				 */
X  				if ((ch = getc(p)) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					/* come here when received SIGCONT */
X***************
X*** 112,122
X  				/*
X  				 * lpd needs to use a different filter to
X  				 * print data so stop what we are doing and
X  				 * wait for lpd to restart us.
X  				 */
X! 				if ((ch = getchar()) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					break;
X  				} else {
X  					ungetc(ch, stdin);
X
X--- 350,360 -----
X  				/*
X  				 * lpd needs to use a different filter
X  				 * to print data so stop what we are
X  				 * doing and wait for lpd to restart us.
X  				 */
X! 				if ((ch = getc(p)) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					/* come here when received SIGCONT */
X  #ifdef LA120
X  					printf("%s",widthstring); /* CHANGE */
X***************
X*** 115,124
X  				 * wait for lpd to restart us.
X  				 */
X  				if ((ch = getchar()) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					break;
X  				} else {
X  					ungetc(ch, stdin);
X  					ch = '\031';
X  				}
X
X--- 353,368 -----
X  				 * doing and wait for lpd to restart us.
X  				 */
X  				if ((ch = getc(p)) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X+ 					/* come here when received SIGCONT */
X+ #ifdef LA120
X+ 					printf("%s",widthstring); /* CHANGE */
X+ 					printf("%s",lengthstring); /* CHANGE */
X+ 					printf("\033[%dt",actualength);
X+ #endif
X  					break;
X  				} else {
X  					ungetc(ch, p);
X  					ch = '\031';
X  				}
X***************
X*** 117,127
X  				if ((ch = getchar()) == '\1') {
X  					fflush(stdout);
X  					kill(getpid(), SIGSTOP);
X  					break;
X  				} else {
X! 					ungetc(ch, stdin);
X  					ch = '\031';
X  				}
X  
X  			default:
X  				if (col >= width || !literal && ch < ' ') {
X
X--- 361,371 -----
X  					printf("%s",lengthstring); /* CHANGE */
X  					printf("\033[%dt",actualength);
X  #endif
X  					break;
X  				} else {
X! 					ungetc(ch, p);
X  					ch = '\031';
X  				}
X  				goto putit;
X  
X  			default:
X***************
X*** 120,129
X  					break;
X  				} else {
X  					ungetc(ch, stdin);
X  					ch = '\031';
X  				}
X  
X  			default:
X  				if (col >= width || !literal && ch < ' ') {
X  					col++;
X  					break;
X
X--- 364,374 -----
X  					break;
X  				} else {
X  					ungetc(ch, p);
X  					ch = '\031';
X  				}
X+ 				goto putit;
X  
X  			default:
X  				if (col>=width || !literal && ch<' ') {
X  					col++;
X  					break;
X***************
X*** 122,132
X  					ungetc(ch, stdin);
X  					ch = '\031';
X  				}
X  
X  			default:
X! 				if (col >= width || !literal && ch < ' ') {
X  					col++;
X  					break;
X  				}
X  				cp = &buf[0][col];
X  				for (i = 0; i < MAXREP; i++) {
X
X--- 367,377 -----
X  					ch = '\031';
X  				}
X  				goto putit;
X  
X  			default:
X! 				if (col>=width || !literal && ch<' ') {
X  					col++;
X  					break;
X  				}
X  putit:
X  				cp = &buf[0][col];
X***************
X*** 126,135
X  			default:
X  				if (col >= width || !literal && ch < ' ') {
X  					col++;
X  					break;
X  				}
X  				cp = &buf[0][col];
X  				for (i = 0; i < MAXREP; i++) {
X  					if (i > maxrep)
X  						maxrep = i;
X  					if (*cp == ' ') {
X
X--- 371,381 -----
X  			default:
X  				if (col>=width || !literal && ch<' ') {
X  					col++;
X  					break;
X  				}
X+ putit:
X  				cp = &buf[0][col];
X  				for (i = 0; i < MAXREP; i++) {
X  					if (i > maxrep)
X  						maxrep = i;
X  					if (*cp == ' ') {
X***************
X*** 149,158
X  		for (i = 0; i <= maxrep; i++) {
X  			for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
X  				putc(*cp, o);
X  				*cp++ = ' ';
X  			}
X  			if (i < maxrep)
X  				putc('\r', o);
X  			else
X  				putc(ch, o);
X  			if (++lineno >= length) {
X
X--- 395,411 -----
X  		for (i = 0; i <= maxrep; i++) {
X  			for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
X  				putc(*cp, o);
X  				*cp++ = ' ';
X  			}
X+ #ifdef LN01
X+ 			/* CHANGE [15-Sep-84 dsh]: pad out every line to the
X+ 			 * declared width of the page.
X+ 			 */
X+ 			for (j=maxcol[i]; j<132; j++)
X+ 				putchar(' ');
X+ #endif
X  			if (i < maxrep)
X  				putc('\r', o);
X  			else
X  				putc(ch, o);
X  /* CHANGE: 7-Jun-84 dsh: This does not belong here.
X***************
X*** 153,166
X  			}
X  			if (i < maxrep)
X  				putc('\r', o);
X  			else
X  				putc(ch, o);
X! 			if (++lineno >= length) {
X! 				npages++;
X! 				lineno = 0;
X! 			}
X  			maxcol[i] = -1;
X  		}
X  	}
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		putchar('\f');
X
X--- 406,421 -----
X  #endif
X  			if (i < maxrep)
X  				putc('\r', o);
X  			else
X  				putc(ch, o);
X! /* CHANGE: 7-Jun-84 dsh: This does not belong here.
X!  *			if (++lineno >= length) {
X!  *				npages++;
X!  *				lineno = 0;
X!  *			}
X!  */
X  			maxcol[i] = -1;
X  		}
X  /* CHANGE 7-Jun-84 dsh: It belongs here instead. */
X  		if (++lineno >= length) {
X  			npages++;
X***************
X*** 159,168
X  				npages++;
X  				lineno = 0;
X  			}
X  			maxcol[i] = -1;
X  		}
X  	}
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		putchar('\f');
X  		npages++;
X  	}
X
X--- 414,428 -----
X   *				lineno = 0;
X   *			}
X   */
X  			maxcol[i] = -1;
X  		}
X+ /* CHANGE 7-Jun-84 dsh: It belongs here instead. */
X+ 		if (++lineno >= length) {
X+ 			npages++;
X+ 			lineno = 0;
X+ 		}
X  	}
X  
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		/* CHANGE [15-Sep-84 dsh]: For LN01, pad each line out to
X  		 * its' declared width, otherwise just put out the \n
X***************
X*** 160,169
X  				lineno = 0;
X  			}
X  			maxcol[i] = -1;
X  		}
X  	}
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		putchar('\f');
X  		npages++;
X  	}
X  	if (name && acctfile && access(acctfile, 02) >= 0 &&
X
X--- 420,430 -----
X  		if (++lineno >= length) {
X  			npages++;
X  			lineno = 0;
X  		}
X  	}
X+ 
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		/* CHANGE [15-Sep-84 dsh]: For LN01, pad each line out to
X  		 * its' declared width, otherwise just put out the \n
X  		 */
X  		while(lineno++ < length) /* putchar('\n'); */
X***************
X*** 161,171
X  			}
X  			maxcol[i] = -1;
X  		}
X  	}
X  	if (lineno) {		/* be sure to end on a page boundary */
X! 		putchar('\f');
X  		npages++;
X  	}
X  	if (name && acctfile && access(acctfile, 02) >= 0 &&
X  	    freopen(acctfile, "a", stdout) != NULL) {
X  		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
X
X--- 422,445 -----
X  			lineno = 0;
X  		}
X  	}
X  
X  	if (lineno) {		/* be sure to end on a page boundary */
X! 		/* CHANGE [15-Sep-84 dsh]: For LN01, pad each line out to
X! 		 * its' declared width, otherwise just put out the \n
X! 		 */
X! 		while(lineno++ < length) /* putchar('\n'); */
X! #ifndef LN01
X! 			putchar('\n');
X! #else
X! 		{
X! 			for (j=0; j<132; j++)
X! 				putchar(' ');
X! 			putchar('\n');
X! 		}
X! #endif
X! 		/* putchar('\f'); */
X  		npages++;
X  	}
X  
X  #ifdef LA120
X  	printf("%s",FINALWIDTH);
X***************
X*** 164,173
X  	}
X  	if (lineno) {		/* be sure to end on a page boundary */
X  		putchar('\f');
X  		npages++;
X  	}
X  	if (name && acctfile && access(acctfile, 02) >= 0 &&
X  	    freopen(acctfile, "a", stdout) != NULL) {
X  		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
X  	}
X  	exit(0);
X
X--- 438,477 -----
X  		}
X  #endif
X  		/* putchar('\f'); */
X  		npages++;
X  	}
X+ 
X+ #ifdef LA120
X+ 	printf("%s",FINALWIDTH);
X+ 	printf("%s",FINALENGTH);
X+ #endif
X+ #ifdef LN01
X+ /* CHANGE [9-Jul-84 dsh]: From nportrait.c */
X+ /* CHANGE [12-Jul-84 kkk]: Added sleep, probably 9 is enough */
X+ /* CHANGE [6-Sep-84 dsh]: had it check changed flag before doing this. */
X+ /* CHANGE [15-Sep-84 dsh]: removed check on changed flag.  Removed sleep.
X+  *	Made it set portrait mode rather than nportrait.  This stuff
X+  *	here also helps in flushing out the last page.
X+  */
X+ /*	printf("\033c"); */
X+ 	if (width <= 80) {
X+ 		/* temporarily set landscape */
X+ 		printf("\033c\033[10m\r");
X+ 	}
X+ 	else {
X+ 		printf("\033[11m");  /* Select font (portrait) */
X+ 		printf("\033[3300t");
X+ 		printf("\033[0;3300r\r"); /* Select top and bottom margins. */
X+ 	}
X+ 	printf("\033c\r");
X+ #endif LN01
X+ 
X+ #endif SPINWRITER
X+ 
X+ 	fflush(stdout);
X+ 
X  	if (name && acctfile && access(acctfile, 02) >= 0 &&
X  	    freopen(acctfile, "a", stdout) != NULL) {
X  		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
X  	}
X  	exit(0);
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l lpf.c.diff
echo x - lpr.c.diff '		' '-rw-r--r--  1 david       19930 Dec  6 19:49 lpr.c.diff'
sed 's/^X//' > lpr.c.diff <<'EOF-OF-THIS-FILE'
X*** lpr.c.orig.1	Mon Jan 30 15:11:55 1984
X--- lpr.c	Fri Apr 20 14:24:32 1984
X***************
X*** 7,16
X   *
X   * Allows multiple printers and printers on remote machines by
X   * using information from a printer data base.
X   */
X  
X  #include <stdio.h>
X  #include <sys/types.h>
X  #include <sys/file.h>
X  #include <sys/stat.h>
X  #include <pwd.h>
X
X--- 7,34 -----
X   *
X   * Allows multiple printers and printers on remote machines by
X   * using information from a printer data base.
X   */
X  
X+ /* CHANGES:
X+  *-- 30JAN84 dsh: added "-L<page-length>" option.  This was to specify
X+  *	how many lines was to be on the line.  To be used with the
X+  *	LA120 and its variable number of lines.  To communicate this
X+  *	to lpd, had to add a new "card" command "S".  
X+  *	(both "l" and "L" were already in use).
X+  *-- 27MAR84 dsh: Remade option scanner to scan an environment
X+  *	environment variable before the command line.  This allows
X+  *	one to have personal defaults to lpr, which have priority
X+  *	between the system defaults and the command line.  These
X+  *	defaults live in a variable called "LPR".
X+  *
X+  *	This was accomplished by moving the previous scanner into
X+  *	two new routines, "scanargs()" and "getstring()".  Where
X+  *	scanargs() scans a string picking off options, and getstring()
X+  *	gets the value of the option.
X+  */
X+ 
X  #include <stdio.h>
X  #include <sys/types.h>
X  #include <sys/file.h>
X  #include <sys/stat.h>
X  #include <pwd.h>
X***************
X*** 37,46
X  int     userid;			/* user id */
X  char	*person;		/* user name */
X  char	*title;			/* pr'ing title */
X  char	*fonts[4];		/* troff font names */
X  char	*width;			/* width for versatec printing */
X  char	host[32];		/* host name */
X  char	*class = host;		/* class title on header page */
X  char    *jobname;		/* job name on header page */
X  char	*name;			/* program name */
X  char	*printer;		/* printer name */
X
X--- 55,65 -----
X  int     userid;			/* user id */
X  char	*person;		/* user name */
X  char	*title;			/* pr'ing title */
X  char	*fonts[4];		/* troff font names */
X  char	*width;			/* width for versatec printing */
X+ char	*length;		/* page length; CHANGE dsh 30JAN84 */
X  char	host[32];		/* host name */
X  char	*class;			/* class title on header page */
X  char    *jobname;		/* job name on header page */
X  char	*name;			/* program name */
X  char	*printer;		/* printer name */
X***************
X*** 38,48
X  char	*person;		/* user name */
X  char	*title;			/* pr'ing title */
X  char	*fonts[4];		/* troff font names */
X  char	*width;			/* width for versatec printing */
X  char	host[32];		/* host name */
X! char	*class = host;		/* class title on header page */
X  char    *jobname;		/* job name on header page */
X  char	*name;			/* program name */
X  char	*printer;		/* printer name */
X  char	buf[BUFSIZ];
X  
X
X--- 57,67 -----
X  char	*title;			/* pr'ing title */
X  char	*fonts[4];		/* troff font names */
X  char	*width;			/* width for versatec printing */
X  char	*length;		/* page length; CHANGE dsh 30JAN84 */
X  char	host[32];		/* host name */
X! char	*class;			/* class title on header page */
X  char    *jobname;		/* job name on header page */
X  char	*name;			/* program name */
X  char	*printer;		/* printer name */
X  char	buf[BUFSIZ];
X  
X***************
X*** 66,75
X  	extern struct passwd *getpwuid();
X  	struct passwd *pw;
X  	extern char *itoa();
X  	register char *arg, *cp;
X  	int i, f;
X  	struct stat stb;
X  
X  	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X  		signal(SIGHUP, cleanup);
X  	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X
X--- 85,95 -----
X  	extern struct passwd *getpwuid();
X  	struct passwd *pw;
X  	extern char *itoa();
X  	register char *arg, *cp;
X  	int i, f;
X+ 	register int argcnt;
X  	struct stat stb;
X  	char *defenv;
X  
X  	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X  		signal(SIGHUP, cleanup);
X***************
X*** 67,76
X  	struct passwd *pw;
X  	extern char *itoa();
X  	register char *arg, *cp;
X  	int i, f;
X  	struct stat stb;
X  
X  	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X  		signal(SIGHUP, cleanup);
X  	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X  		signal(SIGINT, cleanup);
X
X--- 87,97 -----
X  	extern char *itoa();
X  	register char *arg, *cp;
X  	int i, f;
X  	register int argcnt;
X  	struct stat stb;
X+ 	char *defenv;
X  
X  	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X  		signal(SIGHUP, cleanup);
X  	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X  		signal(SIGINT, cleanup);
X***************
X*** 79,88
X  	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X  		signal(SIGTERM, cleanup);
X  
X  	name = argv[0];
X  	gethostname(host, sizeof (host));
X  
X  	while (argc > 1 && argv[1][0] == '-') {
X  		argc--;
X  		arg = *++argv;
X  		switch (arg[1]) {
X
X--- 100,110 -----
X  	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
X  		signal(SIGTERM, cleanup);
X  
X  	name = argv[0];
X  	gethostname(host, sizeof (host));
X+ 	class = host;			/* set the default */
X  
X  	if ((defenv=getenv("LPR")) != NULL) (void) scanargs(defenv);
X  	for (; argc > 1 && argv[1][0] == '-'; argc--,argv++)
X  		scanargs(argv[1]);
X  /*	donothing(argc, argv);for debugging */
X***************
X*** 80,93
X  		signal(SIGTERM, cleanup);
X  
X  	name = argv[0];
X  	gethostname(host, sizeof (host));
X  
X! 	while (argc > 1 && argv[1][0] == '-') {
X! 		argc--;
X! 		arg = *++argv;
X! 		switch (arg[1]) {
X  
X  		case 'P':		/* specifiy printer name */
X  			if (arg[2])
X  				printer = &arg[2];
X  			else if (argc > 1) {
X
X--- 102,115 -----
X  
X  	name = argv[0];
X  	gethostname(host, sizeof (host));
X  	class = host;			/* set the default */
X  
X! 	if ((defenv=getenv("LPR")) != NULL) (void) scanargs(defenv);
X! 	for (; argc > 1 && argv[1][0] == '-'; argc--,argv++)
X! 		scanargs(argv[1]);
X! /*	donothing(argc, argv);for debugging */
X  
X  	if (printer == '\0') {
X  		printer = getenv("PRINTER");
X  		if (printer == '\0') printer = DEFLP;
X  	}
X***************
X*** 85,193
X  	while (argc > 1 && argv[1][0] == '-') {
X  		argc--;
X  		arg = *++argv;
X  		switch (arg[1]) {
X  
X! 		case 'P':		/* specifiy printer name */
X! 			if (arg[2])
X! 				printer = &arg[2];
X! 			else if (argc > 1) {
X! 				argc--;
X! 				printer = *++argv;
X! 			}
X! 			break;
X! 
X! 		case 'C':		/* classification spec */
X! 			hdr++;
X! 			if (arg[2])
X! 				class = &arg[2];
X! 			else if (argc > 1) {
X! 				argc--;
X! 				class = *++argv;
X! 			}
X! 			break;
X! 
X! 		case 'J':		/* job name */
X! 			hdr++;
X! 			if (arg[2])
X! 				jobname = &arg[2];
X! 			else if (argc > 1) {
X! 				argc--;
X! 				jobname = *++argv;
X! 			}
X! 			break;
X! 
X! 		case 'T':		/* pr's title line */
X! 			if (arg[2])
X! 				title = &arg[2];
X! 			else if (argc > 1) {
X! 				argc--;
X! 				title = *++argv;
X! 			}
X! 			break;
X! 
X! 		case 'l':		/* literal output */
X! 		case 'p':		/* print using ``pr'' */
X! 		case 't':		/* print troff output (cat files) */
X! 		case 'n':		/* print ditroff output */
X! 		case 'd':		/* print tex output (dvi files) */
X! 		case 'g':		/* print graph(1G) output */
X! 		case 'c':		/* print cifplot output */
X! 		case 'v':		/* print vplot output */
X! 			format = arg[1];
X! 			break;
X! 
X! 		case 'f':		/* print fortran output */
X! 			format = 'r';
X! 			break;
X! 
X! 		case '4':		/* troff fonts */
X! 		case '3':
X! 		case '2':
X! 		case '1':
X! 			if (argc > 1) {
X! 				argc--;
X! 				fonts[arg[1] - '1'] = *++argv;
X! 			}
X! 			break;
X! 
X! 		case 'w':		/* versatec page width */
X! 			width = arg+2;
X! 			break;
X! 
X! 		case 'r':		/* remove file when done */
X! 			rflag++;
X! 			break;
X! 
X! 		case 'm':		/* send mail when done */
X! 			mailflg++;
X! 			break;
X! 
X! 		case 'h':		/* toggle want of header page */
X! 			hdr = !hdr;
X! 			break;
X! 
X! 		case 's':		/* try to link files */
X! 			sflag++;
X! 			break;
X! 
X! 		case 'q':		/* just q job */
X! 			qflag++;
X! 			break;
X! 
X! 		case 'i':		/* indent output */
X! 			iflag++;
X! 			indent = arg[2] ? atoi(&arg[2]) : 8;
X! 			break;
X! 
X! 		case '#':		/* n copies */
X! 			if (isdigit(arg[2])) {
X! 				i = atoi(&arg[2]);
X! 				if (i > 0)
X! 					ncopies = i;
X! 			}
X! 		}
X  	}
X  	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
X  		printer = DEFLP;
X  	chkprinter(printer);
X  	if (SC && ncopies > 1)
X
X--- 107,119 -----
X  	if ((defenv=getenv("LPR")) != NULL) (void) scanargs(defenv);
X  	for (; argc > 1 && argv[1][0] == '-'; argc--,argv++)
X  		scanargs(argv[1]);
X  /*	donothing(argc, argv);for debugging */
X  
X! 	if (printer == '\0') {
X! 		printer = getenv("PRINTER");
X! 		if (printer == '\0') printer = DEFLP;
X  	}
X  	chkprinter(printer);
X  	if (SC && ncopies > 1)
X  		fatal("multiple copies are not allowed");
X  	if (MC > 0 && ncopies > MC)
X***************
X*** 185,196
X  				if (i > 0)
X  					ncopies = i;
X  			}
X  		}
X  	}
X- 	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
X- 		printer = DEFLP;
X  	chkprinter(printer);
X  	if (SC && ncopies > 1)
X  		fatal("multiple copies are not allowed");
X  	if (MC > 0 && ncopies > MC)
X  		fatal("only %d copies are allowed", MC);
X
X--- 111,120 -----
X  
X  	if (printer == '\0') {
X  		printer = getenv("PRINTER");
X  		if (printer == '\0') printer = DEFLP;
X  	}
X  	chkprinter(printer);
X  	if (SC && ncopies > 1)
X  		fatal("multiple copies are not allowed");
X  	if (MC > 0 && ncopies > MC)
X  		fatal("only %d copies are allowed", MC);
X***************
X*** 215,225
X  	tfd = nfile(tfname);
X  	(void) fchown(tfd, DU, -1);	/* owned by daemon for protection */
X  	card('H', host);
X  	card('P', person);
X  	if (hdr) {
X! 		if (jobname == NULL) {
X  			if (argc == 1)
X  				jobname = "stdin";
X  			else
X  				jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1];
X  		}
X
X--- 139,149 -----
X  	tfd = nfile(tfname);
X  	(void) fchown(tfd, DU, -1);	/* owned by daemon for protection */
X  	card('H', host);
X  	card('P', person);
X  	if (hdr) {
X! 		if (jobname == 0) {
X  			if (argc == 1)
X  				jobname = "stdin";
X  			else {
X  				arg = rindex(argv[1], '/');
X  				if (*arg)
X***************
X*** 218,229
X  	card('P', person);
X  	if (hdr) {
X  		if (jobname == NULL) {
X  			if (argc == 1)
X  				jobname = "stdin";
X! 			else
X! 				jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1];
X  		}
X  		card('J', jobname);
X  		card('C', class);
X  		card('L', person);
X  	}
X
X--- 142,158 -----
X  	card('P', person);
X  	if (hdr) {
X  		if (jobname == 0) {
X  			if (argc == 1)
X  				jobname = "stdin";
X! 			else {
X! 				arg = rindex(argv[1], '/');
X! 				if (*arg)
X! 					jobname = arg+1;
X! 				else
X! 					jobname =  argv[1];
X! 			}
X  		}
X  		card('J', jobname);
X  		card('C', class);
X  		card('L', person);
X  	}
X***************
X*** 225,238
X  		}
X  		card('J', jobname);
X  		card('C', class);
X  		card('L', person);
X  	}
X! 	if (iflag)
X! 		card('I', itoa(indent));
X! 	if (mailflg)
X! 		card('M', person);
X  	if (format == 't' || format == 'n' || format == 'd')
X  		for (i = 0; i < 4; i++)
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X  	if (width != NULL)
X
X--- 154,167 -----
X  		}
X  		card('J', jobname);
X  		card('C', class);
X  		card('L', person);
X  	}
X! 	if (iflag) card('I', itoa(indent));
X! 
X! 	if (mailflg) card('M', person);
X! 
X  	if (format == 't' || format == 'n' || format == 'd')
X  		for (i = 0; i < 4; i++)
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X  
X***************
X*** 233,244
X  		card('M', person);
X  	if (format == 't' || format == 'n' || format == 'd')
X  		for (i = 0; i < 4; i++)
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X- 	if (width != NULL)
X- 		card('W', width);
X  
X  	/*
X  	 * Read the files and spool them.
X  	 */
X  	if (argc == 1)
X
X--- 162,171 -----
X  
X  	if (format == 't' || format == 'n' || format == 'd')
X  		for (i = 0; i < 4; i++)
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X  
X  	if (width[0] != '\0') card('W', width);
X  
X  	if (length[0] != '\0') card('S', length);	/* CHANGE */
X  
X***************
X*** 236,245
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X  	if (width != NULL)
X  		card('W', width);
X  
X  	/*
X  	 * Read the files and spool them.
X  	 */
X  	if (argc == 1)
X  		copy(0, " ");
X
X--- 163,176 -----
X  	if (format == 't' || format == 'n' || format == 'd')
X  		for (i = 0; i < 4; i++)
X  			if (fonts[i] != NULL)
X  				card('1'+i, fonts[i]);
X  
X+ 	if (width[0] != '\0') card('W', width);
X+ 
X+ 	if (length[0] != '\0') card('S', length);	/* CHANGE */
X+ 
X  	/*
X  	 * Read the files and spool them.
X  	 */
X  	if (argc == 1)
X  		copy(0, " ");
X***************
X*** 247,257
X  		if ((f = test(arg = *++argv)) < 0)
X  			continue;	/* file unreasonable */
X  
X  		if (sflag && (cp = linked(arg)) != NULL) {
X  			if (format == 'p')
X! 				card('T', title ? title : arg);
X  			for (i = 0; i < ncopies; i++)
X  				card(format, &dfname[inchar-2]);
X  			card('U', &dfname[inchar-2]);
X  			if (f)
X  				card('U', cp);
X
X--- 178,188 -----
X  		if ((f = test(arg = *++argv)) < 0)
X  			continue;	/* file unreasonable */
X  
X  		if (sflag && (cp = linked(arg)) != NULL) {
X  			if (format == 'p')
X! 				card('T', title!=0 ? title : arg);
X  			for (i = 0; i < ncopies; i++)
X  				card(format, &dfname[inchar-2]);
X  			card('U', &dfname[inchar-2]);
X  			if (f)
X  				card('U', cp);
X***************
X*** 301,310
X  			printf("jobs queued, but cannot start daemon.\n");
X  		exit(0);
X  	}
X  	cleanup();
X  	/* NOTREACHED */
X  }
X  
X  /*
X   * Create the file n and copy from file descriptor f.
X   */
X
X--- 232,497 -----
X  			printf("jobs queued, but cannot start daemon.\n");
X  		exit(0);
X  	}
X  	cleanup();
X  	/* NOTREACHED */
X+ }
X+ 
X+ /* donothing() -- added 27MAR84, for testing purposes.  It simply
X+  *	prints out interesting things and exits.
X+  */
X+ donothing(argc, argv)
X+ int argc;
X+ char **argv;
X+ {
X+ 	printf("person:%s\n", person);
X+ 	printf("title:%s\n", title);
X+ 	printf("width:%s\n", width);
X+ 	printf("length:%s\n", length);
X+ 	printf("host:%s\n", host);
X+ 	printf("class:%s\n", class);
X+ 	printf("jobname:%s\n", jobname);
X+ 	printf("name:%s\n", name);
X+ 	printf("printer:%s\n", printer);
X+ 	printf("format:%c, ncopies:%d\n", format, ncopies);
X+ 	for (argc--, argv++; argc >= 1; argc--, argv++)
X+ 		printf ("%d:%s\n", argc, argv[0]);
X+ 	exit();
X+ }
X+ 	
X+ 
X+ 
X+ /* scanargs() -- scan through a string for lpr command-line options.
X+  *
X+  *	Control stays within this routine as long as the string
X+  *	has options within it.  It has to do this for scanning
X+  *	"LPR".  When scanning an argv thing, we merely end up
X+  *	at the end of the string and return.
X+  */
X+ 
X+ #define iswhite(c)	((c) == ' ' || (c) == '\t')
X+ #define skipwhite(s)	for(; iswhite(*(s)); (s)++) /*NULL*/ ;
X+ 
X+ int scanargs (argstring)
X+ char *argstring;
X+ {
X+     char *getstring();
X+     register int i;
X+     register char c;
X+ 
X+ loop:
X+ /* printf("scanargs: arg:[%s]\n", argstring) ; */
X+ 	skipwhite(argstring);
X+ 	if (argstring[0] != '-') return;
X+ 	argstring++;
X+ 	switch (argstring[0]) {
X+ 
X+ 	    case 'P': 		/* specifiy printer name */
X+ 	    	argstring++;
X+ 	    	argstring = getstring(argstring, &printer);
X+ 		break;
X+ 
X+ 	    case 'C': 		/* classification spec */
X+ 		hdr++;
X+ 		argstring++;
X+ 		argstring = getstring(argstring, &class);
X+ 		break;
X+ 
X+ 	    case 'J': 		/* job name */
X+ 		hdr++;
X+ 		argstring++;
X+ 		argstring = getstring(argstring, &jobname);
X+ 		break;
X+ 
X+ 	    case 'T': 		/* pr's title line */
X+ 	    	argstring++;
X+ 	    	argstring = getstring(argstring, &title);
X+ 		break;
X+ 
X+ 	    case 'l': 		/* literal output */
X+ 	    case 'p': 		/* print using ``pr'' */
X+ 	    case 't': 		/* print troff output (cat files) */
X+ 	    case 'n': 		/* print ditroff output */
X+ 	    case 'd': 		/* print tex output (dvi files) */
X+ 	    case 'g': 		/* print graph(1G) output */
X+ 	    case 'c': 		/* print cifplot output */
X+ 	    case 'v': 		/* print vplot output */
X+ 		format = argstring[0];
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 'f': 		/* print fortran output */
X+ 		format = 'r';
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case '4': 		/* troff fonts */
X+ 	    case '3': 
X+ 	    case '2': 
X+ 	    case '1': 
X+ 	    	c = argstring[0];
X+ 	    	argstring++;
X+ 	    	argstring = getstring(argstring, &fonts[c-'1']);
X+ 		break;
X+ 
X+ 	    case 'w': 		/* versatec page width */
X+ 	    	argstring++;
X+ 	    	argstring = getstring(argstring, &width);
X+ 		break;
X+ 
X+ 	    case 'L': 		/* page length (LA120) CHANGE: dsh 30JAN */
X+ 	    	argstring++;
X+ 	    	argstring = getstring(argstring, &length);
X+ 		break;
X+ 
X+ 	    case 'r': 		/* remove file when done */
X+ 		rflag++;
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 'm': 		/* send mail when done */
X+ 		mailflg++;
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 'h': 		/* toggle want of header page */
X+ 		hdr = !hdr;
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 's': 		/* try to link files */
X+ 		sflag++;
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 'q': 		/* just q job */
X+ 		qflag++;
X+ 		argstring++;
X+ 		break;
X+ 
X+ 	    case 'i': 		/* indent output */
X+ 		iflag++;
X+ 		indent = 8;	/* default value */
X+ 		{
X+ 			char *is;
X+ 			argstring++;
X+ 			argstring = getstring(argstring, &is);
X+ 			if (isdigit(*is)) indent = atoi(is);
X+ 		}
X+ 		break;
X+ 
X+ 	    case '#': 		/* n copies */
X+ 		{
X+ 			char *is;
X+ 			argstring++;
X+ 			argstring = getstring(argstring, &is);
X+ 			if (isdigit(*is)) i = atoi(is);
X+ 		}
X+ 		if (i > 0)
X+ 		    ncopies = i;
X+ 		break;
X+ 	}
X+ 	goto loop;
X+ }
X+ 
X+ 
X+ /* getstring() -- parse out a string from the command-line option.
X+  *
X+  * Syntax is scanned as follows:
X+  *
X+  *	1. already scanned is "-x" where "x" is an option letter.
X+  *	2. skip white space (if any)
X+  *	3. If this argument ran out (defined by seeing the "-" for
X+  *	   the start of the next option, or a '\0' for end-of-string),
X+  *	   goto 5.
X+  *	4. (found a value attached to this argument).  Move the pointer to
X+  *	   the end of the value, and copy it to the buffer pointed to by 
X+  *	   "option".  goto 6.
X+  *	5. (did not find a value attached to this argument, 
X+  *	    might be in "nxtarg").  If there is something in nxtarg, use
X+  *	    that for the value and set rv.  otherwise, nothing is changed
X+  *	   anywhere.
X+  *	6. done.  return.
X+  *
X+  * rg:		pointer to "arg" in scanargs().
X+  * nxarg:	same as "rg" but for "nxtarg".
X+  * option:	pointer to the buffer to store the value in.
X+  * rv:		pointer to "rv" in scanargs().
X+  */
X+ char *getstring(argstring, option)
X+ register char *argstring;
X+ char **option;
X+ {
X+ 	register char *from_s, *to_s;
X+ 	register char c;
X+ 	
X+ 	skipwhite(argstring);
X+ 	to_s = from_s = *option = argstring;
X+ 	
X+ 	/* start state. */
X+ state1:	c = *from_s++;
X+ 	if (iswhite(c)) goto state1;
X+ 	else if (c == '"') goto state2;
X+ 	else if (c == '\'') goto state6;
X+ 	else if (c == '-') goto state5;
X+ 	else if (c == '\0') { from_s--; goto state5; }
X+ 	else goto state9;
X+ 
X+ 	/* scan a string quoted with double-quotes. */
X+ state2:	c = *from_s++;
X+ 	if (c == '"') goto state5;
X+ 	else if (c == '\0') { from_s--; goto state5; }
X+ 	else goto state3;
X+ 
X+ 	/* interior part of double-quoted string. */
X+ state3:	*to_s++ = c;
X+ 	c = *from_s++;
X+ 	if (c == '"') goto state5;
X+ 	else if (c == '\0') { from_s--; goto state5; }
X+ 	else if (c == '\\') goto state4;
X+ 	else goto state3;
X+ 
X+ 	/* backslash handling for double-quoted string. */
X+ state4:	c = *from_s++;
X+ 	goto state3;
X+ 
X+ 	/* general purpose done state. */
X+ state5:	*to_s++ = '\0';
X+ 	goto done;
X+ 
X+ 	/* scan a string quoted with single-quotes. */
X+ state6:	c = *from_s++;
X+ 	if (c == '\'') goto state5;
X+ 	else if (c == '\0') { from_s--; goto state5; }
X+ 	else goto state7;
X+ 
X+ 	/* interior part of singly-quoted string. */
X+ state7:	*to_s++ = c;
X+ 	c = *from_s++;
X+ 	if (c == '\'') goto state5;
X+ 	else if (c == '\0') { from_s--; goto state5; }
X+ 	else if (c == '\\') goto state8;
X+ 	else goto state7;
X+ 
X+ 	/* handle backslashes. */
X+ state8:	c = *from_s++;
X+ 	goto state7;
X+ 
X+ 	/* token which is not quoted. */
X+ state9:	*to_s++ = c;
X+ 	c = *from_s++;
X+ 	if (c == '\0') { from_s--; goto state5; }
X+ 	else if (iswhite(c)) goto state5; 
X+ 	else if (c == '\\') goto state10;
X+ 	else goto state9;
X+ 
X+ 	/* handle backslashes for unquoted token. */
X+ state10: c = *from_s++;
X+ 	goto state9;
X+ 
X+ done:
X+ 	return(from_s);
X  }
X  
X  /*
X   * Create the file n and copy from file descriptor f.
X   */
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l lpr.c.diff
echo x - printjob.c.diff '		' '-rw-r--r--  1 david        7802 Dec  6 19:52 printjob.c.diff'
sed 's/^X//' > printjob.c.diff <<'EOF-OF-THIS-FILE'
X*** printjob.c.orig	Mon Jan 30 15:18:49 1984
X--- printjob.c	Thu Sep  6 12:15:31 1984
X***************
X*** 7,16
X   *
X   *	NOTE: the lock file is used to pass information to lpq and lprm.
X   *	it does not need to be removed because file locks are dynamic.
X   */
X  
X  #include "lp.h"
X  
X  #define DORETURN	0		/* absorb fork error */
X  #define DOABORT		1		/* abort if dofork fails */
X  
X
X--- 7,22 -----
X   *
X   *	NOTE: the lock file is used to pass information to lpq and lprm.
X   *	it does not need to be removed because file locks are dynamic.
X   */
X  
X+ /* CHANGES:
X+  *-- 30JAN84 dsh: (see change in lpr.c for same day).  Added new command
X+  *	"S" for communicating page sizes.
X+  *-- 6-Sep-84 dsh: Added variable Iflag.  Set to 1 when see an 'I' card.
X+  */
X+ 
X  #include "lp.h"
X  
X  #define DORETURN	0		/* absorb fork error */
X  #define DOABORT		1		/* abort if dofork fails */
X  
X***************
X*** 34,43
X  static char	width[10] = "-w";	/* page width in characters */
X  static char	length[10] = "-l";	/* page length in lines */
X  static char	pxwidth[10] = "-x";	/* page width in pixels */
X  static char	pxlength[10] = "-y";	/* page length in pixels */
X  static char	indent[10] = "-i0";	/* indentation size in characters */
X  
X  printjob()
X  {
X  	struct stat stb;
X  	register struct queue *q, **qp;
X
X--- 40,51 -----
X  static char	width[10] = "-w";	/* page width in characters */
X  static char	length[10] = "-l";	/* page length in lines */
X  static char	pxwidth[10] = "-x";	/* page width in pixels */
X  static char	pxlength[10] = "-y";	/* page length in pixels */
X  static char	indent[10] = "-i0";	/* indentation size in characters */
X+ static int	Iflag = 0;		/* flag that we actually want indent */
X+ 					/* set when we see an 'I' card */
X  
X  printjob()
X  {
X  	struct stat stb;
X  	register struct queue *q, **qp;
X***************
X*** 228,237
X  	 *		H -- "host name" of machine where lpr was done
X  	 *              P -- "person" user's login name
X  	 *              I -- "indent" amount to indent output
X  	 *              f -- "file name" name of text file to print
X  	 *		l -- "file name" text file with control chars
X  	 *		p -- "file name" text file to print with pr(1)
X  	 *		t -- "file name" troff(1) file to print
X  	 *		n -- "file name" ditroff(1) file to print
X  	 *		d -- "file name" dvi file to print
X  	 *		g -- "file name" plot(1G) file to print
X
X--- 236,246 -----
X  	 *		H -- "host name" of machine where lpr was done
X  	 *              P -- "person" user's login name
X  	 *              I -- "indent" amount to indent output
X  	 *              f -- "file name" name of text file to print
X  	 *		l -- "file name" text file with control chars
X+ 	 *		r -- "file name" text file with Fortran style carraige control
X  	 *		p -- "file name" text file to print with pr(1)
X  	 *		t -- "file name" troff(1) file to print
X  	 *		n -- "file name" ditroff(1) file to print
X  	 *		d -- "file name" dvi file to print
X  	 *		g -- "file name" plot(1G) file to print
X***************
X*** 243,252
X  	 *		4 -- "S font file" for troff
X  	 *		N -- "name" of file (used by lpq)
X  	 *              U -- "unlink" name of file to remove
X  	 *                    (after we print it. (Pass 2 only)).
X  	 *		M -- "mail" to user when done printing
X  	 *
X  	 *      getline reads a line and expands tabs to blanks
X  	 */
X  
X  	/* pass 1 */
X
X--- 252,263 -----
X  	 *		4 -- "S font file" for troff
X  	 *		N -- "name" of file (used by lpq)
X  	 *              U -- "unlink" name of file to remove
X  	 *                    (after we print it. (Pass 2 only)).
X  	 *		M -- "mail" to user when done printing
X+ 	 *		W -- "width" page width on printer
X+ 	 *		S -- "length" page length on printer
X  	 *
X  	 *      getline reads a line and expands tabs to blanks
X  	 */
X  
X  	/* pass 1 */
X***************
X*** 303,312
X  
X  		case 'W':	/* page width */
X  			strcpy(width+2, line+1);
X  			continue;
X  
X  		case 'I':	/* indent amount */
X  			strcpy(indent+2, line+1);
X  			continue;
X  
X  		default:	/* some file to print */
X
X--- 314,327 -----
X  
X  		case 'W':	/* page width */
X  			strcpy(width+2, line+1);
X  			continue;
X  
X+ 		case 'S':	/* page length (size) CHANGE 30JAN */
X+ 			strcpy(length+2,line+1); /* CHANGE */
X+ 			continue;		/* CHANGE */
X+ 
X  		case 'I':	/* indent amount */
X  			Iflag = 1;	/* CHANGE [6-Sep-84 dsh]: set the flag */
X  			strcpy(indent+2, line+1);
X  			continue;
X  
X***************
X*** 304,313
X  		case 'W':	/* page width */
X  			strcpy(width+2, line+1);
X  			continue;
X  
X  		case 'I':	/* indent amount */
X  			strcpy(indent+2, line+1);
X  			continue;
X  
X  		default:	/* some file to print */
X  			if ((i = print(line[0], line+1)) > 0) {
X
X--- 319,329 -----
X  		case 'S':	/* page length (size) CHANGE 30JAN */
X  			strcpy(length+2,line+1); /* CHANGE */
X  			continue;		/* CHANGE */
X  
X  		case 'I':	/* indent amount */
X+ 			Iflag = 1;	/* CHANGE [6-Sep-84 dsh]: set the flag */
X  			strcpy(indent+2, line+1);
X  			continue;
X  
X  		default:	/* some file to print */
X  			if ((i = print(line[0], line+1)) > 0) {
X***************
X*** 416,427
X  		fi = p[0];			/* use pipe for input */
X  	case 'f':	/* print plain text file */
X  		prog = IF;
X  		av[1] = width;
X  		av[2] = length;
X! 		av[3] = indent;
X! 		n = 4;
X  		break;
X  	case 'l':	/* like 'f' but pass control characters */
X  		prog = IF;
X  		av[1] = "-c";
X  		av[2] = width;
X
X--- 432,448 -----
X  		fi = p[0];			/* use pipe for input */
X  	case 'f':	/* print plain text file */
X  		prog = IF;
X  		av[1] = width;
X  		av[2] = length;
X! 		/* CHANGE [6-Sep-84 dsh]: only put in indent if wanted */
X! 		if (Iflag) {
X! 			av[3] = indent;
X! 			n = 4;
X! 		}
X! 		else
X! 			n = 3;
X  		break;
X  	case 'l':	/* like 'f' but pass control characters */
X  		prog = IF;
X  		av[1] = "-c";
X  		av[2] = width;
X***************
X*** 424,435
X  	case 'l':	/* like 'f' but pass control characters */
X  		prog = IF;
X  		av[1] = "-c";
X  		av[2] = width;
X  		av[3] = length;
X! 		av[4] = indent;
X! 		n = 5;
X  		break;
X  	case 'r':	/* print a fortran text file */
X  		prog = RF;
X  		av[1] = width;
X  		av[2] = length;
X
X--- 445,460 -----
X  	case 'l':	/* like 'f' but pass control characters */
X  		prog = IF;
X  		av[1] = "-c";
X  		av[2] = width;
X  		av[3] = length;
X! 		if (Iflag) {
X! 			av[4] = indent;
X! 			n = 5;
X! 		}
X! 		else
X! 			n = 4;
X  		break;
X  	case 'r':	/* print a fortran text file */
X  		prog = RF;
X  		av[1] = width;
X  		av[2] = length;
X***************
X*** 917,927
X  	if ((FF = pgetstr("ff", &bp)) == NULL)
X  		FF = DEFFF;
X  	if ((PW = pgetnum("pw")) < 0)
X  		PW = DEFWIDTH;
X  	sprintf(&width[2], "%d", PW);
X! 	if ((PL = pgetnum("pl")) < 0)
X  		PL = DEFLENGTH;
X  	sprintf(&length[2], "%d", PL);
X  	if ((PX = pgetnum("px")) < 0)
X  		PX = 0;
X  	sprintf(&pxwidth[2], "%d", PX);
X
X--- 942,952 -----
X  	if ((FF = pgetstr("ff", &bp)) == NULL)
X  		FF = DEFFF;
X  	if ((PW = pgetnum("pw")) < 0)
X  		PW = DEFWIDTH;
X  	sprintf(&width[2], "%d", PW);
X! 	if ((PL = pgetnum("pl")) < 0) 
X  		PL = DEFLENGTH;
X  	sprintf(&length[2], "%d", PL); /* might get changed later (if -L had been specified to lpr */
X  	if ((PX = pgetnum("px")) < 0)
X  		PX = 0;
X  	sprintf(&pxwidth[2], "%d", PX);
X***************
X*** 919,929
X  	if ((PW = pgetnum("pw")) < 0)
X  		PW = DEFWIDTH;
X  	sprintf(&width[2], "%d", PW);
X  	if ((PL = pgetnum("pl")) < 0)
X  		PL = DEFLENGTH;
X! 	sprintf(&length[2], "%d", PL);
X  	if ((PX = pgetnum("px")) < 0)
X  		PX = 0;
X  	sprintf(&pxwidth[2], "%d", PX);
X  	if ((PY = pgetnum("py")) < 0)
X  		PY = 0;
X
X--- 944,954 -----
X  	if ((PW = pgetnum("pw")) < 0)
X  		PW = DEFWIDTH;
X  	sprintf(&width[2], "%d", PW);
X  	if ((PL = pgetnum("pl")) < 0) 
X  		PL = DEFLENGTH;
X! 	sprintf(&length[2], "%d", PL); /* might get changed later (if -L had been specified to lpr */
X  	if ((PX = pgetnum("px")) < 0)
X  		PX = 0;
X  	sprintf(&pxwidth[2], "%d", PX);
X  	if ((PY = pgetnum("py")) < 0)
X  		PY = 0;
EOF-OF-THIS-FILE
echo -n '			 ' ; ls -l printjob.c.diff