1*32172Sedward /* @(#)psgrind.c 1.1 09/15/87 */ 2*32172Sedward /* 3*32172Sedward * psgrind - quick hack to grind C source files directly into 4*32172Sedward * PostScript. 5*32172Sedward * 6*32172Sedward * John Coker 7*32172Sedward * University of California, Berkeley 8*32172Sedward * 9*32172Sedward * The basis for this program is the enscript utility provided 10*32172Sedward * by TranScript to driver the Apple LaserWriter printer. This 11*32172Sedward * code was taken and mangled without permission of any kind; 12*32172Sedward * don't tell anyone. -john 13*32172Sedward */ 14*32172Sedward 15*32172Sedward #define POSTSCRIPTPRINTER "gp" 16*32172Sedward 17*32172Sedward #define HEADERFONT "Helvetica-Bold" 18*32172Sedward #define BODYFONT "Helvetica" 19*32172Sedward #define KWORDFONT "Helvetica-Bold" 20*32172Sedward #define COMMENTFONT "Helvetica-Oblique" 21*32172Sedward #define LITERALFONT "Courier" 22*32172Sedward 23*32172Sedward #ifndef PSGRINDPRO 24*32172Sedward #define PSGRINDPRO "/psgrind.pro" 25*32172Sedward #endif !PSGRINDPRO 26*32172Sedward 27*32172Sedward #ifndef PSGRINDTEMP 28*32172Sedward #define PSGRINDTEMP "/GRXXXXXX" 29*32172Sedward #endif !PSGRINDTEMP 30*32172Sedward 31*32172Sedward #define UperInch 1440 32*32172Sedward #define PtsPerInch 72 33*32172Sedward #define UperPt 20 34*32172Sedward #define TruePageWidth (UperInch*17/2) 35*32172Sedward #define PageWidth (UperInch*(8*17-3)/4) 36*32172Sedward #define PageLength (UperInch*(8*11-3)/8) 37*32172Sedward #define TruePageLength (UperInch*11) 38*32172Sedward 39*32172Sedward #include <stdio.h> 40*32172Sedward #include <ctype.h> 41*32172Sedward #include <strings.h> 42*32172Sedward #include <pwd.h> 43*32172Sedward #include <sys/types.h> 44*32172Sedward #include <sys/stat.h> 45*32172Sedward #include "transcript.h" 46*32172Sedward 47*32172Sedward #define LPR "lpr" 48*32172Sedward #define REVERSE "psrev" 49*32172Sedward 50*32172Sedward #define MAXBAD 20 /* number of bad chars to pass before complaint */ 51*32172Sedward 52*32172Sedward private struct stat S; 53*32172Sedward char *ctime (); 54*32172Sedward char *getenv (); 55*32172Sedward char *rindex (); 56*32172Sedward 57*32172Sedward #define FSIZEMAX 256 /* number of chars per font */ 58*32172Sedward 59*32172Sedward /* the layout of a font information block */ 60*32172Sedward struct font { 61*32172Sedward char name[100]; /* PostScript font name */ 62*32172Sedward int dsize; /* size */ 63*32172Sedward int Xwid[FSIZEMAX]; /* X widths for each character */ 64*32172Sedward }; 65*32172Sedward 66*32172Sedward private struct font fonts[16]; /* 16 possible fonts at one time */ 67*32172Sedward private int nf = 0; /* number of fonts known about */ 68*32172Sedward 69*32172Sedward private int HeaderFont = -1; /* handle for header font */ 70*32172Sedward private int BodyFont = -1; /* handle for body font */ 71*32172Sedward private int KwordFont = -1; /* handle for keyword font */ 72*32172Sedward private int LiteralFont = -1; /* handle for literal font */ 73*32172Sedward private int CommentFont = -1; /* handle for comment font */ 74*32172Sedward 75*32172Sedward private int TabWidth = TruePageWidth / 10; /* width of a tab */ 76*32172Sedward private int BSWidth; /* width of a backspace */ 77*32172Sedward 78*32172Sedward private int UperLine = UperInch / 7; 79*32172Sedward private int UperHLine = UperInch / 7; 80*32172Sedward 81*32172Sedward private char *prog; /* program name argv[0] */ 82*32172Sedward private char TempName[100]; /* name of temporary PostScript file */ 83*32172Sedward private char OutName[256] = 0; /* filename for disk output */ 84*32172Sedward private int PipeOut = 0; /* true if output to stdout (-p -) */ 85*32172Sedward private int ListOmitted = 0; /* list omitted chars on the tty */ 86*32172Sedward private int LPTsimulate = 0; /* true if an lpt should be simulated */ 87*32172Sedward private int LinesLeft = 64; /* lines left on page when in LPT mode */ 88*32172Sedward private int LineNo; /* line number in current file */ 89*32172Sedward private int SeenText = 1; /* true if seen some text on this page */ 90*32172Sedward private int OutOnly = 0; /* true if PS file only wanted */ 91*32172Sedward private int Rotated = 0; /* true if the page is to be rotated */ 92*32172Sedward private int Reverse = 0; /* output should be piped to psrev */ 93*32172Sedward private char *PageSpec = 0; /* ditto */ 94*32172Sedward private int PreFeed = 0; /* true if prefeed should be enabled */ 95*32172Sedward private int TwoColumn = 0; /* true of if in two-column mode */ 96*32172Sedward private int FirstCol = 1; /* true if we're printing column 1 */ 97*32172Sedward private int NoTitle = 0; /* true if title line is to be suppressed */ 98*32172Sedward private int Cvted = 0; /* true if converted a file to PS format */ 99*32172Sedward 100*32172Sedward private int IgnoreGarbage = 0; /* true if garbage should be ignored */ 101*32172Sedward private int SeenFile = 0; /* true if a file has been processed */ 102*32172Sedward private int SeenFont = 0; /* true if we've seen a font request */ 103*32172Sedward private int ScannedFonts = 0; /* true if we've scanned the font file */ 104*32172Sedward private char *FileName = 0; /* name of file currently being PSed */ 105*32172Sedward private char *FileDate = 0; /* last mod date of file being PSed */ 106*32172Sedward private char DateStr[27]; /* thanks, but no thanks ctime! */ 107*32172Sedward 108*32172Sedward private char *spoolJobClass = 0; 109*32172Sedward private char *spoolJobName = 0; 110*32172Sedward private char *PrinterName = 0; 111*32172Sedward private int spoolNotify = 0; 112*32172Sedward private int spoolNoBurst = 0; 113*32172Sedward private int spoolCopies = 1; 114*32172Sedward 115*32172Sedward private char tempstr[256]; /* various path names */ 116*32172Sedward 117*32172Sedward private int CurFont; /* current Font */ 118*32172Sedward private int LastFont; /* previous Font */ 119*32172Sedward 120*32172Sedward private int cX, cY; /* current page positions */ 121*32172Sedward private int dX, dY; /* desired page positions */ 122*32172Sedward private int lX, lY; /* page positions of the start of the line */ 123*32172Sedward private int crX, crY; /* X and Y increments to apply to CR's */ 124*32172Sedward 125*32172Sedward #define None 0 126*32172Sedward #define RelX 1 127*32172Sedward #define RelY 2 128*32172Sedward #define RelXY 3 129*32172Sedward #define AbsX 4 130*32172Sedward #define AbsY 8 131*32172Sedward #define AbsXY 12 132*32172Sedward 133*32172Sedward private int movepending; /* moveto pending coords on stack */ 134*32172Sedward private int showpending; /* number of characters waiting to be shown */ 135*32172Sedward private char *UsersHeader = 0; /* user specified heading */ 136*32172Sedward private char *Header = 0; /* generated header (usually FileName) */ 137*32172Sedward private int Page = 0; /* current page number */ 138*32172Sedward private int TotalPages = 0; /* total number of pages printed */ 139*32172Sedward private int TruncChars = 0; /* number of characters truncated */ 140*32172Sedward private int UndefChars = 0; /* number of characters skipped because 141*32172Sedward they weren't defined in some font */ 142*32172Sedward private int BadChars = 0; /* number of bad characters seen so far */ 143*32172Sedward 144*32172Sedward private FILE *OutFile = 0; /* output ps file */ 145*32172Sedward 146*32172Sedward /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */ 147*32172Sedward private decodefont (name, f) 148*32172Sedward register char *name; 149*32172Sedward register struct font *f; { 150*32172Sedward register char *d, *p; 151*32172Sedward 152*32172Sedward SeenFont++; 153*32172Sedward if (ScannedFonts) { 154*32172Sedward fprintf(stderr,"Fonts must be specified before any files are processed\n"); 155*32172Sedward exit(1); 156*32172Sedward } 157*32172Sedward p = name; 158*32172Sedward d = f->name; 159*32172Sedward while (isascii(*p) && (isalpha(*p) || (*p == '-'))) {*d++ = *p++;} 160*32172Sedward *d++ = '\0'; 161*32172Sedward if (isascii(*p) && isdigit(*p)) { 162*32172Sedward f->dsize = 0; 163*32172Sedward do 164*32172Sedward f->dsize = f->dsize * 10 + *p++ - '0'; 165*32172Sedward while ('0' <= *p && *p <= '9'); 166*32172Sedward } 167*32172Sedward if (*p || !f->dsize || !f->name[0]) { 168*32172Sedward fprintf (stderr, "Poorly formed font name: \"%s\"\n", name); 169*32172Sedward exit (1); 170*32172Sedward } 171*32172Sedward } 172*32172Sedward 173*32172Sedward 174*32172Sedward #define NOTDEF 0x8000 175*32172Sedward #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--) 176*32172Sedward 177*32172Sedward /* Scan the font metrics directory looking for entries that match the 178*32172Sedward * entries in ``fonts''. For entries 179*32172Sedward * that are found the data in the font description is filled in, 180*32172Sedward * if any are missing, it dies horribly. 181*32172Sedward */ 182*32172Sedward private ScanFont () { 183*32172Sedward register struct font *f; 184*32172Sedward register FILE *FontData; /* afm file */ 185*32172Sedward char *c; 186*32172Sedward int ccode, cwidth, inChars; 187*32172Sedward char *MetricsDir = (char *) getenv ("METRICS"); 188*32172Sedward char FontFile[512]; /* afm file name */ 189*32172Sedward char afmbuf[BUFSIZ]; 190*32172Sedward 191*32172Sedward if (MetricsDir == 0) 192*32172Sedward MetricsDir = LibDir; 193*32172Sedward 194*32172Sedward if (!SeenFont & Rotated & TwoColumn) { 195*32172Sedward fonts[HeaderFont].dsize = 10; 196*32172Sedward fonts[BodyFont].dsize = 7; 197*32172Sedward fonts[KwordFont].dsize = 7; 198*32172Sedward fonts[LiteralFont].dsize = 8; 199*32172Sedward fonts[CommentFont].dsize = 7; 200*32172Sedward } 201*32172Sedward 202*32172Sedward /* loop through fonts, find and read metric entry in dir */ 203*32172Sedward ForAllFonts (f) { 204*32172Sedward mstrcat(FontFile, MetricsDir, "/", sizeof FontFile); 205*32172Sedward mstrcat(FontFile, FontFile, f->name, sizeof FontFile); 206*32172Sedward mstrcat(FontFile, FontFile, ".afm", sizeof FontFile); 207*32172Sedward if ((FontData = fopen(FontFile,"r")) == NULL){ 208*32172Sedward fprintf(stderr,"Can't open font metrics file %s\n",FontFile); 209*32172Sedward exit(1); 210*32172Sedward } 211*32172Sedward /* read the .afm file to get the widths */ 212*32172Sedward for (ccode = 0; ccode < FSIZEMAX; ccode++) f->Xwid[ccode] = NOTDEF; 213*32172Sedward 214*32172Sedward inChars = 0; 215*32172Sedward while(fgets(afmbuf, sizeof afmbuf, FontData) != NULL) { 216*32172Sedward /* strip off newline */ 217*32172Sedward if ((c = index(afmbuf, '\n')) == 0) { 218*32172Sedward fprintf(stderr, "AFM file %s line too long %s\n", FontFile, afmbuf); 219*32172Sedward exit(1); 220*32172Sedward } 221*32172Sedward *c = '\0'; 222*32172Sedward if (*afmbuf == '\0') continue; 223*32172Sedward if (strcmp(afmbuf, "StartCharMetrics") == 0) { 224*32172Sedward inChars++; 225*32172Sedward continue; 226*32172Sedward } 227*32172Sedward if (strcmp(afmbuf, "EndCharMetrics") == 0) break; 228*32172Sedward if (inChars == 1) { 229*32172Sedward if (sscanf(afmbuf, "C %d ; WX %d ;",&ccode,&cwidth) != 2) { 230*32172Sedward fprintf(stderr,"Trouble with AFM file %s\n",FontFile); 231*32172Sedward exit(1); 232*32172Sedward } 233*32172Sedward /* get out once we see an unencoded char */ 234*32172Sedward if (ccode == -1) break; 235*32172Sedward if (ccode > 255) continue; 236*32172Sedward f->Xwid[ccode] = (cwidth * f->dsize * UperPt) / 1000; 237*32172Sedward continue; 238*32172Sedward } 239*32172Sedward } 240*32172Sedward fclose (FontData); 241*32172Sedward } 242*32172Sedward 243*32172Sedward TabWidth = fonts[BodyFont].Xwid['0'] * 8; /* 8 * figure width */ 244*32172Sedward BSWidth = fonts[BodyFont].Xwid[' ']; /* space width */ 245*32172Sedward 246*32172Sedward UperLine = (fonts[BodyFont].dsize + 1) * UperPt; 247*32172Sedward 248*32172Sedward if (LPTsimulate) 249*32172Sedward UperHLine = UperLine; 250*32172Sedward else 251*32172Sedward UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt; 252*32172Sedward 253*32172Sedward crX = 0; 254*32172Sedward crY = -UperLine; 255*32172Sedward } 256*32172Sedward 257*32172Sedward /* Return a font number for the font with the indicated name 258*32172Sedward * and size. Adds info to the font list for the eventual search. 259*32172Sedward */ 260*32172Sedward private DefineFont (name, size) 261*32172Sedward char *name; { 262*32172Sedward register struct font *p; 263*32172Sedward p = &fonts[nf]; 264*32172Sedward strcpy (p->name, name); 265*32172Sedward p->dsize = size; 266*32172Sedward return (nf++); 267*32172Sedward } 268*32172Sedward 269*32172Sedward /* add a shown character to the PS file */ 270*32172Sedward private OUTputc (c) 271*32172Sedward unsigned char c; { 272*32172Sedward if (showpending == 0) {putc('(', OutFile); showpending++;} 273*32172Sedward if (c == '\\' || c=='(' || c == ')') putc('\\', OutFile); 274*32172Sedward if ((c > 0176) || (c < 040)) { 275*32172Sedward putc('\\',OutFile); 276*32172Sedward putc((c >> 6) +'0',OutFile); 277*32172Sedward putc(((c >> 3) & 07)+'0', OutFile); 278*32172Sedward putc((c & 07)+'0',OutFile); 279*32172Sedward } 280*32172Sedward else putc (c, OutFile); 281*32172Sedward } 282*32172Sedward 283*32172Sedward /* Set the current font */ 284*32172Sedward private SetFont (f) { 285*32172Sedward FlushShow(); 286*32172Sedward LastFont = CurFont; 287*32172Sedward fprintf(OutFile, "%d F\n", CurFont = f); 288*32172Sedward } 289*32172Sedward 290*32172Sedward /* Reset to previous font */ 291*32172Sedward private PrevFont () { 292*32172Sedward int temp; 293*32172Sedward 294*32172Sedward FlushShow(); 295*32172Sedward temp = CurFont; 296*32172Sedward CurFont = LastFont; 297*32172Sedward LastFont = temp; 298*32172Sedward fprintf(OutFile, "%d F\n", CurFont); 299*32172Sedward } 300*32172Sedward 301*32172Sedward /* put a character onto the page at the desired X and Y positions. 302*32172Sedward * If the current position doesn't agree with the desired position, put out 303*32172Sedward * movement directives. Leave the current position updated 304*32172Sedward * to account for the character. 305*32172Sedward */ 306*32172Sedward private ShowChar (c) 307*32172Sedward register int c; { 308*32172Sedward register struct font *f; 309*32172Sedward register nX, nY; 310*32172Sedward static level = 0; 311*32172Sedward 312*32172Sedward level++; 313*32172Sedward f = &fonts[CurFont]; 314*32172Sedward 315*32172Sedward if (f->Xwid[c] == NOTDEF) { 316*32172Sedward UndefChars++; 317*32172Sedward if(ListOmitted) 318*32172Sedward printf("\'%c\' (%03o) not found in font %s\n",c,c,f->name); 319*32172Sedward if(level<=1){ 320*32172Sedward ShowChar('\\'); 321*32172Sedward ShowChar((c>>6)+'0'); 322*32172Sedward ShowChar(((c>>3)&07)+'0'); 323*32172Sedward ShowChar((c&07)+'0'); 324*32172Sedward } 325*32172Sedward level--; 326*32172Sedward return; 327*32172Sedward } 328*32172Sedward nX = dX + f->Xwid[c]; /* resulting position after showing this char */ 329*32172Sedward nY = dY; 330*32172Sedward 331*32172Sedward if (c != ' ' || ((cX == dX) && (cY == dY))) 332*32172Sedward if ((!Rotated && (nX <= PageWidth) && (nY <= PageLength)) 333*32172Sedward || (Rotated && (nX <= PageLength) && (nY <= PageWidth))) { 334*32172Sedward if (cX != dX) { 335*32172Sedward if (cY != dY) { 336*32172Sedward FlushShow(); 337*32172Sedward /* absolute x, relative y */ 338*32172Sedward fprintf(OutFile,"%d %d",dX, dY); 339*32172Sedward movepending = AbsXY; 340*32172Sedward } 341*32172Sedward else { 342*32172Sedward FlushShow(); 343*32172Sedward fprintf(OutFile,"%d",dX-cX); /* relative x */ 344*32172Sedward movepending = RelX; 345*32172Sedward } 346*32172Sedward } 347*32172Sedward else if (cY != dY) { 348*32172Sedward FlushShow(); 349*32172Sedward fprintf(OutFile,"%d",dY-cY); /* relative y */ 350*32172Sedward movepending = RelY; 351*32172Sedward } 352*32172Sedward OUTputc (c); 353*32172Sedward showpending++; 354*32172Sedward cX = nX; 355*32172Sedward cY = nY; 356*32172Sedward } 357*32172Sedward else 358*32172Sedward TruncChars++; 359*32172Sedward dX = nX; 360*32172Sedward dY = nY; 361*32172Sedward 362*32172Sedward level--; 363*32172Sedward } 364*32172Sedward 365*32172Sedward /* put out a shown string to the PS file */ 366*32172Sedward private ShowStr (s) 367*32172Sedward register char *s; { 368*32172Sedward while (*s) { 369*32172Sedward if (*s >= 040) ShowChar (*s); 370*32172Sedward s++; 371*32172Sedward } 372*32172Sedward } 373*32172Sedward 374*32172Sedward /* flush pending show */ 375*32172Sedward private FlushShow() { 376*32172Sedward if (showpending) { 377*32172Sedward putc(')',OutFile); 378*32172Sedward switch (movepending) { 379*32172Sedward case RelX: 380*32172Sedward putc('X',OutFile); 381*32172Sedward break; 382*32172Sedward case RelY: 383*32172Sedward putc('Y',OutFile); 384*32172Sedward break; 385*32172Sedward case AbsXY: 386*32172Sedward putc('B',OutFile); 387*32172Sedward break; 388*32172Sedward case None: 389*32172Sedward putc('S',OutFile); 390*32172Sedward break; 391*32172Sedward } 392*32172Sedward putc('\n',OutFile); 393*32172Sedward movepending = None; 394*32172Sedward showpending = 0; 395*32172Sedward } 396*32172Sedward } 397*32172Sedward 398*32172Sedward /* put out a page heading to the PS file */ 399*32172Sedward private InitPage () { 400*32172Sedward char *basename(); 401*32172Sedward char header[200]; 402*32172Sedward register int OldFont = CurFont; 403*32172Sedward 404*32172Sedward TotalPages++; 405*32172Sedward fprintf(OutFile, "%%%%Page: ? %d\n", TotalPages); 406*32172Sedward fprintf(OutFile, "StartPage\n"); 407*32172Sedward LinesLeft = 64; 408*32172Sedward SeenText = 0; 409*32172Sedward cX = cY = -1; 410*32172Sedward showpending = 0; 411*32172Sedward FirstCol = 1; 412*32172Sedward lX = dX = UperInch; 413*32172Sedward lY = dY = PageLength - UperHLine * 3 / 2; 414*32172Sedward if (Rotated) { 415*32172Sedward fprintf(OutFile, "Landscape\n"); 416*32172Sedward lX = dX = UperInch / 4; 417*32172Sedward } 418*32172Sedward movepending = None; 419*32172Sedward cX = dX; cY = dY; 420*32172Sedward if (!NoTitle) { 421*32172Sedward SetFont (HeaderFont); 422*32172Sedward fprintf(OutFile, "%d %d ", cX, cY); 423*32172Sedward movepending = AbsXY; 424*32172Sedward if (UsersHeader) { 425*32172Sedward if (*UsersHeader == 0) { 426*32172Sedward fprintf(OutFile,"()B\n"); 427*32172Sedward movepending = None; 428*32172Sedward showpending = 0; 429*32172Sedward } 430*32172Sedward else ShowStr (UsersHeader); 431*32172Sedward } 432*32172Sedward else { 433*32172Sedward Page++; 434*32172Sedward if (FileName == 0) 435*32172Sedward sprintf(header, "Page %d", Page); 436*32172Sedward else 437*32172Sedward sprintf (header, "%s, page %d", basename(FileName), Page); 438*32172Sedward ShowStr (header); 439*32172Sedward } 440*32172Sedward FlushShow(); 441*32172Sedward dX = lX = lX + crX * 3; 442*32172Sedward dY = lY = lY + crY * 3; 443*32172Sedward } 444*32172Sedward else { 445*32172Sedward /* fake it to force a moveto */ 446*32172Sedward cX = cY = 0; 447*32172Sedward } 448*32172Sedward SetFont (OldFont); 449*32172Sedward } 450*32172Sedward 451*32172Sedward /* terminate a page. */ 452*32172Sedward private ClosePage () { 453*32172Sedward FlushShow(); 454*32172Sedward fprintf(OutFile,"EndPage\n"); 455*32172Sedward } 456*32172Sedward 457*32172Sedward /* skip to a new page */ 458*32172Sedward private PageEject () { 459*32172Sedward if (TwoColumn && FirstCol) { 460*32172Sedward FirstCol = 0; 461*32172Sedward lX = dX = TruePageWidth / 2; 462*32172Sedward lY = dY = PageLength - (UperHLine * 3 / 2); 463*32172Sedward if (Rotated) { 464*32172Sedward lX = dX = TruePageLength / 2; 465*32172Sedward } 466*32172Sedward if (!NoTitle) { 467*32172Sedward dX = lX = lX + crX * 3; 468*32172Sedward dY = lY = lY + crY * 3; 469*32172Sedward } 470*32172Sedward } 471*32172Sedward else { 472*32172Sedward ClosePage (); 473*32172Sedward InitPage (); 474*32172Sedward } 475*32172Sedward LinesLeft = 64; 476*32172Sedward SeenText = 0; 477*32172Sedward } 478*32172Sedward 479*32172Sedward #if 0 480*32172Sedward /* commented out AIS Fri Feb 22 10:00:36 1985 */ 481*32172Sedward private PageMessage (TotalPages) 482*32172Sedward { 483*32172Sedward if (TotalPages > 0) { 484*32172Sedward printf ("psgrind formatted[ %d page%s * %d cop%s ]\n", 485*32172Sedward TotalPages, TotalPages > 1 ? "s" : "", 486*32172Sedward spoolCopies, spoolCopies > 1 ? "ies" : "y" ); 487*32172Sedward } 488*32172Sedward } 489*32172Sedward #endif 490*32172Sedward 491*32172Sedward private CommentHeader() { 492*32172Sedward long clock; 493*32172Sedward struct passwd *pswd; 494*32172Sedward char hostname[40]; 495*32172Sedward /* copy the file, prepending a new comment header */ 496*32172Sedward fprintf(OutFile,"%%!%s\n",COMMENTVERSION); 497*32172Sedward fprintf(OutFile,"%%%%Creator: "); 498*32172Sedward pswd = getpwuid(getuid()); 499*32172Sedward gethostname(hostname, (int) sizeof hostname); 500*32172Sedward fprintf(OutFile,"%s:%s (%s)%s\n", hostname, pswd->pw_name, 501*32172Sedward pswd->pw_gecos, spoolJobClass); 502*32172Sedward 503*32172Sedward fprintf(OutFile,"%%%%Title: %s %s\n", 504*32172Sedward (FileName?FileName:"stdin"), 505*32172Sedward spoolJobName); 506*32172Sedward 507*32172Sedward fprintf(OutFile,"%%%%CreationDate: %s",(time(&clock),ctime(&clock))); 508*32172Sedward } 509*32172Sedward 510*32172Sedward 511*32172Sedward /* list of C keywords to put in KwordFont */ 512*32172Sedward private char *KeyWordList[] = { 513*32172Sedward "int", "char", "float", "double", "struct", "union", 514*32172Sedward "long", "short", "unsigned", "auto", "extern", "register", 515*32172Sedward "typedef", "static", "goto", "return", "sizeof", "break", 516*32172Sedward "continue", "if", "else", "for", "do", "while", "switch", 517*32172Sedward "case", "default", "entry", NULL 518*32172Sedward }; 519*32172Sedward 520*32172Sedward /* macros identifying C identifiers */ 521*32172Sedward #define isfirst(c) (isalpha(c) || (c) == '_') 522*32172Sedward #define isident(c) (isalnum(c) || (c) == '_') 523*32172Sedward 524*32172Sedward /* Copy the standard input file to the PS file */ 525*32172Sedward private CopyFile () { 526*32172Sedward register int c, last; 527*32172Sedward register int col = 1; 528*32172Sedward int InComment, InString, InChar, IsKword; 529*32172Sedward char token[50], *tend = token + sizeof (token) - 1; 530*32172Sedward register char *tp, **kwp; 531*32172Sedward 532*32172Sedward if (OutFile == 0) { 533*32172Sedward if (OutOnly && !(PageSpec || Reverse)) { 534*32172Sedward OutFile = PipeOut ? stdout : fopen(OutName,"w"); 535*32172Sedward } 536*32172Sedward else { 537*32172Sedward mktemp(mstrcat(TempName,TempDir,PSGRINDTEMP,sizeof TempName)); 538*32172Sedward OutFile = fopen (TempName, "w"); 539*32172Sedward } 540*32172Sedward } 541*32172Sedward if (OutFile == NULL) { 542*32172Sedward fprintf(stderr, "Can't create PS file %s\n",TempName); 543*32172Sedward exit(1); 544*32172Sedward } 545*32172Sedward if (!ScannedFonts) { 546*32172Sedward ScannedFonts++; 547*32172Sedward ScanFont(); 548*32172Sedward } 549*32172Sedward if (!Cvted) { 550*32172Sedward CommentHeader(); 551*32172Sedward if (nf) { 552*32172Sedward register struct font *f; 553*32172Sedward fprintf(OutFile,"%%%%DocumentFonts:"); 554*32172Sedward ForAllFonts(f) { 555*32172Sedward fprintf(OutFile," %s",f->name); 556*32172Sedward } 557*32172Sedward fprintf(OutFile,"\n"); 558*32172Sedward } 559*32172Sedward /* copy in fixed prolog */ 560*32172Sedward if (copyfile(mstrcat(tempstr,LibDir,PSGRINDPRO,sizeof tempstr), 561*32172Sedward OutFile)) { 562*32172Sedward fprintf(stderr,"trouble copying prolog file \"%s\".\n",tempstr); 563*32172Sedward exit(1); 564*32172Sedward } 565*32172Sedward fprintf(OutFile,"StartEnscriptDoc %% end fixed prolog\n"); 566*32172Sedward DumpFonts(); 567*32172Sedward fprintf(OutFile,"%%%%EndProlog\n"); 568*32172Sedward if (PreFeed) { 569*32172Sedward fprintf(OutFile,"true DoPreFeed\n"); 570*32172Sedward } 571*32172Sedward } 572*32172Sedward Cvted++; 573*32172Sedward 574*32172Sedward Page = 0; 575*32172Sedward LineNo = 1; 576*32172Sedward BadChars = 0; /* give each file a clean slate */ 577*32172Sedward InitPage (); 578*32172Sedward last = '\0'; 579*32172Sedward InComment = InChar = InString = 0; 580*32172Sedward while ((c = getchar ()) != EOF) { 581*32172Sedward if ((c > 0177 || c < 0) && (!IgnoreGarbage)) { 582*32172Sedward if (BadChars++ > MAXBAD) {/* allow some kruft but not much */ 583*32172Sedward fprintf(stderr,"\"%s\" not a text file? - char '\\%03o'@0%o\nTry -g.\n", 584*32172Sedward FileName ? FileName : "stdin", c, ftell (stdin) - 1); 585*32172Sedward exit(1); 586*32172Sedward } 587*32172Sedward } else { 588*32172Sedward switch (c) { 589*32172Sedward case 010: /* backspace */ 590*32172Sedward dX -= BSWidth; 591*32172Sedward break; 592*32172Sedward case 015: /* carriage return ^M */ 593*32172Sedward dY = lY; 594*32172Sedward dX = lX; 595*32172Sedward break; 596*32172Sedward case 012: /* linefeed ^J */ 597*32172Sedward LineNo++; 598*32172Sedward if (dX != lX || dY != lY || !LPTsimulate || SeenText){ 599*32172Sedward SeenText++; 600*32172Sedward dY = lY = lY + crY; 601*32172Sedward dX = lX = lX + crX; 602*32172Sedward } 603*32172Sedward else 604*32172Sedward LinesLeft = 64; 605*32172Sedward if (((!Rotated) && (dY < UperLine)) 606*32172Sedward || (Rotated && (dY < ((PageLength-TruePageWidth) + 607*32172Sedward 3*UperLine+480))) 608*32172Sedward || (LPTsimulate && (--LinesLeft <= 0))) 609*32172Sedward PageEject (); 610*32172Sedward col = 1; 611*32172Sedward break; 612*32172Sedward case 014: /* form feed ^L */ 613*32172Sedward PageEject (); 614*32172Sedward col = 1; 615*32172Sedward break; 616*32172Sedward case 011: /* tab ^I */ 617*32172Sedward col = (col - 1) / 8 * 8 + 9; 618*32172Sedward dX = lX + (col - 1) / 8 * TabWidth; 619*32172Sedward break; 620*32172Sedward case '\\': /* special escape */ 621*32172Sedward last = c; 622*32172Sedward if ((c = getchar()) == EOF) 623*32172Sedward goto done; 624*32172Sedward ShowChar('\\'); 625*32172Sedward col++; 626*32172Sedward if (c == '\n') { 627*32172Sedward /* want to leave newlines alone */ 628*32172Sedward ungetc(c, stdin); 629*32172Sedward } else { 630*32172Sedward ShowChar(c); 631*32172Sedward col++; 632*32172Sedward } 633*32172Sedward break; 634*32172Sedward case '"': /* a string quote mark */ 635*32172Sedward if (InComment || InChar) { 636*32172Sedward /* just put out the quote */ 637*32172Sedward ShowChar('"'); 638*32172Sedward col++; 639*32172Sedward } else if (InString) { 640*32172Sedward ShowChar('"'); 641*32172Sedward col++; 642*32172Sedward PrevFont(); 643*32172Sedward InString = 0; 644*32172Sedward } else { 645*32172Sedward SetFont(LiteralFont); 646*32172Sedward ShowChar('"'); 647*32172Sedward col++; 648*32172Sedward InString = 1; 649*32172Sedward } 650*32172Sedward break; 651*32172Sedward case '\'': /* a char quote mark */ 652*32172Sedward if (InComment || InString) { 653*32172Sedward /* just put out the character */ 654*32172Sedward ShowChar('\''); 655*32172Sedward col++; 656*32172Sedward } else if (InChar) { 657*32172Sedward ShowChar('\''); 658*32172Sedward col++; 659*32172Sedward PrevFont(); 660*32172Sedward InChar = 0; 661*32172Sedward } else { 662*32172Sedward SetFont(LiteralFont); 663*32172Sedward ShowChar('\''); 664*32172Sedward col++; 665*32172Sedward InChar = 1; 666*32172Sedward } 667*32172Sedward break; 668*32172Sedward case '/': 669*32172Sedward if (InComment && last == '*') { 670*32172Sedward ShowChar('/'); 671*32172Sedward col++; 672*32172Sedward SetFont(BodyFont); 673*32172Sedward InComment = 0; 674*32172Sedward } else if ((c = getchar()) == '*' && !InComment) { 675*32172Sedward SetFont(CommentFont); 676*32172Sedward InComment = 1; 677*32172Sedward ShowChar('/'); 678*32172Sedward ShowChar('*'); 679*32172Sedward col += 2; 680*32172Sedward } else { 681*32172Sedward ungetc(c, stdin); 682*32172Sedward ShowChar('/'); 683*32172Sedward col++; 684*32172Sedward c = '/'; 685*32172Sedward } 686*32172Sedward break; 687*32172Sedward default: /* plain text, put it out */ 688*32172Sedward if (!InComment && !InString && isfirst(c)) { 689*32172Sedward tp = token; 690*32172Sedward while (isident(c) && tp < tend) { 691*32172Sedward *tp++ = c; 692*32172Sedward last = c; 693*32172Sedward c = getchar(); 694*32172Sedward } 695*32172Sedward *tp = '\0'; 696*32172Sedward ungetc(c, stdin); 697*32172Sedward tp = token; 698*32172Sedward IsKword = 0; 699*32172Sedward for (kwp = KeyWordList; *kwp != NULL; kwp++) 700*32172Sedward if (!strcmp(*kwp, tp)) { 701*32172Sedward IsKword = 1; 702*32172Sedward break; 703*32172Sedward } 704*32172Sedward if (IsKword) 705*32172Sedward SetFont(KwordFont); 706*32172Sedward ShowStr(tp); 707*32172Sedward col += strlen(tp); 708*32172Sedward if (IsKword) 709*32172Sedward SetFont(BodyFont); 710*32172Sedward } else if (fonts[CurFont].Xwid[c] != NOTDEF) { 711*32172Sedward /* other normal character */ 712*32172Sedward ShowChar (c); 713*32172Sedward col++; 714*32172Sedward } else { /* not in font, quote it */ 715*32172Sedward ShowChar ('\\'); 716*32172Sedward ShowChar ((c >> 6) + '0'); 717*32172Sedward ShowChar (((c >> 3) & 7) + '0'); 718*32172Sedward ShowChar ((c & 7) + '0'); 719*32172Sedward col += 4; 720*32172Sedward } 721*32172Sedward break; 722*32172Sedward } 723*32172Sedward } 724*32172Sedward last = c; 725*32172Sedward } 726*32172Sedward 727*32172Sedward done: 728*32172Sedward ClosePage (); 729*32172Sedward } 730*32172Sedward 731*32172Sedward /* dump the fonts to the PS file for setup */ 732*32172Sedward private DumpFonts () { 733*32172Sedward register struct font *f; 734*32172Sedward 735*32172Sedward ForAllFonts (f) { 736*32172Sedward fprintf(OutFile,"%d %d /%s\n",f-&fonts[0],f->dsize*UperPt,f->name); 737*32172Sedward } 738*32172Sedward fprintf(OutFile, "%d SetUpFonts\n", nf); 739*32172Sedward } 740*32172Sedward 741*32172Sedward 742*32172Sedward /* 743*32172Sedward * close the PS file 744*32172Sedward */ 745*32172Sedward private ClosePS () { 746*32172Sedward fprintf(OutFile,"%%%%Trailer\n"); 747*32172Sedward if (PreFeed) { 748*32172Sedward fprintf(OutFile,"false DoPreFeed\n"); 749*32172Sedward } 750*32172Sedward fprintf(OutFile,"EndEnscriptDoc\nEnscriptJob restore\n"); 751*32172Sedward } 752*32172Sedward 753*32172Sedward private ProcessArg (p) 754*32172Sedward register char *p; { 755*32172Sedward static enum State { 756*32172Sedward normal, PSname, 757*32172Sedward H_fontname, B_fontname, K_fontname, C_fontname, L_fontname, 758*32172Sedward grabheader, getclass, getjobname 759*32172Sedward } state = normal; 760*32172Sedward 761*32172Sedward switch (state) { 762*32172Sedward case PSname: 763*32172Sedward strcpy (OutName, p); 764*32172Sedward if (strcmp(OutName,"-") == 0) PipeOut++; 765*32172Sedward state = normal; 766*32172Sedward break; 767*32172Sedward case H_fontname: 768*32172Sedward decodefont (p, &fonts[HeaderFont]); 769*32172Sedward state = normal; 770*32172Sedward break; 771*32172Sedward case B_fontname: 772*32172Sedward decodefont (p, &fonts[BodyFont]); 773*32172Sedward state = normal; 774*32172Sedward break; 775*32172Sedward case K_fontname: 776*32172Sedward decodefont (p, &fonts[KwordFont]); 777*32172Sedward state = normal; 778*32172Sedward break; 779*32172Sedward case L_fontname: 780*32172Sedward decodefont (p, &fonts[LiteralFont]); 781*32172Sedward state = normal; 782*32172Sedward break; 783*32172Sedward case C_fontname: 784*32172Sedward decodefont (p, &fonts[CommentFont]); 785*32172Sedward state = normal; 786*32172Sedward break; 787*32172Sedward case grabheader: 788*32172Sedward UsersHeader = p; 789*32172Sedward state = normal; 790*32172Sedward break; 791*32172Sedward case getclass: 792*32172Sedward spoolJobClass = p; 793*32172Sedward state = normal; 794*32172Sedward break; 795*32172Sedward case getjobname: 796*32172Sedward spoolJobName = p; 797*32172Sedward state = normal; 798*32172Sedward break; 799*32172Sedward default: 800*32172Sedward if (*p == '-') while (*++p) switch (*p) { 801*32172Sedward case '1': 802*32172Sedward TwoColumn = 0; 803*32172Sedward if (SeenFile) { 804*32172Sedward fprintf(stderr,"Specify -1 before any files\n"); 805*32172Sedward exit(1); 806*32172Sedward } 807*32172Sedward break; 808*32172Sedward case '2': 809*32172Sedward TwoColumn++; 810*32172Sedward if (SeenFile){ 811*32172Sedward fprintf(stderr,"Specify -2 before any files\n"); 812*32172Sedward exit(1); 813*32172Sedward } 814*32172Sedward break; 815*32172Sedward case 'v': 816*32172Sedward Reverse = 1; 817*32172Sedward break; 818*32172Sedward case 's': 819*32172Sedward PageSpec = (++p); 820*32172Sedward while (*p != '\0') p++; 821*32172Sedward return; 822*32172Sedward 823*32172Sedward /* the following options allow uswer specification 824*32172Sedward of the five files used by the program */ 825*32172Sedward case 'H': state = H_fontname; break; 826*32172Sedward case 'B': state = B_fontname; break; 827*32172Sedward case 'K': state = K_fontname; break; 828*32172Sedward case 'L': state = L_fontname; break; 829*32172Sedward case 'C': state = C_fontname; break; 830*32172Sedward 831*32172Sedward case 'g': IgnoreGarbage++; break; 832*32172Sedward case 'o': ListOmitted++; break; 833*32172Sedward case 'p': OutOnly++; state = PSname; break; 834*32172Sedward case 'r': 835*32172Sedward Rotated++; 836*32172Sedward if (SeenFile){ 837*32172Sedward fprintf(stderr,"Specify rotation before any files\n"); 838*32172Sedward exit(1); 839*32172Sedward } 840*32172Sedward break; 841*32172Sedward case 'R': 842*32172Sedward Rotated = 0; 843*32172Sedward if (SeenFile){ 844*32172Sedward fprintf(stderr,"Specify rotation before any files\n"); 845*32172Sedward exit(1); 846*32172Sedward } 847*32172Sedward break; 848*32172Sedward case 'k': 849*32172Sedward PreFeed++; 850*32172Sedward if (SeenFile){ 851*32172Sedward fprintf(stderr,"Specify prefeed before any files\n"); 852*32172Sedward exit(1); 853*32172Sedward } 854*32172Sedward break; 855*32172Sedward 856*32172Sedward /* the following switches are as in lpr(1) and */ 857*32172Sedward /* are passed through when spooling to a printer */ 858*32172Sedward case 'P': /* printer name */ 859*32172Sedward PrinterName = (++p); 860*32172Sedward while (*p != '\0') p++; 861*32172Sedward return; 862*32172Sedward case 'J': /* job name (title) for the Job: field */ 863*32172Sedward state = getjobname; 864*32172Sedward break; 865*32172Sedward case 'm': /* notify by mail */ 866*32172Sedward spoolNotify = 1; 867*32172Sedward break; 868*32172Sedward case 'h': 869*32172Sedward spoolNoBurst = 1; 870*32172Sedward break; 871*32172Sedward case '#': 872*32172Sedward spoolCopies = atoi(++p); 873*32172Sedward if (spoolCopies < 1){ 874*32172Sedward fprintf(stderr,"Bad argument for -# (number of copies)\n"); 875*32172Sedward exit(1); 876*32172Sedward } 877*32172Sedward break; 878*32172Sedward 879*32172Sedward default: 880*32172Sedward printf ("Unknown option: %c\n", *p); 881*32172Sedward SeenFile++; 882*32172Sedward break; 883*32172Sedward } 884*32172Sedward else {/* not a flag -- a filename */ 885*32172Sedward FileName = Header = p; 886*32172Sedward if (freopen (FileName, "r", stdin) == NULL) { 887*32172Sedward printf ("Can't open %s\n", FileName); 888*32172Sedward exit (1); 889*32172Sedward } 890*32172Sedward fstat (fileno (stdin), &S); 891*32172Sedward FileDate = strcpy(DateStr,ctime (&S.st_mtime)); 892*32172Sedward CopyFile (); 893*32172Sedward fclose (stdin); 894*32172Sedward SeenFile = 1; 895*32172Sedward } 896*32172Sedward } 897*32172Sedward } 898*32172Sedward 899*32172Sedward main (argc, argv) 900*32172Sedward char **argv; { 901*32172Sedward register char *p, *arg; 902*32172Sedward 903*32172Sedward prog = *argv; 904*32172Sedward 905*32172Sedward BodyFont = LastFont = CurFont = DefineFont (BODYFONT, 10); 906*32172Sedward HeaderFont = DefineFont (HEADERFONT, 12); 907*32172Sedward KwordFont = DefineFont (KWORDFONT, 10); 908*32172Sedward CommentFont = DefineFont (COMMENTFONT, 10); 909*32172Sedward LiteralFont = DefineFont (LITERALFONT, 11); 910*32172Sedward 911*32172Sedward /* process args in environment variable PSGRIND */ 912*32172Sedward if (p = getenv ("PSGRIND")) 913*32172Sedward while (1) { 914*32172Sedward register char quote = ' '; 915*32172Sedward while (*p == ' ') 916*32172Sedward p++; 917*32172Sedward if (*p == '"' || *p == '\'') 918*32172Sedward quote = *p++; 919*32172Sedward arg = p; 920*32172Sedward while (*p != quote && *p != '\0') 921*32172Sedward p++; 922*32172Sedward if (*p == '\0') { 923*32172Sedward if (*arg) 924*32172Sedward ProcessArg (arg); 925*32172Sedward break; 926*32172Sedward } 927*32172Sedward *p++ = '\0'; 928*32172Sedward ProcessArg (arg); 929*32172Sedward } 930*32172Sedward 931*32172Sedward /* process the command line arguments */ 932*32172Sedward while (argc > 1) { 933*32172Sedward argc--; 934*32172Sedward ProcessArg (*++argv); 935*32172Sedward } 936*32172Sedward 937*32172Sedward if (!SeenFile) { 938*32172Sedward FileName = Header = 0; 939*32172Sedward FileDate = ""; 940*32172Sedward fstat (fileno (stdin), &S); 941*32172Sedward 942*32172Sedward if ((S.st_mode & S_IFMT) == S_IFREG) 943*32172Sedward FileDate = strcpy(DateStr, ctime (&S.st_mtime)); 944*32172Sedward CopyFile (); 945*32172Sedward } 946*32172Sedward 947*32172Sedward if (Cvted) { 948*32172Sedward ClosePS (); 949*32172Sedward fclose (OutFile); 950*32172Sedward OutFile = 0; 951*32172Sedward } 952*32172Sedward if (TruncChars) 953*32172Sedward printf ("%d characters omitted because of long lines.\n", 954*32172Sedward TruncChars); 955*32172Sedward if (UndefChars) 956*32172Sedward printf ("%d characters omitted because of incomplete fonts.\n", 957*32172Sedward UndefChars); 958*32172Sedward /* PageMessage (TotalPages); */ 959*32172Sedward if (Cvted) { 960*32172Sedward if (OutOnly) { 961*32172Sedward if (Reverse || PageSpec) { 962*32172Sedward char temparg[200]; 963*32172Sedward char *sargs[200]; 964*32172Sedward int args = 0; 965*32172Sedward 966*32172Sedward int cpid = 0; 967*32172Sedward /* feed Temporary through psrev */ 968*32172Sedward freopen(TempName, "r", stdin); 969*32172Sedward if (!PipeOut) freopen(OutName, "w", stdout); 970*32172Sedward unlink(TempName); 971*32172Sedward 972*32172Sedward addarg(sargs, REVERSE, &args); 973*32172Sedward addarg(sargs, "-r", &args); 974*32172Sedward if (!Reverse) addarg(sargs, "-R", &args); 975*32172Sedward 976*32172Sedward if (PageSpec) { 977*32172Sedward sprintf(temparg,"-s%s",PageSpec); 978*32172Sedward addarg(sargs, temparg, &args); 979*32172Sedward } 980*32172Sedward if ((cpid = fork()) < 0) pexit(prog,1); 981*32172Sedward if (cpid == 0) { 982*32172Sedward execvp(REVERSE, sargs); 983*32172Sedward pexit(prog,1); 984*32172Sedward } 985*32172Sedward else { 986*32172Sedward wait(0); 987*32172Sedward } 988*32172Sedward } 989*32172Sedward /* fprintf (stderr,"PS file left on %s\n", OutName); */ 990*32172Sedward } 991*32172Sedward else 992*32172Sedward SpoolIt(); 993*32172Sedward } 994*32172Sedward } 995*32172Sedward 996*32172Sedward private addarg(argv, argstr, argc) 997*32172Sedward char **argv; 998*32172Sedward char *argstr; 999*32172Sedward register int *argc; 1000*32172Sedward { 1001*32172Sedward register char *p = (char *) malloc (strlen(argstr) + 1); 1002*32172Sedward strcpy (p, argstr); 1003*32172Sedward argv[(*argc)++] = p; 1004*32172Sedward argv[*argc] = '\0'; 1005*32172Sedward } 1006*32172Sedward 1007*32172Sedward private SpoolIt() 1008*32172Sedward { 1009*32172Sedward char temparg[200]; 1010*32172Sedward char *argstr[200]; 1011*32172Sedward int nargs = 0; 1012*32172Sedward 1013*32172Sedward char *rargs[40]; 1014*32172Sedward int nr = 0; 1015*32172Sedward int cpid =0; 1016*32172Sedward int fdpipe[2]; 1017*32172Sedward 1018*32172Sedward addarg(argstr, LPR, &nargs); 1019*32172Sedward if (spoolCopies > 1) { 1020*32172Sedward sprintf(temparg,"-#%d",spoolCopies); 1021*32172Sedward addarg(argstr, temparg, &nargs); 1022*32172Sedward } 1023*32172Sedward if (PrinterName) { 1024*32172Sedward sprintf(temparg,"-P%s",PrinterName); 1025*32172Sedward addarg(argstr, temparg, &nargs); 1026*32172Sedward } 1027*32172Sedward else if (getenv("PRINTER") == 0) { 1028*32172Sedward /* no printer name known anywhere, use default */ 1029*32172Sedward sprintf(temparg,"-P%s",POSTSCRIPTPRINTER); 1030*32172Sedward addarg(argstr, temparg, &nargs); 1031*32172Sedward } 1032*32172Sedward if (spoolJobClass) { 1033*32172Sedward addarg(argstr, "-C", &nargs); 1034*32172Sedward addarg(argstr, spoolJobClass, &nargs); 1035*32172Sedward } 1036*32172Sedward addarg(argstr, "-J", &nargs); 1037*32172Sedward if (spoolJobName) { 1038*32172Sedward addarg(argstr, spoolJobName, &nargs); 1039*32172Sedward } 1040*32172Sedward else { 1041*32172Sedward if (!FileName) addarg(argstr, "stdin", &nargs); 1042*32172Sedward else addarg(argstr, FileName, &nargs); 1043*32172Sedward } 1044*32172Sedward if (spoolNotify) { 1045*32172Sedward addarg(argstr, "-m", &nargs); 1046*32172Sedward } 1047*32172Sedward if (spoolNoBurst) { 1048*32172Sedward addarg(argstr, "-h", &nargs); 1049*32172Sedward } 1050*32172Sedward 1051*32172Sedward if (Reverse || PageSpec) { 1052*32172Sedward /* lpr input will be stdin */ 1053*32172Sedward 1054*32172Sedward addarg(rargs, REVERSE, &nr); 1055*32172Sedward addarg(rargs, "-r", &nr); 1056*32172Sedward if (!Reverse) addarg(rargs, "-R", &nr); 1057*32172Sedward if (PageSpec) { 1058*32172Sedward sprintf(temparg,"-s%s",PageSpec); 1059*32172Sedward addarg(rargs, temparg, &nr); 1060*32172Sedward } 1061*32172Sedward /* addarg(rargs, TempName, &nr); */ 1062*32172Sedward 1063*32172Sedward freopen(TempName,"r",stdin); 1064*32172Sedward unlink(TempName); 1065*32172Sedward if (pipe(fdpipe)) pexit(prog,1); 1066*32172Sedward if ((cpid = fork()) < 0) pexit(prog,1); 1067*32172Sedward else if (!cpid) { /* child */ 1068*32172Sedward if (close(1)) { 1069*32172Sedward pexit(prog,1); 1070*32172Sedward } 1071*32172Sedward /* set stdout to be the output pipe */ 1072*32172Sedward if (dup (fdpipe[1]) == -1) { 1073*32172Sedward pexit(prog,1); 1074*32172Sedward } 1075*32172Sedward /* don't want to read or write the pipe itself, since dup */ 1076*32172Sedward if (close (fdpipe[1]) || close (fdpipe[0])) { 1077*32172Sedward pexit(prog,1); 1078*32172Sedward } 1079*32172Sedward /* leave stderr alone */ 1080*32172Sedward execvp (REVERSE, rargs); 1081*32172Sedward pexit(prog,1); 1082*32172Sedward } 1083*32172Sedward else { 1084*32172Sedward /* parent */ 1085*32172Sedward /* replace stdin with pipe */ 1086*32172Sedward if (close(0)) { 1087*32172Sedward pexit(prog,1); 1088*32172Sedward } 1089*32172Sedward 1090*32172Sedward if (dup(fdpipe[0]) == -1) { 1091*32172Sedward pexit(prog,1); 1092*32172Sedward } 1093*32172Sedward if (close (fdpipe[0]) || close (fdpipe[1])) { 1094*32172Sedward pexit(prog,1); 1095*32172Sedward } 1096*32172Sedward 1097*32172Sedward /* leave stdout and stderr alone */ 1098*32172Sedward execvp(LPR, argstr); 1099*32172Sedward pexit(prog,1); 1100*32172Sedward } 1101*32172Sedward } 1102*32172Sedward else { /* just do lpr */ 1103*32172Sedward /* remove the temporary file after spooling */ 1104*32172Sedward addarg(argstr, "-r", &nargs); /* should we use a symbolic link too? */ 1105*32172Sedward addarg(argstr, TempName, &nargs); 1106*32172Sedward execvp(LPR, argstr); 1107*32172Sedward pexit(prog,1); 1108*32172Sedward } 1109*32172Sedward } 1110*32172Sedward 1111*32172Sedward char * 1112*32172Sedward basename(path) 1113*32172Sedward char *path; 1114*32172Sedward { 1115*32172Sedward register char *cp; 1116*32172Sedward 1117*32172Sedward for (cp = path; *cp != '\0'; cp++) 1118*32172Sedward ; 1119*32172Sedward for (--cp; cp > path && *cp != '/'; cp--) 1120*32172Sedward ; 1121*32172Sedward if (*cp == '/' && *(cp+1) != '\0') 1122*32172Sedward return (cp + 1); 1123*32172Sedward else 1124*32172Sedward return (path); 1125*32172Sedward } 1126