xref: /csrg-svn/local/transcript/src/psgrind.c (revision 32180)
1*32180Sedward /*	@(#)psgrind.c	1.2 09/15/87	*/
232172Sedward /*
332172Sedward  *  psgrind - quick hack to grind C source files directly into
432172Sedward  *  PostScript.
532172Sedward  *
632172Sedward  *  John Coker
732172Sedward  *  University of California, Berkeley
832172Sedward  *
932172Sedward  *  The basis for this program is the enscript utility provided
1032172Sedward  *  by TranScript to driver the Apple LaserWriter printer.  This
1132172Sedward  *  code was taken and mangled without permission of any kind;
1232172Sedward  *  don't tell anyone.  -john
1332172Sedward  */
1432172Sedward 
1532172Sedward #define POSTSCRIPTPRINTER "gp"
1632172Sedward 
1732172Sedward #define HEADERFONT	"Helvetica-Bold"
1832172Sedward #define BODYFONT 	"Helvetica"
1932172Sedward #define KWORDFONT 	"Helvetica-Bold"
2032172Sedward #define COMMENTFONT	"Helvetica-Oblique"
2132172Sedward #define LITERALFONT  	"Courier"
2232172Sedward 
2332172Sedward #ifndef PSGRINDPRO
2432172Sedward #define PSGRINDPRO	"/psgrind.pro"
2532172Sedward #endif !PSGRINDPRO
2632172Sedward 
2732172Sedward #ifndef PSGRINDTEMP
2832172Sedward #define PSGRINDTEMP	"/GRXXXXXX"
2932172Sedward #endif !PSGRINDTEMP
3032172Sedward 
3132172Sedward #define UperInch 1440
3232172Sedward #define PtsPerInch 72
3332172Sedward #define UperPt 20
3432172Sedward #define TruePageWidth  (UperInch*17/2)
3532172Sedward #define PageWidth  (UperInch*(8*17-3)/4)
3632172Sedward #define PageLength (UperInch*(8*11-3)/8)
3732172Sedward #define TruePageLength (UperInch*11)
3832172Sedward 
3932172Sedward #include <stdio.h>
4032172Sedward #include <ctype.h>
4132172Sedward #include <strings.h>
4232172Sedward #include <pwd.h>
4332172Sedward #include <sys/types.h>
4432172Sedward #include <sys/stat.h>
4532172Sedward #include "transcript.h"
4632172Sedward 
4732172Sedward #define LPR "lpr"
4832172Sedward #define REVERSE "psrev"
4932172Sedward 
5032172Sedward #define MAXBAD 20	/* number of bad chars to pass before complaint */
5132172Sedward 
5232172Sedward private struct stat S;
5332172Sedward char   *ctime ();
5432172Sedward char   *getenv ();
5532172Sedward char   *rindex ();
5632172Sedward 
5732172Sedward #define FSIZEMAX 256		/* number of chars per font */
5832172Sedward 
5932172Sedward /* the layout of a font information block */
6032172Sedward struct font {
6132172Sedward     char    name[100];		/* PostScript font name */
6232172Sedward     int     dsize;		/* size */
6332172Sedward     int     Xwid[FSIZEMAX];	/* X widths for each character */
6432172Sedward };
6532172Sedward 
6632172Sedward private struct font fonts[16];		/* 16 possible fonts at one time */
6732172Sedward private int nf = 0;			/* number of fonts known about */
6832172Sedward 
6932172Sedward private int HeaderFont = -1;		/* handle for header font */
7032172Sedward private int BodyFont = -1;		/* handle for body font */
7132172Sedward private int KwordFont = -1;		/* handle for keyword font */
7232172Sedward private int LiteralFont = -1;		/* handle for literal font */
7332172Sedward private int CommentFont = -1;		/* handle for comment font */
7432172Sedward 
7532172Sedward private int TabWidth = TruePageWidth / 10;	/* width of a tab */
7632172Sedward private int BSWidth;				/* width of a backspace */
7732172Sedward 
7832172Sedward private int UperLine = UperInch / 7;
7932172Sedward private int UperHLine = UperInch / 7;
8032172Sedward 
8132172Sedward private char *prog;		/* program name argv[0] */
8232172Sedward private char TempName[100];	/* name of temporary PostScript file */
8332172Sedward private char OutName[256] = 0;	/* filename for disk output */
8432172Sedward private int PipeOut = 0;	/* true if output to stdout (-p -) */
8532172Sedward private int ListOmitted = 0;	/* list omitted chars on the tty */
8632172Sedward private int LPTsimulate = 0;	/* true if an lpt should be simulated */
8732172Sedward private int LinesLeft = 64;	/* lines left on page when in LPT mode */
8832172Sedward private int LineNo;		/* line number in current file */
8932172Sedward private int SeenText = 1;	/* true if seen some text on this page */
9032172Sedward private int OutOnly = 0;	/* true if PS file only wanted */
9132172Sedward private int Rotated = 0;	/* true if the page is to be rotated */
9232172Sedward private int Reverse = 0;	/* output should be piped to psrev */
9332172Sedward private char *PageSpec = 0;	/* ditto */
9432172Sedward private int PreFeed = 0;	/* true if prefeed should be enabled */
9532172Sedward private int TwoColumn = 0;	/* true of if in two-column mode */
9632172Sedward private int FirstCol = 1;	/* true if we're printing column 1 */
9732172Sedward private int NoTitle = 0;	/* true if title line is to be suppressed */
9832172Sedward private int Cvted = 0;		/* true if converted a file to PS format */
9932172Sedward 
10032172Sedward private int IgnoreGarbage = 0;	/* true if garbage should be ignored */
10132172Sedward private int SeenFile = 0;	/* true if a file has been processed */
10232172Sedward private int SeenFont = 0;	/* true if we've seen a font request */
10332172Sedward private int ScannedFonts = 0;	/* true if we've scanned the font file */
10432172Sedward private char *FileName = 0;	/* name of file currently being PSed */
10532172Sedward private char *FileDate = 0;	/* last mod date of file being PSed */
10632172Sedward private char DateStr[27];	/* thanks, but no thanks ctime! */
10732172Sedward 
10832172Sedward private char *spoolJobClass = 0;
10932172Sedward private char *spoolJobName = 0;
11032172Sedward private char *PrinterName = 0;
11132172Sedward private int spoolNotify = 0;
11232172Sedward private int spoolNoBurst = 0;
11332172Sedward private int spoolCopies = 1;
11432172Sedward 
11532172Sedward private char tempstr[256];	/* various path names */
11632172Sedward 
11732172Sedward private int CurFont;		/* current Font */
11832172Sedward private int LastFont;		/* previous Font */
11932172Sedward 
12032172Sedward private int cX, cY;		/* current page positions */
12132172Sedward private int dX, dY;		/* desired page positions */
12232172Sedward private int lX, lY;		/* page positions of the start of the line */
12332172Sedward private int crX, crY;		/* X and Y increments to apply to CR's */
12432172Sedward 
12532172Sedward #define None	0
12632172Sedward #define RelX	1
12732172Sedward #define	RelY	2
12832172Sedward #define RelXY	3
12932172Sedward #define AbsX	4
13032172Sedward #define AbsY	8
13132172Sedward #define AbsXY	12
13232172Sedward 
13332172Sedward private int movepending;	/* moveto pending coords on stack */
13432172Sedward private int showpending;	/* number of characters waiting to be shown */
13532172Sedward private char *UsersHeader = 0;	/* user specified heading */
13632172Sedward private char *Header = 0;	/* generated header (usually FileName) */
13732172Sedward private int Page = 0;		/* current page number */
13832172Sedward private int TotalPages = 0;	/* total number of pages printed */
13932172Sedward private int TruncChars = 0;	/* number of characters truncated */
14032172Sedward private int UndefChars = 0;	/* number of characters skipped because
14132172Sedward 				   they weren't defined in some font */
14232172Sedward private int BadChars   = 0;	/* number of bad characters seen so far */
14332172Sedward 
14432172Sedward private FILE *OutFile = 0;	/* output ps file */
14532172Sedward 
14632172Sedward /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
14732172Sedward private decodefont (name, f)
14832172Sedward register char  *name;
14932172Sedward register struct font *f; {
15032172Sedward     register char *d, *p;
15132172Sedward 
15232172Sedward     SeenFont++;
15332172Sedward     if (ScannedFonts) {
15432172Sedward 	fprintf(stderr,"Fonts must be specified before any files are processed\n");
15532172Sedward 	exit(1);
15632172Sedward     }
15732172Sedward     p = name;
15832172Sedward     d = f->name;
15932172Sedward     while (isascii(*p) && (isalpha(*p) || (*p == '-'))) {*d++ = *p++;}
16032172Sedward     *d++ = '\0';
16132172Sedward     if (isascii(*p) && isdigit(*p)) {
16232172Sedward 	f->dsize = 0;
16332172Sedward 	do
16432172Sedward 	    f->dsize = f->dsize * 10 + *p++ - '0';
16532172Sedward 	while ('0' <= *p && *p <= '9');
16632172Sedward     }
16732172Sedward     if (*p || !f->dsize || !f->name[0]) {
16832172Sedward 	fprintf (stderr, "Poorly formed font name: \"%s\"\n", name);
16932172Sedward 	exit (1);
17032172Sedward     }
17132172Sedward }
17232172Sedward 
17332172Sedward 
17432172Sedward #define NOTDEF 0x8000
17532172Sedward #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
17632172Sedward 
17732172Sedward /* Scan the font metrics directory looking for entries that match the
17832172Sedward  * entries in ``fonts''.  For entries
17932172Sedward  * that are found the data in the font description is filled in,
18032172Sedward  * if any are missing, it dies horribly.
18132172Sedward  */
18232172Sedward private ScanFont () {
18332172Sedward     register struct font   *f;
18432172Sedward     register FILE *FontData;		/* afm file */
18532172Sedward     char    *c;
18632172Sedward     int     ccode, cwidth, inChars;
18732172Sedward     char   *MetricsDir = (char *) getenv ("METRICS");
18832172Sedward     char    FontFile[512];		/* afm file name */
18932172Sedward     char    afmbuf[BUFSIZ];
19032172Sedward 
19132172Sedward     if (MetricsDir == 0)
19232172Sedward 	MetricsDir = LibDir;
19332172Sedward 
19432172Sedward     if (!SeenFont & Rotated & TwoColumn) {
19532172Sedward 	fonts[HeaderFont].dsize = 10;
19632172Sedward 	fonts[BodyFont].dsize = 7;
19732172Sedward 	fonts[KwordFont].dsize = 7;
19832172Sedward 	fonts[LiteralFont].dsize = 8;
19932172Sedward 	fonts[CommentFont].dsize = 7;
20032172Sedward     }
20132172Sedward 
20232172Sedward     /* loop through fonts, find and read metric entry in dir */
20332172Sedward     ForAllFonts (f) {
20432172Sedward 	mstrcat(FontFile, MetricsDir, "/", sizeof FontFile);
20532172Sedward 	mstrcat(FontFile, FontFile, f->name, sizeof FontFile);
20632172Sedward 	mstrcat(FontFile, FontFile, ".afm", sizeof FontFile);
20732172Sedward 	if ((FontData = fopen(FontFile,"r")) == NULL){
20832172Sedward 	    fprintf(stderr,"Can't open font metrics file %s\n",FontFile);
20932172Sedward 	    exit(1);
21032172Sedward 	}
21132172Sedward 	/* read the .afm file to get the widths */
21232172Sedward 	for (ccode = 0; ccode < FSIZEMAX; ccode++) f->Xwid[ccode] = NOTDEF;
21332172Sedward 
21432172Sedward 	inChars = 0;
21532172Sedward 	while(fgets(afmbuf, sizeof afmbuf, FontData) != NULL) {
21632172Sedward 	    /* strip off newline */
21732172Sedward 	    if ((c = index(afmbuf, '\n')) == 0) {
21832172Sedward 		fprintf(stderr, "AFM file %s line too long %s\n", FontFile, afmbuf);
21932172Sedward 		exit(1);
22032172Sedward 	    }
22132172Sedward 	    *c = '\0';
22232172Sedward 	    if (*afmbuf == '\0') continue;
22332172Sedward 	    if (strcmp(afmbuf, "StartCharMetrics") == 0) {
22432172Sedward 		inChars++;
22532172Sedward 		continue;
22632172Sedward 	    }
22732172Sedward 	    if (strcmp(afmbuf, "EndCharMetrics") == 0) break;
22832172Sedward 	    if (inChars == 1) {
22932172Sedward 		if (sscanf(afmbuf, "C %d ; WX %d ;",&ccode,&cwidth) != 2) {
23032172Sedward 		    fprintf(stderr,"Trouble with AFM file %s\n",FontFile);
23132172Sedward 		    exit(1);
23232172Sedward 		}
23332172Sedward 		/* get out once we see an unencoded char */
23432172Sedward 		if (ccode == -1) break;
23532172Sedward 		if (ccode > 255) continue;
23632172Sedward 		f->Xwid[ccode] = (cwidth * f->dsize * UperPt) / 1000;
23732172Sedward 		continue;
23832172Sedward 	    }
23932172Sedward 	}
24032172Sedward     fclose (FontData);
24132172Sedward     }
24232172Sedward 
24332172Sedward     TabWidth = fonts[BodyFont].Xwid['0'] * 8; /* 8 * figure width */
24432172Sedward     BSWidth = fonts[BodyFont].Xwid[' ']; /* space width */
24532172Sedward 
24632172Sedward     UperLine = (fonts[BodyFont].dsize + 1) * UperPt;
24732172Sedward 
24832172Sedward     if (LPTsimulate)
24932172Sedward 	UperHLine = UperLine;
25032172Sedward     else
25132172Sedward 	UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
25232172Sedward 
25332172Sedward     crX = 0;
25432172Sedward     crY = -UperLine;
25532172Sedward }
25632172Sedward 
25732172Sedward /* Return a font number for the font with the indicated name
25832172Sedward  * and size.  Adds info to the font list for the eventual search.
25932172Sedward  */
26032172Sedward private DefineFont (name, size)
26132172Sedward char   *name; {
26232172Sedward     register struct font   *p;
26332172Sedward     p = &fonts[nf];
26432172Sedward     strcpy (p->name, name);
26532172Sedward     p->dsize = size;
26632172Sedward     return (nf++);
26732172Sedward }
26832172Sedward 
26932172Sedward /* add a shown character to the PS file */
27032172Sedward private OUTputc (c)
27132172Sedward unsigned char    c; {
27232172Sedward     if (showpending == 0) {putc('(', OutFile); showpending++;}
27332172Sedward     if (c == '\\' || c=='(' || c == ')') putc('\\', OutFile);
27432172Sedward     if ((c > 0176) || (c < 040)) {
27532172Sedward 	putc('\\',OutFile);
27632172Sedward 	putc((c >> 6) +'0',OutFile);
27732172Sedward 	putc(((c >> 3) & 07)+'0', OutFile);
27832172Sedward 	putc((c & 07)+'0',OutFile);
27932172Sedward     }
28032172Sedward     else putc (c, OutFile);
28132172Sedward }
28232172Sedward 
28332172Sedward /* Set the current font */
28432172Sedward private SetFont (f) {
28532172Sedward     FlushShow();
28632172Sedward     LastFont = CurFont;
28732172Sedward     fprintf(OutFile, "%d F\n", CurFont = f);
28832172Sedward }
28932172Sedward 
29032172Sedward /* Reset to previous font */
29132172Sedward private PrevFont () {
29232172Sedward     int	temp;
29332172Sedward 
29432172Sedward     FlushShow();
29532172Sedward     temp = CurFont;
29632172Sedward     CurFont = LastFont;
29732172Sedward     LastFont = temp;
29832172Sedward     fprintf(OutFile, "%d F\n", CurFont);
29932172Sedward }
30032172Sedward 
30132172Sedward /* put a character onto the page at the desired X and Y positions.
30232172Sedward  * If the current position doesn't agree with the desired position, put out
30332172Sedward  * movement directives.  Leave the current position updated
30432172Sedward  * to account for the character.
30532172Sedward  */
30632172Sedward private ShowChar (c)
30732172Sedward register int c; {
30832172Sedward     register struct font   *f;
30932172Sedward     register    nX, nY;
31032172Sedward     static level = 0;
31132172Sedward 
31232172Sedward     level++;
31332172Sedward     f = &fonts[CurFont];
31432172Sedward 
31532172Sedward     if (f->Xwid[c] == NOTDEF) {
31632172Sedward 	UndefChars++;
31732172Sedward 	if(ListOmitted)
31832172Sedward 	    printf("\'%c\' (%03o) not found in font %s\n",c,c,f->name);
31932172Sedward 	if(level<=1){
32032172Sedward 	    ShowChar('\\');
32132172Sedward 	    ShowChar((c>>6)+'0');
32232172Sedward 	    ShowChar(((c>>3)&07)+'0');
32332172Sedward 	    ShowChar((c&07)+'0');
32432172Sedward 	}
32532172Sedward 	level--;
32632172Sedward 	return;
32732172Sedward     }
32832172Sedward     nX = dX + f->Xwid[c]; /* resulting position after showing this char */
32932172Sedward     nY = dY;
33032172Sedward 
33132172Sedward     if (c != ' ' || ((cX == dX) && (cY == dY)))
33232172Sedward 	if ((!Rotated && (nX <= PageWidth) && (nY <= PageLength))
33332172Sedward 	|| (Rotated && (nX <= PageLength) && (nY <= PageWidth))) {
33432172Sedward 	    if (cX != dX) {
33532172Sedward 	       if (cY != dY) {
33632172Sedward 		  FlushShow();
33732172Sedward 		  /* absolute x, relative y */
33832172Sedward 		  fprintf(OutFile,"%d %d",dX, dY);
33932172Sedward 		  movepending = AbsXY;
34032172Sedward 		  }
34132172Sedward 	       else {
34232172Sedward 		  FlushShow();
34332172Sedward 		  fprintf(OutFile,"%d",dX-cX); /* relative x */
34432172Sedward 		  movepending = RelX;
34532172Sedward 		  }
34632172Sedward 	    }
34732172Sedward 	    else if (cY != dY) {
34832172Sedward 		FlushShow();
34932172Sedward 		fprintf(OutFile,"%d",dY-cY); /* relative y */
35032172Sedward 		movepending = RelY;
35132172Sedward 		}
35232172Sedward 	    OUTputc (c);
35332172Sedward 	    showpending++;
35432172Sedward 	    cX = nX;
35532172Sedward 	    cY = nY;
35632172Sedward 	}
35732172Sedward 	else
35832172Sedward 	    TruncChars++;
35932172Sedward     dX = nX;
36032172Sedward     dY = nY;
36132172Sedward 
36232172Sedward     level--;
36332172Sedward }
36432172Sedward 
36532172Sedward /* put out a shown string to the PS file */
36632172Sedward private ShowStr (s)
36732172Sedward register char  *s; {
36832172Sedward     while (*s) {
36932172Sedward 	if (*s >= 040) ShowChar (*s);
37032172Sedward 	s++;
37132172Sedward     }
37232172Sedward }
37332172Sedward 
37432172Sedward /* flush pending show */
37532172Sedward private FlushShow() {
37632172Sedward     if (showpending) {
37732172Sedward        putc(')',OutFile);
37832172Sedward 	switch (movepending) {
37932172Sedward 	    case RelX:
38032172Sedward 		putc('X',OutFile);
38132172Sedward 		break;
38232172Sedward 	    case RelY:
38332172Sedward 	    	putc('Y',OutFile);
38432172Sedward 		break;
38532172Sedward 	    case AbsXY:
38632172Sedward 	    	putc('B',OutFile);
38732172Sedward 		break;
38832172Sedward 	    case None:
38932172Sedward 	    	putc('S',OutFile);
39032172Sedward 	    	break;
39132172Sedward 	}
39232172Sedward 	putc('\n',OutFile);
39332172Sedward 	movepending = None;
39432172Sedward 	showpending = 0;
39532172Sedward     }
39632172Sedward }
39732172Sedward 
39832172Sedward /* put out a page heading to the PS file */
39932172Sedward private InitPage () {
40032172Sedward     char    *basename();
40132172Sedward     char    header[200];
40232172Sedward     register int  OldFont = CurFont;
40332172Sedward 
40432172Sedward     TotalPages++;
40532172Sedward     fprintf(OutFile, "%%%%Page: ? %d\n", TotalPages);
40632172Sedward     fprintf(OutFile, "StartPage\n");
40732172Sedward     LinesLeft = 64;
40832172Sedward     SeenText = 0;
40932172Sedward     cX = cY = -1;
41032172Sedward     showpending = 0;
41132172Sedward     FirstCol = 1;
41232172Sedward     lX = dX = UperInch;
41332172Sedward     lY = dY = PageLength - UperHLine * 3 / 2;
41432172Sedward     if (Rotated) {
41532172Sedward         fprintf(OutFile, "Landscape\n");
41632172Sedward 	lX = dX = UperInch / 4;
41732172Sedward     }
41832172Sedward     movepending = None;
41932172Sedward     cX = dX; cY = dY;
42032172Sedward     if (!NoTitle) {
42132172Sedward 	SetFont (HeaderFont);
42232172Sedward         fprintf(OutFile, "%d %d ", cX, cY);
42332172Sedward         movepending = AbsXY;
42432172Sedward 	if (UsersHeader) {
42532172Sedward 	    if (*UsersHeader == 0) {
42632172Sedward 		fprintf(OutFile,"()B\n");
42732172Sedward 		movepending = None;
42832172Sedward 		showpending = 0;
42932172Sedward 	    }
43032172Sedward 	    else ShowStr (UsersHeader);
43132172Sedward 	}
43232172Sedward 	else {
43332172Sedward 	    Page++;
43432172Sedward 	    if (FileName == 0)
43532172Sedward 		    sprintf(header, "Page %d", Page);
43632172Sedward 	    else
43732172Sedward 	    sprintf (header, "%s,  page %d", basename(FileName), Page);
43832172Sedward 	    ShowStr (header);
43932172Sedward 	}
44032172Sedward 	FlushShow();
44132172Sedward 	dX = lX = lX + crX * 3;
44232172Sedward 	dY = lY = lY + crY * 3;
44332172Sedward     }
44432172Sedward     else {
44532172Sedward 	/* fake it to force a moveto */
44632172Sedward 	cX = cY = 0;
44732172Sedward     }
44832172Sedward     SetFont (OldFont);
44932172Sedward }
45032172Sedward 
45132172Sedward /* terminate a page. */
45232172Sedward private ClosePage () {
45332172Sedward     FlushShow();
45432172Sedward     fprintf(OutFile,"EndPage\n");
45532172Sedward }
45632172Sedward 
45732172Sedward /* skip to a new page */
45832172Sedward private PageEject () {
45932172Sedward     if (TwoColumn && FirstCol) {
46032172Sedward 	FirstCol = 0;
46132172Sedward 	lX = dX = TruePageWidth / 2;
46232172Sedward 	lY = dY = PageLength - (UperHLine * 3 / 2);
46332172Sedward 	if (Rotated) {
46432172Sedward 	   lX = dX = TruePageLength / 2;
46532172Sedward 	   }
46632172Sedward 	if (!NoTitle) {
46732172Sedward 	    dX = lX = lX + crX * 3;
46832172Sedward 	    dY = lY = lY + crY * 3;
46932172Sedward 	}
47032172Sedward     }
47132172Sedward     else {
47232172Sedward 	ClosePage ();
47332172Sedward 	InitPage ();
47432172Sedward     }
47532172Sedward     LinesLeft = 64;
47632172Sedward     SeenText = 0;
47732172Sedward }
47832172Sedward 
47932172Sedward #if 0
48032172Sedward /* commented out AIS Fri Feb 22 10:00:36 1985 */
48132172Sedward private PageMessage (TotalPages)
48232172Sedward {
48332172Sedward     if (TotalPages > 0) {
48432172Sedward 	printf ("psgrind formatted[ %d page%s * %d cop%s ]\n",
48532172Sedward 		TotalPages, TotalPages > 1 ? "s" : "",
48632172Sedward 		spoolCopies, spoolCopies > 1 ? "ies" : "y" );
48732172Sedward     }
48832172Sedward }
48932172Sedward #endif
49032172Sedward 
49132172Sedward private CommentHeader() {
49232172Sedward     long clock;
49332172Sedward     struct passwd *pswd;
49432172Sedward     char hostname[40];
49532172Sedward     /* copy the file, prepending a new comment header */
49632172Sedward     fprintf(OutFile,"%%!%s\n",COMMENTVERSION);
49732172Sedward     fprintf(OutFile,"%%%%Creator: ");
49832172Sedward     pswd = getpwuid(getuid());
49932172Sedward     gethostname(hostname, (int) sizeof hostname);
50032172Sedward     fprintf(OutFile,"%s:%s (%s)%s\n", hostname, pswd->pw_name,
50132172Sedward     	pswd->pw_gecos, spoolJobClass);
50232172Sedward 
50332172Sedward     fprintf(OutFile,"%%%%Title: %s %s\n",
50432172Sedward     	(FileName?FileName:"stdin"),
50532172Sedward 	spoolJobName);
50632172Sedward 
50732172Sedward     fprintf(OutFile,"%%%%CreationDate: %s",(time(&clock),ctime(&clock)));
50832172Sedward }
50932172Sedward 
51032172Sedward 
51132172Sedward /* list of C keywords to put in KwordFont */
51232172Sedward private char *KeyWordList[] = {
513*32180Sedward     "asm", "auto", "break", "case", "char", "continue", "default", "do",
514*32180Sedward     "double", "else", "entry", "enum", "extern", "float", "for", "fortran",
515*32180Sedward     "goto", "if", "int", "long", "register", "return", "short", "sizeof",
516*32180Sedward     "static", "struct", "switch", "typedef", "union", "unsigned", "void",
517*32180Sedward     "while", NULL
51832172Sedward };
51932172Sedward 
52032172Sedward /* macros identifying C identifiers */
52132172Sedward #define isfirst(c)	(isalpha(c) || (c) == '_')
52232172Sedward #define isident(c)	(isalnum(c) || (c) == '_')
52332172Sedward 
52432172Sedward /* Copy the standard input file to the PS file */
52532172Sedward private CopyFile () {
52632172Sedward     register int   c, last;
52732172Sedward     register int    col = 1;
52832172Sedward     int	InComment, InString, InChar, IsKword;
52932172Sedward     char token[50], *tend = token + sizeof (token) - 1;
53032172Sedward     register char *tp, **kwp;
53132172Sedward 
53232172Sedward     if (OutFile == 0) {
53332172Sedward 	if (OutOnly && !(PageSpec || Reverse)) {
53432172Sedward 	   OutFile = PipeOut ? stdout : fopen(OutName,"w");
53532172Sedward 	}
53632172Sedward 	else {
53732172Sedward 	    mktemp(mstrcat(TempName,TempDir,PSGRINDTEMP,sizeof TempName));
53832172Sedward 	    OutFile = fopen (TempName, "w");
53932172Sedward 	}
54032172Sedward     }
54132172Sedward     if (OutFile == NULL) {
54232172Sedward 	fprintf(stderr, "Can't create PS file %s\n",TempName);
54332172Sedward 	exit(1);
54432172Sedward     }
54532172Sedward     if (!ScannedFonts) {
54632172Sedward 	ScannedFonts++;
54732172Sedward 	ScanFont();
54832172Sedward     }
54932172Sedward     if (!Cvted) {
55032172Sedward 	CommentHeader();
55132172Sedward 	if (nf) {
55232172Sedward 	    register struct font *f;
55332172Sedward 	    fprintf(OutFile,"%%%%DocumentFonts:");
55432172Sedward  	    ForAllFonts(f) {
55532172Sedward 		fprintf(OutFile," %s",f->name);
55632172Sedward 	    }
55732172Sedward 	    fprintf(OutFile,"\n");
55832172Sedward 	}
55932172Sedward 	/* copy in fixed prolog */
56032172Sedward 	if (copyfile(mstrcat(tempstr,LibDir,PSGRINDPRO,sizeof tempstr),
56132172Sedward 		OutFile)) {
56232172Sedward 	    fprintf(stderr,"trouble copying prolog file \"%s\".\n",tempstr);
56332172Sedward 	    exit(1);
56432172Sedward 	}
56532172Sedward 	fprintf(OutFile,"StartEnscriptDoc %% end fixed prolog\n");
56632172Sedward 	DumpFonts();
56732172Sedward 	fprintf(OutFile,"%%%%EndProlog\n");
56832172Sedward 	if (PreFeed) {
56932172Sedward 	    fprintf(OutFile,"true DoPreFeed\n");
57032172Sedward 	}
57132172Sedward     }
57232172Sedward     Cvted++;
57332172Sedward 
57432172Sedward     Page = 0;
57532172Sedward     LineNo = 1;
57632172Sedward     BadChars = 0;		/* give each file a clean slate */
57732172Sedward     InitPage ();
57832172Sedward     last = '\0';
57932172Sedward     InComment = InChar = InString = 0;
58032172Sedward     while ((c = getchar ()) != EOF) {
58132172Sedward 	if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
58232172Sedward 	    if (BadChars++ > MAXBAD) {/* allow some kruft but not much */
58332172Sedward 	      fprintf(stderr,"\"%s\" not a text file? - char '\\%03o'@0%o\nTry -g.\n",
58432172Sedward 		    FileName ? FileName : "stdin", c, ftell (stdin) - 1);
58532172Sedward 	      exit(1);
58632172Sedward 	    }
58732172Sedward 	} else {
58832172Sedward 	    switch (c) {
58932172Sedward 		case 010: /* backspace */
59032172Sedward 		    dX -= BSWidth;
59132172Sedward 		    break;
59232172Sedward 		case 015: /* carriage return ^M */
59332172Sedward 		    dY = lY;
59432172Sedward 		    dX = lX;
59532172Sedward 		    break;
59632172Sedward 		case 012: /* linefeed ^J */
59732172Sedward 		    LineNo++;
59832172Sedward 		    if (dX != lX || dY != lY || !LPTsimulate || SeenText){
59932172Sedward 			SeenText++;
60032172Sedward 			dY = lY = lY + crY;
60132172Sedward 			dX = lX = lX + crX;
60232172Sedward 		    }
60332172Sedward 		    else
60432172Sedward 			LinesLeft = 64;
60532172Sedward 		    if (((!Rotated) && (dY < UperLine))
60632172Sedward 		    || (Rotated && (dY < ((PageLength-TruePageWidth) +
60732172Sedward 						3*UperLine+480)))
60832172Sedward 		    || (LPTsimulate && (--LinesLeft <= 0)))
60932172Sedward 			PageEject ();
61032172Sedward 		    col = 1;
61132172Sedward 		    break;
61232172Sedward 		case 014: /* form feed ^L */
61332172Sedward 		    PageEject ();
61432172Sedward 		    col = 1;
61532172Sedward 		    break;
61632172Sedward 		case 011: /* tab ^I */
61732172Sedward 		    col = (col - 1) / 8 * 8 + 9;
61832172Sedward 		    dX = lX + (col - 1) / 8 * TabWidth;
61932172Sedward 		    break;
62032172Sedward 	        case '\\': /* special escape */
62132172Sedward 		    last = c;
62232172Sedward 		    if ((c = getchar()) == EOF)
62332172Sedward 			goto done;
62432172Sedward 		    ShowChar('\\');
62532172Sedward 		    col++;
62632172Sedward 		    if (c == '\n') {
62732172Sedward 			/* want to leave newlines alone */
62832172Sedward 			ungetc(c, stdin);
62932172Sedward 		    } else {
63032172Sedward 			ShowChar(c);
63132172Sedward 			col++;
63232172Sedward 		    }
63332172Sedward 		    break;
63432172Sedward 	        case '"': /* a string quote mark */
63532172Sedward 		    if (InComment || InChar) {
63632172Sedward 			/* just put out the quote */
63732172Sedward 			ShowChar('"');
63832172Sedward 			col++;
63932172Sedward 		    } else if (InString) {
64032172Sedward 			ShowChar('"');
64132172Sedward 			col++;
64232172Sedward 			PrevFont();
64332172Sedward 			InString = 0;
64432172Sedward 		    } else {
64532172Sedward 			SetFont(LiteralFont);
64632172Sedward 			ShowChar('"');
64732172Sedward 			col++;
64832172Sedward 			InString = 1;
64932172Sedward 		    }
65032172Sedward 		    break;
65132172Sedward 	        case '\'': /* a char quote mark */
65232172Sedward 		    if (InComment || InString) {
65332172Sedward 			/* just put out the character */
65432172Sedward 			ShowChar('\'');
65532172Sedward 			col++;
65632172Sedward 		    } else if (InChar) {
65732172Sedward 			ShowChar('\'');
65832172Sedward 			col++;
65932172Sedward 			PrevFont();
66032172Sedward 			InChar = 0;
66132172Sedward 		    } else {
66232172Sedward 			SetFont(LiteralFont);
66332172Sedward 			ShowChar('\'');
66432172Sedward 			col++;
66532172Sedward 			InChar = 1;
66632172Sedward 		    }
66732172Sedward 		    break;
66832172Sedward 	        case '/':
66932172Sedward 		    if (InComment && last == '*') {
67032172Sedward 			ShowChar('/');
67132172Sedward 			col++;
67232172Sedward 			SetFont(BodyFont);
67332172Sedward 			InComment = 0;
67432172Sedward 		    } else if ((c = getchar()) == '*' && !InComment) {
67532172Sedward 			SetFont(CommentFont);
67632172Sedward 			InComment = 1;
67732172Sedward 			ShowChar('/');
67832172Sedward 			ShowChar('*');
67932172Sedward 			col += 2;
68032172Sedward 		    } else {
68132172Sedward 			ungetc(c, stdin);
68232172Sedward 			ShowChar('/');
68332172Sedward 			col++;
68432172Sedward 			c = '/';
68532172Sedward 		    }
68632172Sedward 		    break;
68732172Sedward 		default: /* plain text, put it out */
68832172Sedward 		    if (!InComment && !InString && isfirst(c)) {
68932172Sedward 			tp = token;
69032172Sedward 			while (isident(c) && tp < tend) {
69132172Sedward 			    *tp++ = c;
69232172Sedward 			    last = c;
69332172Sedward 			    c = getchar();
69432172Sedward 			}
69532172Sedward 			*tp = '\0';
69632172Sedward 			ungetc(c, stdin);
69732172Sedward 			tp = token;
69832172Sedward 			IsKword = 0;
699*32180Sedward 			for (kwp = KeyWordList;
700*32180Sedward 			     *kwp != NULL && **kwp <= *tp; kwp++)
70132172Sedward 				if (!strcmp(*kwp, tp)) {
70232172Sedward 					IsKword = 1;
70332172Sedward 					break;
70432172Sedward 				}
70532172Sedward 			if (IsKword)
70632172Sedward 			    SetFont(KwordFont);
70732172Sedward 			ShowStr(tp);
70832172Sedward 			col += strlen(tp);
70932172Sedward 			if (IsKword)
71032172Sedward 			    SetFont(BodyFont);
71132172Sedward 		    } else if (fonts[CurFont].Xwid[c] != NOTDEF) {
71232172Sedward 			/* other normal character */
71332172Sedward 			ShowChar (c);
71432172Sedward 			col++;
71532172Sedward 		    } else { /* not in font, quote it */
71632172Sedward 			ShowChar ('\\');
71732172Sedward 			ShowChar ((c >> 6) + '0');
71832172Sedward 			ShowChar (((c >> 3) & 7) + '0');
71932172Sedward 			ShowChar ((c & 7) + '0');
72032172Sedward 			col += 4;
72132172Sedward 		    }
72232172Sedward 		    break;
72332172Sedward 	     }
72432172Sedward 	}
72532172Sedward 	last = c;
72632172Sedward     }
72732172Sedward 
72832172Sedward done:
72932172Sedward     ClosePage ();
73032172Sedward }
73132172Sedward 
73232172Sedward /* dump the fonts to the PS file for setup */
73332172Sedward private DumpFonts () {
73432172Sedward     register struct font   *f;
73532172Sedward 
73632172Sedward     ForAllFonts (f) {
73732172Sedward         fprintf(OutFile,"%d %d /%s\n",f-&fonts[0],f->dsize*UperPt,f->name);
73832172Sedward     }
73932172Sedward     fprintf(OutFile, "%d SetUpFonts\n", nf);
74032172Sedward }
74132172Sedward 
74232172Sedward 
74332172Sedward /*
74432172Sedward  * close the PS file
74532172Sedward  */
74632172Sedward private ClosePS () {
74732172Sedward     fprintf(OutFile,"%%%%Trailer\n");
74832172Sedward     if (PreFeed) {
74932172Sedward 	fprintf(OutFile,"false DoPreFeed\n");
75032172Sedward     }
75132172Sedward     fprintf(OutFile,"EndEnscriptDoc\nEnscriptJob restore\n");
75232172Sedward }
75332172Sedward 
75432172Sedward private ProcessArg (p)
75532172Sedward register char  *p; {
75632172Sedward     static  enum State {
75732172Sedward 	normal, PSname,
75832172Sedward 	H_fontname, B_fontname, K_fontname, C_fontname, L_fontname,
75932172Sedward 	grabheader, getclass, getjobname
76032172Sedward     } state = normal;
76132172Sedward 
76232172Sedward     switch (state) {
76332172Sedward 	case PSname:
76432172Sedward 	    strcpy (OutName, p);
76532172Sedward 	    if (strcmp(OutName,"-") == 0) PipeOut++;
76632172Sedward 	    state = normal;
76732172Sedward 	    break;
76832172Sedward 	case H_fontname:
76932172Sedward 	    decodefont (p, &fonts[HeaderFont]);
77032172Sedward 	    state = normal;
77132172Sedward 	    break;
77232172Sedward 	case B_fontname:
77332172Sedward 	    decodefont (p, &fonts[BodyFont]);
77432172Sedward 	    state = normal;
77532172Sedward 	    break;
77632172Sedward 	case K_fontname:
77732172Sedward 	    decodefont (p, &fonts[KwordFont]);
77832172Sedward 	    state = normal;
77932172Sedward 	    break;
78032172Sedward 	case L_fontname:
78132172Sedward 	    decodefont (p, &fonts[LiteralFont]);
78232172Sedward 	    state = normal;
78332172Sedward 	    break;
78432172Sedward 	case C_fontname:
78532172Sedward 	    decodefont (p, &fonts[CommentFont]);
78632172Sedward 	    state = normal;
78732172Sedward 	    break;
78832172Sedward 	case grabheader:
78932172Sedward 	    UsersHeader = p;
79032172Sedward 	    state = normal;
79132172Sedward 	    break;
79232172Sedward 	case getclass:
79332172Sedward 	    spoolJobClass = p;
79432172Sedward 	    state = normal;
79532172Sedward 	    break;
79632172Sedward 	case getjobname:
79732172Sedward 	    spoolJobName = p;
79832172Sedward 	    state = normal;
79932172Sedward 	    break;
80032172Sedward 	default:
80132172Sedward 	    if (*p == '-') while (*++p) switch (*p) {
80232172Sedward 		case '1':
80332172Sedward 		    TwoColumn = 0;
80432172Sedward 		    if (SeenFile) {
80532172Sedward 			fprintf(stderr,"Specify -1 before any files\n");
80632172Sedward 			exit(1);
80732172Sedward 		    }
80832172Sedward 		    break;
80932172Sedward 		case '2':
81032172Sedward 		    TwoColumn++;
81132172Sedward 		    if (SeenFile){
81232172Sedward 			fprintf(stderr,"Specify -2 before any files\n");
81332172Sedward 			exit(1);
81432172Sedward 		    }
81532172Sedward 		    break;
81632172Sedward 		case 'v':
81732172Sedward 		    Reverse = 1;
81832172Sedward 		    break;
81932172Sedward 		case 's':
82032172Sedward 		     PageSpec = (++p);
82132172Sedward 		     while (*p != '\0') p++;
82232172Sedward 		     return;
82332172Sedward 
82432172Sedward 		/* the following options allow uswer specification
82532172Sedward 		   of the five files used by the program */
82632172Sedward 		case 'H': state = H_fontname; break;
82732172Sedward 		case 'B': state = B_fontname; break;
82832172Sedward 		case 'K': state = K_fontname; break;
82932172Sedward 		case 'L': state = L_fontname; break;
83032172Sedward 		case 'C': state = C_fontname; break;
83132172Sedward 
83232172Sedward 		case 'g': IgnoreGarbage++; break;
83332172Sedward 		case 'o': ListOmitted++; break;
83432172Sedward 		case 'p': OutOnly++; state = PSname; break;
83532172Sedward 		case 'r':
83632172Sedward 		    Rotated++;
83732172Sedward 		    if (SeenFile){
83832172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
83932172Sedward 			exit(1);
84032172Sedward 		    }
84132172Sedward 		    break;
84232172Sedward 		case 'R':
84332172Sedward 		    Rotated = 0;
84432172Sedward 		    if (SeenFile){
84532172Sedward 			fprintf(stderr,"Specify rotation before any files\n");
84632172Sedward 			exit(1);
84732172Sedward 		    }
84832172Sedward 		    break;
84932172Sedward 		case 'k':
85032172Sedward 		    PreFeed++;
85132172Sedward 		    if (SeenFile){
85232172Sedward 			fprintf(stderr,"Specify prefeed before any files\n");
85332172Sedward 			exit(1);
85432172Sedward 		    }
85532172Sedward 		    break;
85632172Sedward 
85732172Sedward 		/* the following switches are as in lpr(1) and */
85832172Sedward 		/* are passed through when spooling to a printer */
85932172Sedward 		case 'P': /* printer name */
86032172Sedward 		    PrinterName = (++p);
86132172Sedward 		    while (*p != '\0') p++;
86232172Sedward 		    return;
86332172Sedward 		case 'J': /* job name (title) for the Job: field */
86432172Sedward 		    state = getjobname;
86532172Sedward 		    break;
86632172Sedward 		case 'm': /* notify by mail */
86732172Sedward 		    spoolNotify = 1;
86832172Sedward 		    break;
86932172Sedward 		case 'h':
87032172Sedward 		    spoolNoBurst = 1;
87132172Sedward 		    break;
87232172Sedward 		case '#':
87332172Sedward 		    spoolCopies = atoi(++p);
87432172Sedward 		    if (spoolCopies < 1){
87532172Sedward 		        fprintf(stderr,"Bad argument for -# (number of copies)\n");
87632172Sedward 			exit(1);
87732172Sedward 		    }
87832172Sedward 		    break;
87932172Sedward 
88032172Sedward 		default:
88132172Sedward 		    printf ("Unknown option: %c\n", *p);
88232172Sedward 		    SeenFile++;
88332172Sedward 		    break;
88432172Sedward 		}
88532172Sedward 	    else {/* not a flag -- a filename */
88632172Sedward 		FileName = Header = p;
88732172Sedward 		if (freopen (FileName, "r", stdin) == NULL) {
88832172Sedward 		    printf ("Can't open %s\n", FileName);
88932172Sedward 		    exit (1);
89032172Sedward 		}
89132172Sedward 		fstat (fileno (stdin), &S);
89232172Sedward 		FileDate = strcpy(DateStr,ctime (&S.st_mtime));
89332172Sedward 		CopyFile ();
89432172Sedward 		fclose (stdin);
89532172Sedward 		SeenFile = 1;
89632172Sedward 	    }
89732172Sedward     }
89832172Sedward }
89932172Sedward 
90032172Sedward main (argc, argv)
90132172Sedward char  **argv; {
90232172Sedward     register char  *p, *arg;
90332172Sedward 
90432172Sedward     prog = *argv;
90532172Sedward 
90632172Sedward     BodyFont = LastFont = CurFont = DefineFont (BODYFONT, 10);
90732172Sedward     HeaderFont = DefineFont (HEADERFONT, 12);
90832172Sedward     KwordFont = DefineFont (KWORDFONT, 10);
90932172Sedward     CommentFont = DefineFont (COMMENTFONT, 10);
91032172Sedward     LiteralFont = DefineFont (LITERALFONT, 11);
91132172Sedward 
91232172Sedward     /* process args in environment variable PSGRIND */
91332172Sedward     if (p = getenv ("PSGRIND"))
91432172Sedward 	while (1) {
91532172Sedward 	    register char   quote = ' ';
91632172Sedward 	    while (*p == ' ')
91732172Sedward 		p++;
91832172Sedward 	    if (*p == '"' || *p == '\'')
91932172Sedward 		quote = *p++;
92032172Sedward 	    arg = p;
92132172Sedward 	    while (*p != quote && *p != '\0')
92232172Sedward 		p++;
92332172Sedward 	    if (*p == '\0') {
92432172Sedward 		if (*arg)
92532172Sedward 		    ProcessArg (arg);
92632172Sedward 		break;
92732172Sedward 	    }
92832172Sedward 	    *p++ = '\0';
92932172Sedward 	    ProcessArg (arg);
93032172Sedward 	}
93132172Sedward 
93232172Sedward     /* process the command line arguments */
93332172Sedward     while (argc > 1) {
93432172Sedward 	argc--;
93532172Sedward 	ProcessArg (*++argv);
93632172Sedward     }
93732172Sedward 
93832172Sedward     if (!SeenFile) {
93932172Sedward 	FileName = Header = 0;
94032172Sedward 	FileDate = "";
94132172Sedward 	fstat (fileno (stdin), &S);
94232172Sedward 
94332172Sedward 	if ((S.st_mode & S_IFMT) == S_IFREG)
94432172Sedward 	    FileDate = strcpy(DateStr, ctime (&S.st_mtime));
94532172Sedward 	CopyFile ();
94632172Sedward     }
94732172Sedward 
94832172Sedward     if (Cvted) {
94932172Sedward 	ClosePS ();
95032172Sedward 	fclose (OutFile);
95132172Sedward 	OutFile = 0;
95232172Sedward     }
95332172Sedward     if (TruncChars)
95432172Sedward 	printf ("%d characters omitted because of long lines.\n",
95532172Sedward 		TruncChars);
95632172Sedward     if (UndefChars)
95732172Sedward 	printf ("%d characters omitted because of incomplete fonts.\n",
95832172Sedward 		UndefChars);
95932172Sedward /*  PageMessage (TotalPages); */
96032172Sedward     if (Cvted) {
96132172Sedward 	if (OutOnly) {
96232172Sedward 	    if (Reverse || PageSpec) {
96332172Sedward 		char temparg[200];
96432172Sedward 		char *sargs[200];
96532172Sedward 		int args = 0;
96632172Sedward 
96732172Sedward 		int cpid = 0;
96832172Sedward 		/* feed Temporary through psrev */
96932172Sedward 		freopen(TempName, "r", stdin);
97032172Sedward 		if (!PipeOut) freopen(OutName, "w", stdout);
97132172Sedward 		unlink(TempName);
97232172Sedward 
97332172Sedward 		addarg(sargs, REVERSE, &args);
97432172Sedward 		addarg(sargs, "-r", &args);
97532172Sedward 		if (!Reverse) addarg(sargs, "-R", &args);
97632172Sedward 
97732172Sedward 		if (PageSpec) {
97832172Sedward 		    sprintf(temparg,"-s%s",PageSpec);
97932172Sedward 		    addarg(sargs, temparg, &args);
98032172Sedward 		}
98132172Sedward 		if ((cpid = fork()) < 0) pexit(prog,1);
98232172Sedward 		if (cpid == 0) {
98332172Sedward 		    execvp(REVERSE, sargs);
98432172Sedward 		    pexit(prog,1);
98532172Sedward 		}
98632172Sedward 		else {
98732172Sedward 		    wait(0);
98832172Sedward 		}
98932172Sedward 	    }
99032172Sedward 	  /*  fprintf (stderr,"PS file left on %s\n", OutName); */
99132172Sedward 	}
99232172Sedward 	else
99332172Sedward 	    SpoolIt();
99432172Sedward     }
99532172Sedward }
99632172Sedward 
99732172Sedward private addarg(argv, argstr, argc)
99832172Sedward char **argv;
99932172Sedward char *argstr;
100032172Sedward register int *argc;
100132172Sedward {
100232172Sedward     register char *p = (char *) malloc (strlen(argstr) + 1);
100332172Sedward     strcpy (p, argstr);
100432172Sedward     argv[(*argc)++] = p;
100532172Sedward     argv[*argc] = '\0';
100632172Sedward }
100732172Sedward 
100832172Sedward private SpoolIt()
100932172Sedward {
101032172Sedward     char temparg[200];
101132172Sedward     char *argstr[200];
101232172Sedward     int nargs = 0;
101332172Sedward 
101432172Sedward     char *rargs[40];
101532172Sedward     int  nr = 0;
101632172Sedward     int cpid =0;
101732172Sedward     int fdpipe[2];
101832172Sedward 
101932172Sedward     addarg(argstr, LPR, &nargs);
102032172Sedward     if (spoolCopies > 1) {
102132172Sedward 	sprintf(temparg,"-#%d",spoolCopies);
102232172Sedward 	addarg(argstr, temparg, &nargs);
102332172Sedward     }
102432172Sedward     if (PrinterName) {
102532172Sedward 	sprintf(temparg,"-P%s",PrinterName);
102632172Sedward 	addarg(argstr, temparg, &nargs);
102732172Sedward     }
102832172Sedward     else if (getenv("PRINTER") == 0) {
102932172Sedward 	/* no printer name known anywhere, use default */
103032172Sedward 	sprintf(temparg,"-P%s",POSTSCRIPTPRINTER);
103132172Sedward 	addarg(argstr, temparg, &nargs);
103232172Sedward     }
103332172Sedward     if (spoolJobClass) {
103432172Sedward 	addarg(argstr, "-C", &nargs);
103532172Sedward 	addarg(argstr, spoolJobClass, &nargs);
103632172Sedward     }
103732172Sedward     addarg(argstr, "-J", &nargs);
103832172Sedward     if (spoolJobName) {
103932172Sedward 	addarg(argstr, spoolJobName, &nargs);
104032172Sedward     }
104132172Sedward     else {
104232172Sedward 	if (!FileName) addarg(argstr, "stdin", &nargs);
104332172Sedward 	else addarg(argstr, FileName, &nargs);
104432172Sedward     }
104532172Sedward     if (spoolNotify) {
104632172Sedward 	addarg(argstr, "-m", &nargs);
104732172Sedward     }
104832172Sedward     if (spoolNoBurst) {
104932172Sedward 	addarg(argstr, "-h", &nargs);
105032172Sedward     }
105132172Sedward 
105232172Sedward     if (Reverse || PageSpec) {
105332172Sedward 	/* lpr input will be stdin */
105432172Sedward 
105532172Sedward 	addarg(rargs, REVERSE, &nr);
105632172Sedward 	addarg(rargs, "-r", &nr);
105732172Sedward 	if (!Reverse) addarg(rargs, "-R", &nr);
105832172Sedward 	if (PageSpec) {
105932172Sedward 	    sprintf(temparg,"-s%s",PageSpec);
106032172Sedward 	    addarg(rargs, temparg, &nr);
106132172Sedward         }
106232172Sedward /*	addarg(rargs, TempName, &nr); */
106332172Sedward 
106432172Sedward 	freopen(TempName,"r",stdin);
106532172Sedward 	unlink(TempName);
106632172Sedward 	if (pipe(fdpipe)) pexit(prog,1);
106732172Sedward 	if ((cpid = fork()) < 0) pexit(prog,1);
106832172Sedward 	else if (!cpid) { /* child */
106932172Sedward 	    if (close(1)) {
107032172Sedward 		pexit(prog,1);
107132172Sedward 	    }
107232172Sedward 	    /* set stdout to be the output pipe */
107332172Sedward 	    if (dup (fdpipe[1]) == -1) {
107432172Sedward 		pexit(prog,1);
107532172Sedward 	    }
107632172Sedward 	    /* don't want to read or write the pipe itself, since dup */
107732172Sedward 	    if (close (fdpipe[1]) || close (fdpipe[0])) {
107832172Sedward 		pexit(prog,1);
107932172Sedward 	    }
108032172Sedward 	    /* leave stderr alone */
108132172Sedward 	    execvp (REVERSE, rargs);
108232172Sedward 	    pexit(prog,1);
108332172Sedward 	}
108432172Sedward 	else {
108532172Sedward 	    /* parent */
108632172Sedward 	    /* replace stdin with pipe */
108732172Sedward 	    if (close(0)) {
108832172Sedward 		pexit(prog,1);
108932172Sedward 	    }
109032172Sedward 
109132172Sedward 	    if (dup(fdpipe[0]) == -1) {
109232172Sedward 		pexit(prog,1);
109332172Sedward 	    }
109432172Sedward 	    if (close (fdpipe[0]) || close (fdpipe[1])) {
109532172Sedward 		pexit(prog,1);
109632172Sedward 	    }
109732172Sedward 
109832172Sedward 	    /* leave stdout and stderr alone */
109932172Sedward 	    execvp(LPR, argstr);
110032172Sedward 	    pexit(prog,1);
110132172Sedward 	}
110232172Sedward     }
110332172Sedward     else { /* just do lpr */
110432172Sedward 	/* remove the temporary file after spooling */
110532172Sedward 	addarg(argstr, "-r", &nargs); /* should we use a symbolic link too? */
110632172Sedward 	addarg(argstr, TempName, &nargs);
110732172Sedward 	execvp(LPR, argstr);
110832172Sedward 	pexit(prog,1);
110932172Sedward     }
111032172Sedward }
111132172Sedward 
111232172Sedward char *
111332172Sedward basename(path)
111432172Sedward 	char	*path;
111532172Sedward {
111632172Sedward 	register char	*cp;
111732172Sedward 
111832172Sedward 	for (cp = path; *cp != '\0'; cp++)
111932172Sedward 		;
112032172Sedward 	for (--cp; cp > path && *cp != '/'; cp--)
112132172Sedward 		;
112232172Sedward 	if (*cp == '/' && *(cp+1) != '\0')
112332172Sedward 		return (cp + 1);
112432172Sedward 	else
112532172Sedward 		return (path);
112632172Sedward }
1127