1*33295Skarels #ifndef lint
2*33295Skarels static char Notice[] = "Copyright (c) 1985 Adobe Systems Incorporated";
3*33295Skarels static char *RCSID="$Header: enscript.c,v 2.1 85/11/24 11:48:55 shore Rel $";
4*33295Skarels #endif
5*33295Skarels /* enscript.c
6*33295Skarels  *
7*33295Skarels  * Copyright (c) 1985 Adobe Systems Incorporated
8*33295Skarels  *
9*33295Skarels  * inspired by Gosling's cz
10*33295Skarels  * there have been major overhauls, but the input language is the same:
11*33295Skarels  * 	new widths format
12*33295Skarels  *	generate PostScript (much easier than Press)
13*33295Skarels  *	new and renamed switches (to match 4.2bsd lpr spooler)
14*33295Skarels  *	obeys PostScript comment conventions
15*33295Skarels  *	doesn't worry so much about fonts (everything is scalable and
16*33295Skarels  *	rotatable, use PS font names, no face properties)
17*33295Skarels  *
18*33295Skarels  * enscript generates POSTSCRIPT print files of a special kind
19*33295Skarels  * the coordinate system is in 20ths of a point. (1440 per inch)
20*33295Skarels  *
21*33295Skarels  * Edit History:
22*33295Skarels  * Andrew Shore: Mon Nov 18 14:05:05 1985
23*33295Skarels  * End Edit History.
24*33295Skarels  *
25*33295Skarels  * RCSLOG:
26*33295Skarels  * $Log:	enscript.c,v $
27*33295Skarels  * Revision 2.1  85/11/24  11:48:55  shore
28*33295Skarels  * Product Release 2.0
29*33295Skarels  *
30*33295Skarels  * Revision 1.3  85/11/20  00:10:01  shore
31*33295Skarels  * Added System V support (input options and spooling)
32*33295Skarels  * margins/linecount reworked (Dataproducts)
33*33295Skarels  * incompatible options changes, getopt!
34*33295Skarels  * Guy Riddle's Gaudy mode and other changes
35*33295Skarels  * output spooling messages, pages, copies
36*33295Skarels  *
37*33295Skarels  * Revision 1.2  85/05/14  11:22:14  shore
38*33295Skarels  * *** empty log message ***
39*33295Skarels  *
40*33295Skarels  *
41*33295Skarels  */
42*33295Skarels 
43*33295Skarels #define POSTSCRIPTPRINTER "PostScript"
44*33295Skarels 
45*33295Skarels #define BODYROMAN "Courier"
46*33295Skarels #define HEADFONT "Courier-Bold"
47*33295Skarels 
48*33295Skarels #ifdef DEBUG
49*33295Skarels #define debugp(x) {fprintf x ; VOIDC fflush(stderr);}
50*33295Skarels #else
51*33295Skarels #define debugp(x)
52*33295Skarels #endif
53*33295Skarels 
54*33295Skarels #define UperInch (1440L)
55*33295Skarels #define PtsPerInch 72
56*33295Skarels #define UperPt 20
57*33295Skarels 
58*33295Skarels /* virtual page is 8 x 10.5 inches (for Toshiba compat) */
59*33295Skarels #define PageWidth ((long) UperInch*8)
60*33295Skarels #define PageLength ((long)((UperInch*21)/2))
61*33295Skarels 
62*33295Skarels /*#define PageLength ((long) ((long) (UperInch*(8*11-3)))/8) */
63*33295Skarels /*#define PageWidth  ((long) ((long) (UperInch*(8*17-3)))/8) */
64*33295Skarels 
65*33295Skarels /* true page is 8.5 x 11 inches */
66*33295Skarels #define TruePageWidth  (UperInch*17/2)
67*33295Skarels #define TruePageLength ((long)(UperInch*11))
68*33295Skarels 
69*33295Skarels #include <stdio.h>
70*33295Skarels #include <ctype.h>
71*33295Skarels #include <pwd.h>
72*33295Skarels #ifdef SYSV
73*33295Skarels struct passwd *getpwuid();
74*33295Skarels #include <string.h>
75*33295Skarels #include <time.h>
76*33295Skarels #else
77*33295Skarels #include <strings.h>
78*33295Skarels #include <sys/time.h>
79*33295Skarels #endif
80*33295Skarels #include <signal.h>
81*33295Skarels #include <sys/types.h>
82*33295Skarels #include <sys/stat.h>
83*33295Skarels #include "transcript.h"
84*33295Skarels 
85*33295Skarels #ifdef SYSV
86*33295Skarels #define LPR "lp"
87*33295Skarels #else
88*33295Skarels #define LPR "lpr"
89*33295Skarels #endif
90*33295Skarels 
91*33295Skarels #define MAXBAD 20	/* number of bad chars to pass before complaint */
92*33295Skarels 
93*33295Skarels private struct stat S;
94*33295Skarels 
95*33295Skarels extern char *optarg;		/* getopt current opt char */
96*33295Skarels extern int optind;		/* getopt argv index */
97*33295Skarels 
98*33295Skarels private VOID int1();
99*33295Skarels 
100*33295Skarels #define FSIZEMAX 256		/* number of chars per font */
101*33295Skarels 
102*33295Skarels /* the layout of a font information block */
103*33295Skarels private struct font {
104*33295Skarels     char    name[100];		/* PostScript font name */
105*33295Skarels     int     dsize;		/* size */
106*33295Skarels     int     Xwid[FSIZEMAX];	/* X widths for each character */
107*33295Skarels };
108*33295Skarels 
109*33295Skarels private struct font fonts[16];		/* 16 possible fonts at one time */
110*33295Skarels private int nf = 0;			/* number of fonts known about */
111*33295Skarels 
112*33295Skarels private int TabWidth = TruePageWidth / 10;	/* width of a tab */
113*33295Skarels private int BSWidth;				/* width of a backspace */
114*33295Skarels 
115*33295Skarels private long UperLine = UperInch / 7;
116*33295Skarels private long UperHLine = UperInch / 7;
117*33295Skarels 
118*33295Skarels private char *prog;		/* program name argv[0] */
119*33295Skarels private char *libdir;		/* place for prolog and widths files */
120*33295Skarels private char *tempdir;		/* place for temp file */
121*33295Skarels private char TempName[100];	/* name of temporary PostScript file */
122*33295Skarels private char OutName[256] = "";	/* filename for disk output */
123*33295Skarels private int PipeOut = FALSE;	/* output to stdout (-p -) */
124*33295Skarels private int ListOmitted = FALSE;/* list omitted chars on the tty */
125*33295Skarels private int BeQuiet = TRUE;	/* suppress stderr info messages */
126*33295Skarels private int Gaudy = FALSE;	/* pretty bars along the top */
127*33295Skarels private int LPTsimulate = FALSE;/* an lpt should be simulated */
128*33295Skarels private int Lines = 0;		/* max lines per page */
129*33295Skarels private int LinesLeft = 66;	/* lines left on page when in LPT mode */
130*33295Skarels private int LineMax = 64;	/* ? */
131*33295Skarels private int col;		/* column number on current line */
132*33295Skarels private int SeenText = TRUE;	/* true if seen some text on this page */
133*33295Skarels private int OutOnly = FALSE;	/* PS file only wanted */
134*33295Skarels private int Rotated = FALSE;	/* pages to be rotated landscape */
135*33295Skarels private int PreFeed = FALSE;	/* prefeed should be enabled */
136*33295Skarels private int TwoColumn = FALSE;	/* two-column mode */
137*33295Skarels private int FirstCol = TRUE;	/* we're printing column 1 */
138*33295Skarels private int NoTitle = FALSE;	/* title line is suppressed */
139*33295Skarels private int Cvted = FALSE;	/* converted a file to PS format */
140*33295Skarels 
141*33295Skarels private int IgnoreGarbage = FALSE;/* garbage should be ignored */
142*33295Skarels private int SeenFile = FALSE;	/* a file has been processed */
143*33295Skarels private int SeenFont = FALSE;	/* we've seen a font request */
144*33295Skarels private int ScannedFonts = FALSE;/* we've scanned the font file */
145*33295Skarels private char *FileName = 0;	/* name of file currently being PSed */
146*33295Skarels private char *FileDate = 0;	/* last mod date of file being PSed */
147*33295Skarels private char DateStr[27];	/* thanks, but no thanks ctime! */
148*33295Skarels private int spoolNoBurst = FALSE;/* no break page flag for spooler */
149*33295Skarels 
150*33295Skarels #ifdef SYSV
151*33295Skarels private char *spoolTitle = NULL;
152*33295Skarels #endif
153*33295Skarels #ifdef BSD
154*33295Skarels private char *spoolJobClass = NULL;
155*33295Skarels private char *spoolJobName = NULL;
156*33295Skarels #endif
157*33295Skarels private char *PrinterName = NULL;
158*33295Skarels private int spoolNotify = 0;
159*33295Skarels private char *spoolCopies = "1";
160*33295Skarels 
161*33295Skarels private char tempstr[256];	/* various path names */
162*33295Skarels 
163*33295Skarels private int CurFont;		/* current Font */
164*33295Skarels private int fontindex[26];	/* table of fonts, indexed by font
165*33295Skarels 				   designator ('a' to 'z') */
166*33295Skarels /* indexes for default fonts */
167*33295Skarels 
168*33295Skarels #define Roman fontindex['r'-'a']
169*33295Skarels #define HeaderFont fontindex['h'-'a']
170*33295Skarels 
171*33295Skarels private long cX, cY;		/* current page positions */
172*33295Skarels private long dX, dY;		/* desired page positions */
173*33295Skarels private long lX, lY;		/* page positions of the start of the line */
174*33295Skarels private long crX, crY;		/* X and Y increments to apply to CR's */
175*33295Skarels private long maxX;		/* maximum x coord on line */
176*33295Skarels private long minY;		/* minimum y coord on page */
177*33295Skarels 
178*33295Skarels #define None	0
179*33295Skarels #define RelX	1
180*33295Skarels #define	RelY	2
181*33295Skarels #define RelXY	3
182*33295Skarels #define AbsX	4
183*33295Skarels #define AbsY	8
184*33295Skarels #define AbsXY	12
185*33295Skarels 
186*33295Skarels private int movepending;	/* moveto pending coords on stack */
187*33295Skarels private int showpending;	/* number of characters waiting to be shown */
188*33295Skarels private int pagepending;	/* start on next page when have something to print */
189*33295Skarels private char *UsersHeader = NULL;/* user specified heading */
190*33295Skarels private char *Header = NULL;	/* generated header (usually FileName) */
191*33295Skarels private int Page = 0;		/* current page number */
192*33295Skarels private int TotalPages = 0;	/* total number of pages printed */
193*33295Skarels private int TruncChars = 0;	/* number of characters truncated */
194*33295Skarels private int UndefChars = 0;	/* number of characters skipped because
195*33295Skarels 				   they weren't defined in some font */
196*33295Skarels private int BadChars   = 0;	/* number of bad characters seen so far */
197*33295Skarels private FILE *OutFile = NULL;	/* output ps file */
198*33295Skarels 
199*33295Skarels 
200*33295Skarels /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
201*33295Skarels private decodefont(name, f)
202*33295Skarels register char *name;
203*33295Skarels register struct font *f; {
204*33295Skarels     register char *d, *p;
205*33295Skarels 
206*33295Skarels     SeenFont = TRUE;
207*33295Skarels     p = name;
208*33295Skarels     d = f->name;
209*33295Skarels     f->dsize = 0;
210*33295Skarels     while (isascii(*p) && (isalpha(*p) || (*p == '-'))) {*d++ = *p++;}
211*33295Skarels     *d++ = '\0';
212*33295Skarels     while (isascii(*p) && isdigit(*p)) {
213*33295Skarels 	f->dsize = f->dsize * 10 + *p++ - '0';
214*33295Skarels     }
215*33295Skarels     if (*p || !f->dsize || !f->name[0]) {
216*33295Skarels 	fprintf(stderr, "%s: poorly formed font name & size: \"%s\"\n",
217*33295Skarels 		prog, name);
218*33295Skarels 	exit (1);
219*33295Skarels     }
220*33295Skarels }
221*33295Skarels 
222*33295Skarels #define NOTDEF 0x8000
223*33295Skarels #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
224*33295Skarels 
225*33295Skarels 
226*33295Skarels /* Scan the font metrics directory looking for entries that match the
227*33295Skarels  * entries in ``fonts''.  For entries
228*33295Skarels  * that are found the data in the font description is filled in,
229*33295Skarels  * if any are missing, it dies horribly.
230*33295Skarels  */
231*33295Skarels private VOID ScanFont() {
232*33295Skarels     register struct font   *f;
233*33295Skarels     register FILE *FontData;		/* afm file */
234*33295Skarels     char *c;
235*33295Skarels     int ccode, cwidth, inChars;
236*33295Skarels     char FontFile[512];		/* afm file name */
237*33295Skarels     char afmbuf[BUFSIZ];
238*33295Skarels #ifdef SYSV
239*33295Skarels     char shortname[15];
240*33295Skarels #endif
241*33295Skarels 
242*33295Skarels     if (!SeenFont) {
243*33295Skarels 	if (Lines == 0) Lines = 64;
244*33295Skarels 	if (Rotated && TwoColumn) fonts[Roman].dsize = 7;
245*33295Skarels     }
246*33295Skarels 
247*33295Skarels     /* loop through fonts, find and read metric entry in dir */
248*33295Skarels     ForAllFonts (f) {
249*33295Skarels 	VOIDC mstrcat(FontFile, libdir, "/", sizeof FontFile);
250*33295Skarels #ifdef SYSV
251*33295Skarels 	VOIDC mapname(f->name,shortname);
252*33295Skarels 	VOIDC mstrcat(FontFile, FontFile, shortname, sizeof FontFile);
253*33295Skarels #else
254*33295Skarels 	VOIDC mstrcat(FontFile, FontFile, f->name, sizeof FontFile);
255*33295Skarels #endif
256*33295Skarels 	VOIDC mstrcat(FontFile, FontFile, ".afm", sizeof FontFile);
257*33295Skarels 	if ((FontData = fopen(FontFile,"r")) == NULL){
258*33295Skarels 	    fprintf(stderr,"%s: can't open font metrics file %s\n",
259*33295Skarels 	    	prog,FontFile);
260*33295Skarels 	    exit(1);
261*33295Skarels 	}
262*33295Skarels 	/* read the .afm file to get the widths */
263*33295Skarels 	for (ccode = 0; ccode < FSIZEMAX; ccode++) f->Xwid[ccode] = NOTDEF;
264*33295Skarels 
265*33295Skarels 	inChars = 0;
266*33295Skarels 	while(fgets(afmbuf, sizeof afmbuf, FontData) != NULL) {
267*33295Skarels 	    /* strip off newline */
268*33295Skarels 	    if ((c = INDEX(afmbuf, '\n')) == 0) {
269*33295Skarels 		fprintf(stderr, "%s: AFM file %s line too long %s\n",
270*33295Skarels 			prog, FontFile, afmbuf);
271*33295Skarels 		exit(1);
272*33295Skarels 	    }
273*33295Skarels 	    *c = '\0';
274*33295Skarels 	    if (*afmbuf == '\0') continue;
275*33295Skarels 	    if (strcmp(afmbuf, "StartCharMetrics") == 0) {
276*33295Skarels 		inChars++;
277*33295Skarels 		continue;
278*33295Skarels 	    }
279*33295Skarels 	    if (strcmp(afmbuf, "EndCharMetrics") == 0) break;
280*33295Skarels 	    if (inChars == 1) {
281*33295Skarels 		if (sscanf(afmbuf, "C %d ; WX %d ;",&ccode,&cwidth) != 2) {
282*33295Skarels 		    fprintf(stderr,"%s: trouble with AFM file %s\n",
283*33295Skarels 		    	prog,FontFile);
284*33295Skarels 		    exit(1);
285*33295Skarels 		}
286*33295Skarels 		/* get out once we see an unencoded char */
287*33295Skarels 		if (ccode == -1) break;
288*33295Skarels 		if (ccode > 255) continue;
289*33295Skarels 		f->Xwid[ccode] =
290*33295Skarels 		    (short)(((long) cwidth * (long) f->dsize * (long) UperPt)
291*33295Skarels 		    	/ 1000L);
292*33295Skarels 		continue;
293*33295Skarels 	    }
294*33295Skarels 	}
295*33295Skarels     VOIDC fclose(FontData);
296*33295Skarels     }
297*33295Skarels 
298*33295Skarels     TabWidth = fonts[Roman].Xwid['0'] * 8; /* 8 * figure width */
299*33295Skarels     BSWidth = fonts[Roman].Xwid[' ']; /* space width */
300*33295Skarels 
301*33295Skarels     UperLine = (fonts[Roman].dsize + 1) * UperPt;
302*33295Skarels 
303*33295Skarels     if (LPTsimulate) {
304*33295Skarels 	UperHLine = UperLine;
305*33295Skarels 	Lines = LineMax = 66;
306*33295Skarels     }
307*33295Skarels     else {
308*33295Skarels 	UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
309*33295Skarels     }
310*33295Skarels 
311*33295Skarels     crX = 0;
312*33295Skarels     crY = -UperLine;
313*33295Skarels 
314*33295Skarels }
315*33295Skarels 
316*33295Skarels 
317*33295Skarels /* Return a font number for the font with the indicated name
318*33295Skarels  * and size.  Adds info to the font list for the eventual search.
319*33295Skarels  */
320*33295Skarels private int DefineFont(name, size)
321*33295Skarels char *name; {
322*33295Skarels     register struct font   *p;
323*33295Skarels     p = &fonts[nf];
324*33295Skarels     VOIDC strcpy(p->name, name);
325*33295Skarels     p->dsize = size;
326*33295Skarels     return (nf++);
327*33295Skarels }
328*33295Skarels 
329*33295Skarels 
330*33295Skarels /* dump the fonts to the PS file for setup */
331*33295Skarels private VOID DumpFonts() {
332*33295Skarels     register struct font *f;
333*33295Skarels 
334*33295Skarels     ForAllFonts(f) {
335*33295Skarels         fprintf(OutFile,"%d %d /%s\n",f-&fonts[0],f->dsize*UperPt,f->name);
336*33295Skarels     }
337*33295Skarels     fprintf(OutFile, "%d SetUpFonts\n", nf);
338*33295Skarels }
339*33295Skarels 
340*33295Skarels 
341*33295Skarels /* add a shown character to the PS file */
342*33295Skarels private VOID OUTputc(c)
343*33295Skarels register int c; {
344*33295Skarels     if (!showpending) {putc('(', OutFile); showpending = TRUE;}
345*33295Skarels     if (c == '\\' || c=='(' || c == ')') putc('\\', OutFile);
346*33295Skarels     if ((c > 0176) || (c < 040)) {
347*33295Skarels 	putc('\\',OutFile);
348*33295Skarels 	putc((c >> 6) +'0',OutFile);
349*33295Skarels 	putc(((c >> 3) & 07)+'0', OutFile);
350*33295Skarels 	putc((c & 07)+'0',OutFile);
351*33295Skarels     }
352*33295Skarels     else putc(c, OutFile);
353*33295Skarels }
354*33295Skarels 
355*33295Skarels /* Set the current font */
356*33295Skarels private VOID SetFont(f)
357*33295Skarels int f; {
358*33295Skarels     FlushShow();
359*33295Skarels     CurFont = f;
360*33295Skarels     fprintf(OutFile, "%d F\n",f);
361*33295Skarels }
362*33295Skarels 
363*33295Skarels /* put a character onto the page at the desired X and Y positions.
364*33295Skarels  * If the current position doesn't agree with the desired position, put out
365*33295Skarels  * movement directives.  Leave the current position updated
366*33295Skarels  * to account for the character.
367*33295Skarels  */
368*33295Skarels private VOID ShowChar(c)
369*33295Skarels register int c; {
370*33295Skarels     register struct font   *f;
371*33295Skarels     register long nX, nY;
372*33295Skarels     static level = 0;
373*33295Skarels 
374*33295Skarels     level++;
375*33295Skarels     f = &fonts[CurFont];
376*33295Skarels 
377*33295Skarels     if (f->Xwid[c] == NOTDEF) {
378*33295Skarels 	UndefChars++;
379*33295Skarels 	if(ListOmitted)
380*33295Skarels 	    fprintf(stderr, "%s: \\%03o not found in font %s\n",
381*33295Skarels 	    	prog,c,f->name);
382*33295Skarels 	if(level<=1){
383*33295Skarels 	    ShowChar('\\');
384*33295Skarels 	    ShowChar((c>>6)+'0');
385*33295Skarels 	    ShowChar(((c>>3)&07)+'0');
386*33295Skarels 	    ShowChar((c&07)+'0');
387*33295Skarels 	    col += 3;
388*33295Skarels 	}
389*33295Skarels 	level--;
390*33295Skarels 	return;
391*33295Skarels     }
392*33295Skarels     nX = dX + f->Xwid[c]; /* resulting position after showing this char */
393*33295Skarels     nY = dY;
394*33295Skarels 
395*33295Skarels     if (c != ' ' || ((cX == dX) && (cY == dY))) {
396*33295Skarels 	if(nX <= maxX) {
397*33295Skarels 	    if (cX != dX) {
398*33295Skarels 	       if (cY != dY) {
399*33295Skarels 		  FlushShow();
400*33295Skarels 		  /* absolute x, relative y */
401*33295Skarels 		  fprintf(OutFile,"%ld %ld",dX, dY);
402*33295Skarels 		  movepending = AbsXY;
403*33295Skarels 		  }
404*33295Skarels 	       else {
405*33295Skarels 		  FlushShow();
406*33295Skarels 		  fprintf(OutFile,"%ld",dX-cX); /* relative x */
407*33295Skarels 		  movepending = RelX;
408*33295Skarels 		  }
409*33295Skarels 	    }
410*33295Skarels 	    else if (cY != dY) {
411*33295Skarels 		FlushShow();
412*33295Skarels 		fprintf(OutFile,"%ld",dY-cY); /* relative y */
413*33295Skarels 		movepending = RelY;
414*33295Skarels 		}
415*33295Skarels 	    OUTputc (c);
416*33295Skarels 	    showpending = TRUE;
417*33295Skarels 	    cX = nX;
418*33295Skarels 	    cY = nY;
419*33295Skarels 	}
420*33295Skarels 	else TruncChars++;
421*33295Skarels     }
422*33295Skarels     dX = nX;
423*33295Skarels     dY = nY;
424*33295Skarels 
425*33295Skarels     level--;
426*33295Skarels }
427*33295Skarels 
428*33295Skarels /* put out a shown string to the PS file */
429*33295Skarels private VOID ShowStr(s)
430*33295Skarels register char *s; {
431*33295Skarels     while (*s) {
432*33295Skarels 	if (*s >= 040) ShowChar (*s);
433*33295Skarels 	s++;
434*33295Skarels     }
435*33295Skarels }
436*33295Skarels 
437*33295Skarels /* flush pending show */
438*33295Skarels private FlushShow() {
439*33295Skarels     if (showpending) {
440*33295Skarels        putc(')',OutFile);
441*33295Skarels 	switch (movepending) {
442*33295Skarels 	    case RelX:
443*33295Skarels 		putc('X',OutFile);
444*33295Skarels 		break;
445*33295Skarels 	    case RelY:
446*33295Skarels 	    	putc('Y',OutFile);
447*33295Skarels 		break;
448*33295Skarels 	    case AbsXY:
449*33295Skarels 	    	putc('B',OutFile);
450*33295Skarels 		break;
451*33295Skarels 	    case None:
452*33295Skarels 	    	putc('S',OutFile);
453*33295Skarels 	    	break;
454*33295Skarels 	}
455*33295Skarels 	putc('\n',OutFile);
456*33295Skarels 	movepending = None;
457*33295Skarels 	showpending = FALSE;
458*33295Skarels     }
459*33295Skarels }
460*33295Skarels 
461*33295Skarels /* put out a page heading to the PS file */
462*33295Skarels private VOID InitPage() {
463*33295Skarels     char header[200];
464*33295Skarels     register int OldFont = CurFont;
465*33295Skarels 
466*33295Skarels     TotalPages++;
467*33295Skarels     fprintf(OutFile, "%%%%Page: ? %d\n", TotalPages);
468*33295Skarels     fprintf(OutFile, "StartPage\n");
469*33295Skarels     SeenText = FALSE;
470*33295Skarels     cX = cY = -1;
471*33295Skarels     showpending = pagepending = FALSE;
472*33295Skarels     FirstCol = TRUE;
473*33295Skarels     if (Rotated) {
474*33295Skarels         fprintf(OutFile, "Landscape\n");
475*33295Skarels 	lX = dX = UperInch / 4;
476*33295Skarels 	lY = dY = PageLength - (UperHLine * 3) / 2;
477*33295Skarels 	maxX = TruePageLength;
478*33295Skarels /*	minY = (PageLength - TruePageWidth) + 3*UperLine+480; */
479*33295Skarels 	minY = (TruePageLength-TruePageWidth)+(TruePageWidth-PageWidth)/2;
480*33295Skarels     }
481*33295Skarels     else {
482*33295Skarels 	lX = dX = TwoColumn ? (UperInch * 0.3) : ((UperInch * 5)/8);
483*33295Skarels 	lY = dY = PageLength - UperHLine;
484*33295Skarels 	maxX = TruePageWidth;
485*33295Skarels 	minY = (UperInch/4);	/* 0.25 inches */
486*33295Skarels     }
487*33295Skarels     movepending = None;
488*33295Skarels     cX = dX; cY = dY;
489*33295Skarels 
490*33295Skarels     if (!NoTitle) {
491*33295Skarels 	if (Gaudy) {
492*33295Skarels 	    fprintf(OutFile, "(%s)(%s)[%s](%d)Gaudy\n",
493*33295Skarels 		UsersHeader, Header, FileDate, ++Page);
494*33295Skarels 	    cX = cY = 0; /* force moveto here */
495*33295Skarels 	}
496*33295Skarels 	else {
497*33295Skarels 	    SetFont(HeaderFont);
498*33295Skarels 	    fprintf(OutFile, "%ld %ld ", cX, cY);
499*33295Skarels 	    movepending = AbsXY;
500*33295Skarels 	    if (UsersHeader) {
501*33295Skarels 		if (*UsersHeader == 0) {
502*33295Skarels 		    fprintf(OutFile,"()B\n");
503*33295Skarels 		    movepending = None;
504*33295Skarels 		    showpending = FALSE;
505*33295Skarels 		}
506*33295Skarels 		else ShowStr(UsersHeader);
507*33295Skarels 	    }
508*33295Skarels 	    else {
509*33295Skarels 		VOIDC sprintf(header, "%s        %s        %d",
510*33295Skarels 			Header ? Header : "              ", FileDate, ++Page);
511*33295Skarels 		ShowStr(header);
512*33295Skarels 	    }
513*33295Skarels 	    FlushShow();
514*33295Skarels 	}
515*33295Skarels 	dX = lX = lX + crX * 2;
516*33295Skarels 	dY = lY = lY + crY * 2;
517*33295Skarels     }
518*33295Skarels     else {
519*33295Skarels 	/* fake it to force a moveto */
520*33295Skarels 	cX = cY = 0;
521*33295Skarels     }
522*33295Skarels     if (TwoColumn) maxX = maxX/2 - BSWidth;
523*33295Skarels     else maxX -= ((long) (UperInch * 0.3));
524*33295Skarels     LineMax = (lY - minY) / (-crY);
525*33295Skarels     if ((Lines <= 0) || (Lines > LineMax)) Lines = LinesLeft = LineMax;
526*33295Skarels     else LinesLeft = Lines;
527*33295Skarels     SetFont(OldFont);
528*33295Skarels }
529*33295Skarels 
530*33295Skarels private VOID ClosePage() {
531*33295Skarels     FlushShow();
532*33295Skarels     if (!pagepending) fprintf(OutFile,"EndPage\n");
533*33295Skarels     pagepending = TRUE;
534*33295Skarels }
535*33295Skarels 
536*33295Skarels /* skip to a new page */
537*33295Skarels private VOID PageEject() {
538*33295Skarels     if (TwoColumn && FirstCol) {
539*33295Skarels 	FirstCol = FALSE;
540*33295Skarels 	if (Rotated) {
541*33295Skarels 	    lY = dY = PageLength - (UperHLine * 3) / 2;
542*33295Skarels 	    lX = dX = TruePageLength / 2;
543*33295Skarels 	    maxX = TruePageLength - UperInch * 0.3;
544*33295Skarels 	}
545*33295Skarels 	else {
546*33295Skarels 	    lY = dY = PageLength - UperHLine;
547*33295Skarels 	    lX = dX = TruePageWidth / 2;
548*33295Skarels 	    maxX = TruePageWidth - UperInch * 0.3;
549*33295Skarels 	}
550*33295Skarels 	if (!NoTitle) {
551*33295Skarels 	    dX = lX = lX + crX * 2;
552*33295Skarels 	    dY = lY = lY + crY * 2;
553*33295Skarels 	}
554*33295Skarels     }
555*33295Skarels     else ClosePage();
556*33295Skarels     LinesLeft = Lines;
557*33295Skarels     SeenText = FALSE;
558*33295Skarels }
559*33295Skarels 
560*33295Skarels private VOID CommentHeader() {
561*33295Skarels     long clock;
562*33295Skarels     struct passwd *pswd;
563*33295Skarels     char hostname[40];
564*33295Skarels     /* copy the file, prepending a new comment header */
565*33295Skarels     fprintf(OutFile,"%%!%s\n",COMMENTVERSION);
566*33295Skarels     fprintf(OutFile,"%%%%Creator: ");
567*33295Skarels     pswd = getpwuid((int) getuid());
568*33295Skarels     VOIDC gethostname(hostname, (int) sizeof hostname);
569*33295Skarels     fprintf(OutFile,"%s:%s (%s)\n", hostname, pswd->pw_name, pswd->pw_gecos);
570*33295Skarels     fprintf(OutFile,"%%%%Title: %s\n",(FileName?FileName:"stdin"));
571*33295Skarels     fprintf(OutFile,"%%%%CreationDate: %s",(VOIDC time(&clock),ctime(&clock)));
572*33295Skarels }
573*33295Skarels 
574*33295Skarels /* Copy the standard input file to the PS file */
575*33295Skarels private VOID CopyFile() {
576*33295Skarels     register int c;
577*33295Skarels 
578*33295Skarels     col = 1;
579*33295Skarels     if (OutFile == 0) {
580*33295Skarels 	if (OutOnly) {
581*33295Skarels 	   OutFile = PipeOut ? stdout : fopen(OutName,"w");
582*33295Skarels 	}
583*33295Skarels 	else {
584*33295Skarels 	    VOIDC mktemp(mstrcat(TempName,tempdir,
585*33295Skarels 	    	ENSCRIPTTEMP,sizeof TempName));
586*33295Skarels 	    VOIDC strcpy(OutName,TempName);
587*33295Skarels #ifdef SYSV
588*33295Skarels 	    VOIDC umask(0);
589*33295Skarels #else
590*33295Skarels 	    VOIDC umask(077);
591*33295Skarels #endif
592*33295Skarels 	    OutFile = fopen(TempName, "w");
593*33295Skarels 	}
594*33295Skarels     }
595*33295Skarels     if (OutFile == NULL) {
596*33295Skarels 	fprintf(stderr, "%s: can't create PS file %s\n",prog,TempName);
597*33295Skarels 	exit(1);
598*33295Skarels     }
599*33295Skarels     if (!ScannedFonts) {
600*33295Skarels 	ScannedFonts = TRUE;
601*33295Skarels 	ScanFont();
602*33295Skarels     }
603*33295Skarels     if (!Cvted) {
604*33295Skarels 	CommentHeader();
605*33295Skarels 	if (nf) {
606*33295Skarels 	    register struct font *f;
607*33295Skarels 	    fprintf(OutFile,"%%%%DocumentFonts:");
608*33295Skarels  	    ForAllFonts(f) {
609*33295Skarels 		fprintf(OutFile," %s",f->name);
610*33295Skarels 	    }
611*33295Skarels 	    if(Gaudy) {
612*33295Skarels 		fprintf(OutFile, " Times-Roman Times-Bold Helvetica-Bold");
613*33295Skarels 	    }
614*33295Skarels 	    fprintf(OutFile,"\n");
615*33295Skarels 	}
616*33295Skarels 	/* copy in fixed prolog */
617*33295Skarels 	if (copyfile(mstrcat(tempstr,libdir,ENSCRIPTPRO,sizeof tempstr),
618*33295Skarels 		OutFile)) {
619*33295Skarels 	    fprintf(stderr,"%s: trouble copying prolog file\n",prog);
620*33295Skarels 	    exit(1);
621*33295Skarels 	}
622*33295Skarels 	fprintf(OutFile,"StartEnscriptDoc %% end fixed prolog\n");
623*33295Skarels 	DumpFonts();
624*33295Skarels 	if(Gaudy)
625*33295Skarels 		fprintf(OutFile, "%s %s InitGaudy\n",
626*33295Skarels 		    Rotated ? "10.55" : "8.0", TwoColumn ? "true" : "false");
627*33295Skarels 	if (PreFeed) {
628*33295Skarels 	    fprintf(OutFile,"true DoPreFeed\n");
629*33295Skarels 	}
630*33295Skarels 	fprintf(OutFile,"%%%%EndProlog\n");
631*33295Skarels     }
632*33295Skarels     Cvted = TRUE;
633*33295Skarels 
634*33295Skarels     Page = 0;
635*33295Skarels     BadChars = 0;		/* give each file a clean slate */
636*33295Skarels     pagepending = TRUE;
637*33295Skarels     while ((c = getchar ()) != EOF)
638*33295Skarels 	if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
639*33295Skarels 	    if (BadChars++ > MAXBAD) {/* allow some kruft but not much */
640*33295Skarels 	      fprintf(stderr,"%s: \"%s\" not a text file? Try -g.\n",
641*33295Skarels 		    prog, FileName ? FileName : "(stdin)");
642*33295Skarels 		    if (!PipeOut) VOIDC unlink(OutName);
643*33295Skarels 	      exit(1);
644*33295Skarels 	    }
645*33295Skarels 	}
646*33295Skarels 	else
647*33295Skarels 	    if (c >= ' ') {
648*33295Skarels 		if (pagepending) InitPage();
649*33295Skarels 		ShowChar (c);
650*33295Skarels 		col++;
651*33295Skarels 	    }
652*33295Skarels 	    else switch (c) {
653*33295Skarels 		case 010: /* backspace */
654*33295Skarels 		    dX -= BSWidth;
655*33295Skarels 		    break;
656*33295Skarels 		case 015: /* carriage return ^M */
657*33295Skarels 		    dY = lY;
658*33295Skarels 		    dX = lX;
659*33295Skarels 		    break;
660*33295Skarels 		case 012: /* linefeed ^J */
661*33295Skarels 		    if (pagepending) InitPage();
662*33295Skarels 		    if (dX != lX || dY != lY || !LPTsimulate || SeenText){
663*33295Skarels 			SeenText = TRUE;
664*33295Skarels 			dY = lY = lY + crY;
665*33295Skarels 			dX = lX = lX + crX;
666*33295Skarels 		    }
667*33295Skarels 		    else
668*33295Skarels 			LinesLeft = LineMax;
669*33295Skarels 		    if ((dY < minY) || (--LinesLeft <= 0)) PageEject();
670*33295Skarels 		    col = 1;
671*33295Skarels 		    break;
672*33295Skarels 		case 033: /* escape */
673*33295Skarels 		    switch (c = getchar ()) {
674*33295Skarels 			case '7': /* backup one line */
675*33295Skarels 			    dY = lY = lY - crY;
676*33295Skarels 			    dX = lX = lX - crX;
677*33295Skarels 			    break;
678*33295Skarels 			case '8':  /* backup 1/2 line */
679*33295Skarels 			    dY -= crY / 2;
680*33295Skarels 			    dX -= crX / 2;
681*33295Skarels 			    break;
682*33295Skarels 			case '9':  /* forward 1/2 linefeed */
683*33295Skarels 			    dY += crY / 2;
684*33295Skarels 			    dX += crX / 2;
685*33295Skarels 			    break;
686*33295Skarels 			case 'F': /* font setting */
687*33295Skarels 			    c = getchar ();
688*33295Skarels 			    if ('a' <= c && c <= 'z')
689*33295Skarels 				if (fontindex[c - 'a'] >= 0)
690*33295Skarels 				    SetFont (fontindex[c - 'a']);
691*33295Skarels 				else {
692*33295Skarels 				    fprintf(stderr,"%s: font '%c' not defined\n",
693*33295Skarels 					prog, c);
694*33295Skarels 				    exit(1);
695*33295Skarels 				}
696*33295Skarels 			    else {
697*33295Skarels 				fprintf(stderr,"%s: bad font code in file: '%c'\n",
698*33295Skarels 				    prog, c);
699*33295Skarels 				exit(1);
700*33295Skarels 			    }
701*33295Skarels 			    break;
702*33295Skarels 			case 'D': /* date string */
703*33295Skarels 				VOIDC gets(DateStr);
704*33295Skarels 				FileDate = DateStr;
705*33295Skarels 				break;
706*33295Skarels 			case 'U': /* new "user's" heading */
707*33295Skarels 			    {
708*33295Skarels 				static char header[100];
709*33295Skarels 				VOIDC gets(header);
710*33295Skarels 				UsersHeader = header;
711*33295Skarels 				break;
712*33295Skarels 			    }
713*33295Skarels 			case 'H': /* new heading */
714*33295Skarels 			    {
715*33295Skarels 				static char header[100];
716*33295Skarels 
717*33295Skarels 				VOIDC gets(header);
718*33295Skarels 				ClosePage();
719*33295Skarels 				Header = header;
720*33295Skarels 				Page = 0;
721*33295Skarels 				break;
722*33295Skarels 			    }
723*33295Skarels 		    }
724*33295Skarels 		    break;
725*33295Skarels 		case '%': /* included PostScript line */
726*33295Skarels 		    {	char psline[200];
727*33295Skarels 			VOIDC gets(psline);
728*33295Skarels 			fprintf(OutFile, "%s\n", psline);
729*33295Skarels 			break;
730*33295Skarels 		    }
731*33295Skarels 		case 014: /* form feed ^L */
732*33295Skarels 		    PageEject ();
733*33295Skarels 		    col = 1;
734*33295Skarels 		    break;
735*33295Skarels 		case 011: /* tab ^I */
736*33295Skarels 		    if (pagepending) InitPage();
737*33295Skarels 		    col = (col - 1) / 8 * 8 + 9;
738*33295Skarels 		    dX = lX + (col - 1) / 8 * TabWidth;
739*33295Skarels 		    break;
740*33295Skarels 		default: /* other control character, take your chances */
741*33295Skarels 		    if (pagepending) InitPage();
742*33295Skarels 		    ShowChar(c);
743*33295Skarels 		    col++;
744*33295Skarels 	    }
745*33295Skarels     ClosePage();
746*33295Skarels }
747*33295Skarels 
748*33295Skarels 
749*33295Skarels /*
750*33295Skarels  * close the PS file
751*33295Skarels  */
752*33295Skarels private VOID ClosePS() {
753*33295Skarels     fprintf(OutFile,"%%%%Trailer\n");
754*33295Skarels     if (PreFeed) {
755*33295Skarels 	fprintf(OutFile,"false DoPreFeed\n");
756*33295Skarels     }
757*33295Skarels     fprintf(OutFile,"EndEnscriptDoc\nEnscriptJob restore\n");
758*33295Skarels }
759*33295Skarels 
760*33295Skarels 
761*33295Skarels private VOID SetTime(tval)
762*33295Skarels long tval; {
763*33295Skarels     struct tm *tp;
764*33295Skarels 
765*33295Skarels     if (Gaudy) {
766*33295Skarels 	tp = localtime(&tval);
767*33295Skarels 	VOIDC sprintf(DateStr, "(%02d/%02d/%02d)(%02d:%02d:%02d)",
768*33295Skarels 		tp->tm_year, tp->tm_mon+1, tp->tm_mday,
769*33295Skarels 		tp->tm_hour, tp->tm_min, tp->tm_sec);
770*33295Skarels     }
771*33295Skarels     else {
772*33295Skarels 	VOIDC strcpy(DateStr, ctime(&tval));
773*33295Skarels 	DateStr[24] = '\0'; /* get rid of newline */
774*33295Skarels     }
775*33295Skarels 
776*33295Skarels     FileDate = DateStr;
777*33295Skarels }
778*33295Skarels 
779*33295Skarels 
780*33295Skarels 
781*33295Skarels #ifdef SYSV
782*33295Skarels #define ARGS "12gGBlL:oqrRkKmf:F:b:p:t:d:n:w:h"
783*33295Skarels #else
784*33295Skarels #define ARGS "12gGBlL:oqrRkKf:F:b:p:J:C:P:#:mh"
785*33295Skarels #endif
786*33295Skarels 
787*33295Skarels private VOID ParseArgs(ac, av)
788*33295Skarels int ac;
789*33295Skarels char **av; {
790*33295Skarels     int argp;
791*33295Skarels 
792*33295Skarels     while ((argp = getopt(ac, av, ARGS)) != EOF) {
793*33295Skarels 	debugp((stderr,"option: %c\n",argp));
794*33295Skarels 	switch (argp) {
795*33295Skarels 	    case '1': TwoColumn = FALSE; break;
796*33295Skarels 	    case '2': TwoColumn = TRUE; break;
797*33295Skarels 	    case 'G':
798*33295Skarels 		Gaudy = TRUE;
799*33295Skarels 		if (UsersHeader == NULL) UsersHeader = "";
800*33295Skarels 		if (Header == NULL) Header = "";
801*33295Skarels 		break;
802*33295Skarels 	    case 'g': IgnoreGarbage = TRUE; break;
803*33295Skarels 	    case 'B': NoTitle = TRUE; break;
804*33295Skarels 	    case 'l': LPTsimulate = TRUE; NoTitle = TRUE; Lines = 66; break;
805*33295Skarels 	    case 'L': Lines = atoi(optarg); break;
806*33295Skarels 	    case 'o': ListOmitted = TRUE; break;
807*33295Skarels 	    case 'q': BeQuiet = !BeQuiet; break;
808*33295Skarels 	    case 'r': Rotated = TRUE; break;
809*33295Skarels 	    case 'R': Rotated = FALSE; break;
810*33295Skarels 	    case 'k': PreFeed = TRUE; break;
811*33295Skarels 	    case 'K': PreFeed = FALSE; break;
812*33295Skarels 	    case 'f': {
813*33295Skarels 		register char font = 'r';
814*33295Skarels 		int *whichfont;
815*33295Skarels 
816*33295Skarels 	        if (*optarg == '-') {
817*33295Skarels 		    font = *++optarg;
818*33295Skarels 		    optarg++;
819*33295Skarels 		}
820*33295Skarels 		if ((font < 'a') || ('z' < font)) {
821*33295Skarels 		    fprintf(stderr,
822*33295Skarels 			"%s: '%c' isn't a valid font designator.\n",
823*33295Skarels 			prog, font);
824*33295Skarels 		    exit(1);
825*33295Skarels 		}
826*33295Skarels 		whichfont = &fontindex[font - 'a'];
827*33295Skarels 		if (*whichfont < 0)
828*33295Skarels 		    *whichfont = nf++;
829*33295Skarels 		decodefont (optarg, &fonts[*whichfont]);
830*33295Skarels 	        }
831*33295Skarels 		break;
832*33295Skarels 	    case 'F':
833*33295Skarels 		decodefont (optarg, &fonts[HeaderFont]);
834*33295Skarels 		break;
835*33295Skarels 	    case 'b':
836*33295Skarels 	        UsersHeader = optarg;
837*33295Skarels 		break;
838*33295Skarels 	    case 'p':
839*33295Skarels 		OutOnly = TRUE;
840*33295Skarels 		VOIDC strcpy(OutName,optarg);
841*33295Skarels 		if (strcmp(OutName,"-") == 0) PipeOut = TRUE;
842*33295Skarels 		break;
843*33295Skarels 	    case 'h': spoolNoBurst = TRUE; break;
844*33295Skarels #ifdef SYSV
845*33295Skarels 	/* SYS V lp options processing */
846*33295Skarels 	    case 'm': case 'w':
847*33295Skarels 	    	spoolNotify = argp; break;
848*33295Skarels 	    case 'n': spoolCopies = optarg; break;
849*33295Skarels 	    case 'd': PrinterName = optarg; break;
850*33295Skarels 	    case 't': spoolTitle = optarg; break;
851*33295Skarels #else
852*33295Skarels 	/* BSD lpr options processing */
853*33295Skarels 	    case 'm': spoolNotify = argp; break;
854*33295Skarels 	    case '#': spoolCopies = optarg; break;
855*33295Skarels 	    case 'C': spoolJobClass = optarg; break;
856*33295Skarels 	    case 'J': spoolJobName = optarg; break;
857*33295Skarels 	    case 'P': PrinterName = optarg; break;
858*33295Skarels #endif
859*33295Skarels 	    case '?':
860*33295Skarels 	        /* bad option */
861*33295Skarels 		break;
862*33295Skarels 	    default:
863*33295Skarels 	    	break;
864*33295Skarels 	}
865*33295Skarels     }
866*33295Skarels }
867*33295Skarels 
868*33295Skarels 
869*33295Skarels /* addarg is used to construct an argv for the spooler */
870*33295Skarels private VOID addarg(argv, argstr, argc)
871*33295Skarels char **argv;
872*33295Skarels char *argstr;
873*33295Skarels register int *argc; {
874*33295Skarels     register char *p = (char *) malloc((unsigned) (strlen(argstr) + 1));
875*33295Skarels     VOIDC strcpy(p, argstr);
876*33295Skarels     argv[(*argc)++] = p;
877*33295Skarels     argv[*argc] = '\0';
878*33295Skarels }
879*33295Skarels 
880*33295Skarels 
881*33295Skarels private VOID SpoolIt() {
882*33295Skarels     char temparg[200];
883*33295Skarels     char *argstr[200];
884*33295Skarels     int nargs = 0;
885*33295Skarels #ifdef SYSV
886*33295Skarels     int cpid, wpid;
887*33295Skarels #endif
888*33295Skarels 
889*33295Skarels     addarg(argstr, LPR, &nargs);
890*33295Skarels #ifdef SYSV
891*33295Skarels     addarg(argstr, "-c", &nargs);
892*33295Skarels 
893*33295Skarels     if ((PrinterName == NULL) && ((PrinterName = envget("LPDEST")) == NULL)) {
894*33295Skarels 	PrinterName = POSTSCRIPTPRINTER;
895*33295Skarels     }
896*33295Skarels     VOIDC sprintf(temparg,"-d%s",PrinterName);
897*33295Skarels     addarg(argstr, temparg, &nargs);
898*33295Skarels     if (!BeQuiet) fprintf(stderr,"spooled to %s\n",PrinterName);
899*33295Skarels 
900*33295Skarels     if (spoolNotify) {
901*33295Skarels 	VOIDC sprintf(temparg,"-%c",spoolNotify);
902*33295Skarels 	addarg(argstr, temparg, &nargs);
903*33295Skarels     }
904*33295Skarels     if (atoi(spoolCopies) > 1) {
905*33295Skarels 	VOIDC sprintf(temparg,"-n%s",spoolCopies);
906*33295Skarels 	addarg(argstr, temparg, &nargs);
907*33295Skarels     }
908*33295Skarels     if (BeQuiet) {
909*33295Skarels 	addarg(argstr, "-s", &nargs);
910*33295Skarels     }
911*33295Skarels     if (spoolTitle) {
912*33295Skarels 	VOIDC sprintf(temparg,"-t%s",spoolTitle);
913*33295Skarels     }
914*33295Skarels     else {
915*33295Skarels 	VOIDC sprintf(temparg, "-t%s", (FileName == NULL) ? "stdin" : FileName);
916*33295Skarels     }
917*33295Skarels     if (spoolNoBurst) {
918*33295Skarels 	addarg(argstr,"-o-h",&nargs);
919*33295Skarels     }
920*33295Skarels     addarg(argstr, temparg, &nargs);
921*33295Skarels 
922*33295Skarels #else
923*33295Skarels     /* BSD spooler */
924*33295Skarels     if (atoi(spoolCopies) > 1) {
925*33295Skarels 	VOIDC sprintf(temparg,"-#%s",spoolCopies);
926*33295Skarels 	addarg(argstr, temparg, &nargs);
927*33295Skarels     }
928*33295Skarels     if ((PrinterName == NULL) && ((PrinterName = envget("PRINTER")) == NULL)){
929*33295Skarels 	PrinterName = POSTSCRIPTPRINTER;
930*33295Skarels     }
931*33295Skarels     VOIDC sprintf(temparg,"-P%s",PrinterName);
932*33295Skarels     addarg(argstr, temparg, &nargs);
933*33295Skarels     if (!BeQuiet) fprintf(stderr,"spooled to %s\n",PrinterName);
934*33295Skarels 
935*33295Skarels     if (spoolJobClass) {
936*33295Skarels 	addarg(argstr, "-C", &nargs);
937*33295Skarels 	addarg(argstr, spoolJobClass, &nargs);
938*33295Skarels     }
939*33295Skarels     addarg(argstr, "-J", &nargs);
940*33295Skarels     if (spoolJobName) {
941*33295Skarels 	addarg(argstr, spoolJobName, &nargs);
942*33295Skarels     }
943*33295Skarels     else {
944*33295Skarels 	if (!FileName) addarg(argstr, "stdin", &nargs);
945*33295Skarels 	else addarg(argstr, FileName, &nargs);
946*33295Skarels     }
947*33295Skarels     if (spoolNotify) {
948*33295Skarels 	addarg(argstr, "-m", &nargs);
949*33295Skarels     }
950*33295Skarels     if (spoolNoBurst) {
951*33295Skarels 	addarg(argstr, "-h", &nargs);
952*33295Skarels     }
953*33295Skarels 
954*33295Skarels     /* remove the temporary file after spooling */
955*33295Skarels     addarg(argstr, "-r", &nargs); /* should we use a symbolic link too? */
956*33295Skarels #endif
957*33295Skarels     addarg(argstr, TempName, &nargs);
958*33295Skarels 
959*33295Skarels #ifdef DEBUG
960*33295Skarels     { int i;
961*33295Skarels     fprintf(stderr,"called spooler with: ");
962*33295Skarels     for (i = 0; i < nargs ; i++) fprintf(stderr,"(%s)",argstr[i]);
963*33295Skarels     fprintf(stderr,"\n");
964*33295Skarels     }
965*33295Skarels #endif
966*33295Skarels 
967*33295Skarels #ifdef SYSV
968*33295Skarels     if ((cpid = fork()) < 0) {pexit2(prog,"can't fork spooler",1);}
969*33295Skarels     else if (cpid) {
970*33295Skarels 	while (wpid = wait((int *) 0) > 0) {if (wpid == cpid) break;}
971*33295Skarels 	VOIDC unlink(TempName);
972*33295Skarels     }
973*33295Skarels     else {
974*33295Skarels 	execvp(LPR, argstr);
975*33295Skarels 	pexit2(prog,"can't exec spooler",1);
976*33295Skarels     }
977*33295Skarels #else
978*33295Skarels     execvp(LPR, argstr);
979*33295Skarels     pexit2(prog,"can't exec spooler",1);
980*33295Skarels #endif
981*33295Skarels }
982*33295Skarels 
983*33295Skarels 
984*33295Skarels private char *eargv[60];
985*33295Skarels private int eargc = 1;
986*33295Skarels 
987*33295Skarels 
988*33295Skarels main(argc, argv)
989*33295Skarels int argc;
990*33295Skarels char  **argv; {
991*33295Skarels     register char *p;		/* pointer to "ENSCRIPT" in env */
992*33295Skarels 
993*33295Skarels     prog = *argv;		/* argv[0] is program name */
994*33295Skarels 
995*33295Skarels     debugp((stderr,"PL %ld PW %ld TPL %ld TPW %ld\n",PageLength,PageWidth,TruePageLength,TruePageWidth));
996*33295Skarels 
997*33295Skarels     if (signal(SIGINT, int1) == SIG_IGN) {
998*33295Skarels 	VOIDC signal(SIGINT, SIG_IGN);
999*33295Skarels 	VOIDC signal(SIGQUIT, SIG_IGN);
1000*33295Skarels 	VOIDC signal(SIGHUP, SIG_IGN);
1001*33295Skarels 	VOIDC signal(SIGTERM, SIG_IGN);
1002*33295Skarels     }
1003*33295Skarels     else {
1004*33295Skarels 	VOIDC signal(SIGQUIT, int1);
1005*33295Skarels 	VOIDC signal(SIGHUP, int1);
1006*33295Skarels 	VOIDC signal(SIGTERM, int1);
1007*33295Skarels     }
1008*33295Skarels 
1009*33295Skarels     {	register int    i;
1010*33295Skarels 	for (i = 0; i < 26; i++)
1011*33295Skarels 	    fontindex[i] = -1;
1012*33295Skarels     }
1013*33295Skarels 
1014*33295Skarels     if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir;
1015*33295Skarels     if ((tempdir = envget("PSTEMPDIR")) == NULL) tempdir = TempDir;
1016*33295Skarels 
1017*33295Skarels     Roman = CurFont = DefineFont (BODYROMAN, 10);
1018*33295Skarels     HeaderFont = DefineFont (HEADFONT, 10);
1019*33295Skarels 
1020*33295Skarels     /* process args in environment variable ENSCRIPT */
1021*33295Skarels     if (p = envget("ENSCRIPT")) {
1022*33295Skarels 	while (1) {
1023*33295Skarels 	    register char quote = ' ';
1024*33295Skarels 	    while (*p == ' ') p++;
1025*33295Skarels 	    if ((*p == '"') || (*p == '\'')) quote = *p++;
1026*33295Skarels 	    eargv[eargc++] = p;
1027*33295Skarels 	    while ((*p != quote) && (*p != '\0')) p++;
1028*33295Skarels 	    if (*p == '\0') break;
1029*33295Skarels 	    *p++ = '\0';
1030*33295Skarels 	}
1031*33295Skarels 	ParseArgs(eargc, eargv);
1032*33295Skarels 	if (eargc != optind) {
1033*33295Skarels 	    fprintf(stderr,"%s: bad environment variable ENSCRIPT \"%s\"\n",
1034*33295Skarels 	    	prog, envget("ENSCRIPT"));
1035*33295Skarels 	    exit(1);
1036*33295Skarels 	}
1037*33295Skarels     }
1038*33295Skarels 
1039*33295Skarels     /* process the command line arguments */
1040*33295Skarels     optind = 1; /* reset getopt global */
1041*33295Skarels     ParseArgs(argc, argv);
1042*33295Skarels 
1043*33295Skarels     /* process non-option args */
1044*33295Skarels     for (; optind < argc ; optind++) {
1045*33295Skarels 	FileName = Header = argv[optind];
1046*33295Skarels 	if (freopen (FileName, "r", stdin) == NULL) {
1047*33295Skarels 	    fprintf(stderr, "%s: can't open %s\n", prog, FileName);
1048*33295Skarels 	    exit (1);
1049*33295Skarels 	}
1050*33295Skarels 	VOIDC fstat(fileno (stdin), &S);
1051*33295Skarels 	SetTime(S.st_mtime);
1052*33295Skarels 	CopyFile();
1053*33295Skarels 	VOIDC fclose(stdin);
1054*33295Skarels 	SeenFile = TRUE;
1055*33295Skarels     }
1056*33295Skarels     if (!SeenFile) {
1057*33295Skarels 	FileName = Header = Gaudy ? "" : 0;
1058*33295Skarels 	VOIDC fstat(fileno (stdin), &S);
1059*33295Skarels 
1060*33295Skarels 	if ((S.st_mode & S_IFMT) == S_IFREG)
1061*33295Skarels 	    SetTime(S.st_mtime);
1062*33295Skarels 	else
1063*33295Skarels 	    SetTime(time((long *)0));
1064*33295Skarels 	CopyFile();
1065*33295Skarels     }
1066*33295Skarels 
1067*33295Skarels     if (Cvted) {
1068*33295Skarels 	ClosePS();
1069*33295Skarels 	VOIDC fclose(OutFile);
1070*33295Skarels 	OutFile = 0;
1071*33295Skarels     }
1072*33295Skarels     if (TruncChars && !BeQuiet)
1073*33295Skarels 	fprintf(stderr,"%s: %d characters omitted because of long lines.\n",
1074*33295Skarels 		prog, TruncChars);
1075*33295Skarels     if (UndefChars && !BeQuiet)
1076*33295Skarels 	fprintf(stderr,"%s: %d characters omitted because of incomplete fonts.\n",
1077*33295Skarels 		prog, UndefChars);
1078*33295Skarels     if (!BeQuiet && (TotalPages > 0)) {
1079*33295Skarels 	fprintf(stderr,"[ %d page%s * %s cop%s ] ",
1080*33295Skarels 		TotalPages, TotalPages > 1 ? "s" : "",
1081*33295Skarels 		spoolCopies, atoi(spoolCopies) > 1 ? "ies" : "y" );
1082*33295Skarels     }
1083*33295Skarels     if (Cvted) {
1084*33295Skarels 	if (OutOnly && !BeQuiet) {
1085*33295Skarels 	    fprintf(stderr,"left in %s\n", OutName);
1086*33295Skarels 	}
1087*33295Skarels 	else {
1088*33295Skarels 	    SpoolIt(); /* does an exec */
1089*33295Skarels 	}
1090*33295Skarels     }
1091*33295Skarels }
1092*33295Skarels 
1093*33295Skarels 
1094*33295Skarels /* signal catcher */
1095*33295Skarels private VOID int1() {
1096*33295Skarels     if ((!PipeOut) && (OutName != NULL) && (*OutName != '\0')) {
1097*33295Skarels 	VOIDC unlink(OutName);
1098*33295Skarels     }
1099*33295Skarels     exit(1);
1100*33295Skarels }
1101