~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/psf/psf.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: psf.c,v 1.8 2002/05/23 15:58:55 rufustfirefly Exp $
 
3
 *
 
4
 * Copyright (c) 1990,1995 Regents of The University of Michigan.
 
5
 * All Rights Reserved. See COPYRIGHT.
 
6
 *
 
7
 * PostScript Filter, psf.
 
8
 *
 
9
 * Handles both PostScript files and text files.  Files with the
 
10
 * '%!' PostScript header are sent directly to the printer,
 
11
 * unmodified.  Text files are first converted to PostScript,
 
12
 * then sent.  Printers may be directly attached or on an AppleTalk
 
13
 * network.  Other media are possible.  Currently, psf invokes
 
14
 * pap to send files to AppleTalk-ed printers.  Replace the pap*
 
15
 * variables to use another program for communication.  psf only
 
16
 * converts plain-text.  If called as "tf" or "df", psf will invoke
 
17
 * a troff or dvi to PostScript converter.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif /* HAVE_CONFIG_H */
 
23
 
 
24
#define FUCKED
 
25
 
 
26
#ifdef HAVE_UNISTD_H
 
27
#include <unistd.h>
 
28
#endif /* HAVE_UNISTD_H */
 
29
#include <sys/time.h>
 
30
 
 
31
/* POSIX.1 sys/wait.h check */
 
32
#include <sys/types.h>
 
33
#ifdef HAVE_SYS_WAIT_H
 
34
#include <sys/wait.h>
 
35
#endif /* HAVE_SYS_WAIT_H */
 
36
#ifndef WEXITSTATUS
 
37
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 
38
#endif /* ! WEXITSTATUS */
 
39
#ifndef WIFEXITED
 
40
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 
41
#endif /* ! WIFEXITED */
 
42
 
 
43
#include <sys/file.h>
 
44
#include <syslog.h>
 
45
#include <atalk/paths.h>
 
46
#include <stdio.h>
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include <ctype.h>
 
50
#include <signal.h>
 
51
#include <errno.h>
 
52
 
 
53
/* Forward Declarations */
 
54
int pexecv(char *path, char *argv[]);
 
55
int copyio();
 
56
int textps();
 
57
 
 
58
char            psapath[] = _PATH_PSA;
 
59
char            *psaargv[] = { "psa", 0, 0, 0, 0 };
 
60
 
 
61
/*
 
62
 * If we're not doing accounting, we just call pap as below.
 
63
 * If we are doing accounting, we call pap twice.  The first time,
 
64
 * we call it with "-E" in arg 2, pagecount.ps in arg 3, and "-" in
 
65
 * arg 4.  The second time, we call it with "-c" in arg 2, pagecount.ps
 
66
 * in arg 3, and 0 in arg 4.
 
67
 */
 
68
char            pappath[] = _PATH_PAP;
 
69
char            *papargv[] = { "pap", "-sstatus", 0, 0, 0, 0, 0, 0 };
 
70
 
 
71
char            revpath[] = _PATH_PSORDER;
 
72
char            *revargv[] = { "psorder", "-d", 0 };
 
73
 
 
74
char            *filtargv[] = { 0, 0, 0 };
 
75
 
 
76
char            inbuf[ 1024 * 8 ];
 
77
int             inlen;
 
78
 
 
79
FILE            *acctfile = NULL;
 
80
int             literal;
 
81
int             width = 80, length = 66, indent = 0;
 
82
char            *prog, *name, *host;
 
83
 
 
84
struct papersize {
 
85
    int         width;
 
86
    int         length;
 
87
   float        win;
 
88
    float       lin;
 
89
} papersizes[] = {
 
90
    { 80, 66, 8.5, 11.0 },                      /* US Letter */
 
91
    { 80, 70, 8.27, 11.69 },                    /* A4 */
 
92
};
 
93
 
 
94
int main( ac, av ) 
 
95
    int         ac;
 
96
    char        **av;
 
97
{
 
98
    int                 c, rc, children = 0;
 
99
#ifdef FUCKED
 
100
    int                 psafileno, multiconn = 0, waitidle = 0, waitidle2 = 0;
 
101
#endif /* FUCKED */
 
102
    int                 status;
 
103
    extern char         *optarg;
 
104
    extern int          optind, opterr;
 
105
 
 
106
    opterr = 0;
 
107
    if (( prog = rindex( av[ 0 ], '/' )) == NULL ) {
 
108
        prog = av[ 0 ];
 
109
    } else {
 
110
        prog++;
 
111
    }
 
112
#ifdef ultrix
 
113
    openlog( prog, LOG_PID );
 
114
#else /* ultrix */
 
115
    openlog( prog, LOG_PID, LOG_LPR );
 
116
#endif /* ultrix */
 
117
 
 
118
    while (( c = getopt( ac, av, "P:C:D:F:L:J:x:y:n:h:w:l:i:c" )) != EOF ) {
 
119
        switch ( c ) {
 
120
        case 'n' :
 
121
            name = optarg;
 
122
            break;
 
123
 
 
124
        case 'h' :
 
125
            host = optarg;
 
126
            break;
 
127
 
 
128
        case 'w' :
 
129
            width = atoi( optarg );
 
130
#ifdef ZEROWIDTH
 
131
            /*
 
132
             * Some version of lpd pass 0 for the page width.
 
133
             */
 
134
            if ( width == 0 ) {
 
135
                width = 80;
 
136
            }
 
137
#endif /* ZEROWIDTH */
 
138
            break;
 
139
 
 
140
        case 'l' :
 
141
            length = atoi( optarg );
 
142
            break;
 
143
 
 
144
        case 'i' :
 
145
            indent = atoi( optarg );
 
146
            break;
 
147
 
 
148
        case 'c' :      /* Print control chars */
 
149
            literal++;
 
150
            break;
 
151
 
 
152
        case 'F' :
 
153
        case 'L' :
 
154
        case 'J' :
 
155
        case 'P' :
 
156
        case 'x' :
 
157
        case 'y' :
 
158
            break;
 
159
        
 
160
#ifdef notdef
 
161
        default :
 
162
            syslog( LOG_ERR, "bad option: %c", c );
 
163
            exit( 2 );
 
164
#endif /* notdef */
 
165
        }
 
166
    }
 
167
    if ( ac - optind > 1 ) {
 
168
        syslog( LOG_ERR, "Too many arguments" );
 
169
        exit( 2 );
 
170
    }
 
171
#ifdef FUCKED
 
172
    if ( index( prog, 'w' )) {
 
173
        waitidle++;
 
174
    }
 
175
    if ( index( prog, 'W' )) {
 
176
        waitidle2++;
 
177
    }
 
178
    if ( index( prog, 'm' )) {
 
179
        multiconn++;
 
180
    }
 
181
#endif /* FUCKED */
 
182
 
 
183
    syslog( LOG_INFO, "starting for %s", name ? name : "?" );
 
184
 
 
185
restart:
 
186
    if (( inlen = read( 0, inbuf, sizeof( inbuf ))) < 0 ) {
 
187
        syslog( LOG_ERR, "read: %s", strerror(errno) );
 
188
        exit( 1 );
 
189
    }
 
190
    if ( inlen == 0 ) { /* nothing to be done */
 
191
        syslog( LOG_INFO, "done" );
 
192
        exit( 0 );
 
193
    }
 
194
 
 
195
    /*
 
196
     * If we've been given an accounting file, start the accounting
 
197
     * process.
 
198
     */
 
199
    if ( optind < ac ) {
 
200
        /* build arguments */
 
201
        psaargv[ 1 ] = av[ optind ];
 
202
        psaargv[ 2 ] = name;
 
203
        psaargv[ 3 ] = host;
 
204
        if (( c = pexecv( psapath, psaargv )) < 0 ) {
 
205
            syslog( LOG_ERR, "%s: %s", psapath, strerror(errno) );
 
206
            exit( 2 );
 
207
        }
 
208
        children++;
 
209
        syslog( LOG_INFO, "accounting with psa[%d]", c );
 
210
    }
 
211
 
 
212
    /*
 
213
     * Check prog's name to decide what programs to execute.
 
214
     */
 
215
    if ( strstr( prog, "pap" ) != NULL ) {
 
216
        if ( optind < ac ) {    /* accounting */
 
217
#ifdef FUCKED
 
218
            if ( multiconn ) {
 
219
                psafileno = getdtablesize();
 
220
                psafileno--;
 
221
                dup2( 1, psafileno );
 
222
 
 
223
                if ( waitidle2 ) {
 
224
                    papargv[ 2 ] = "-W";
 
225
                    papargv[ 3 ] = "-c";
 
226
                    papargv[ 4 ] = "-E";
 
227
                    papargv[ 5 ] = _PATH_PAGECOUNT;
 
228
                    papargv[ 6 ] = "-";
 
229
                    papargv[ 7 ] = 0;
 
230
                } else if ( waitidle ) {
 
231
                    papargv[ 2 ] = "-w";
 
232
                    papargv[ 3 ] = "-c";
 
233
                    papargv[ 4 ] = "-E";
 
234
                    papargv[ 5 ] = _PATH_PAGECOUNT;
 
235
                    papargv[ 6 ] = "-";
 
236
                    papargv[ 7 ] = 0;
 
237
                } else {
 
238
                    papargv[ 2 ] = "-c";
 
239
                    papargv[ 3 ] = "-E";
 
240
                    papargv[ 4 ] = _PATH_PAGECOUNT;
 
241
                    papargv[ 5 ] = "-";
 
242
                    papargv[ 6 ] = 0;
 
243
                }
 
244
            } else {
 
245
                /*
 
246
                 * This is how it should be done.
 
247
                 */
 
248
                papargv[ 2 ] = "-c";
 
249
                papargv[ 3 ] = _PATH_PAGECOUNT;
 
250
                papargv[ 4 ] = "-";
 
251
                papargv[ 5 ] = _PATH_PAGECOUNT;
 
252
                papargv[ 6 ] = 0;
 
253
            }
 
254
#endif /* FUCKED */
 
255
        } else {
 
256
            papargv[ 2 ] = "-c";
 
257
            papargv[ 3 ] = "-E";
 
258
            papargv[ 4 ] = 0;
 
259
        }
 
260
 
 
261
        if (( c = pexecv( pappath, papargv )) < 0 ) {
 
262
            syslog( LOG_ERR, "%s: %s", pappath, strerror(errno) );
 
263
            exit( 2 );
 
264
        }
 
265
        children++;
 
266
        syslog( LOG_INFO, "sending to pap[%d]", c );
 
267
    }
 
268
 
 
269
    /*
 
270
     * Might be a good idea to have both a "forw" and a "rev", so that
 
271
     * reversed documents can be reordered for the printing device.
 
272
     */
 
273
    if ( strstr( prog, "rev" ) != NULL ) {
 
274
        if (( c = pexecv( revpath, revargv )) < 0 ) {
 
275
            syslog( LOG_ERR, "%s: %s", revpath, strerror(errno) );
 
276
            exit( 2 );
 
277
        }
 
278
        syslog( LOG_INFO, "sending to rev[%d]", c );
 
279
        children++;
 
280
    }
 
281
 
 
282
    /*
 
283
     * Invoke an external (script) filter to produce PostScript from
 
284
     * non-text input.
 
285
     */
 
286
    if ( *prog != 'i' && *prog != 'o' && *( prog + 1 ) == 'f' ) {
 
287
        filtargv[ 0 ] = filtargv[ 1 ] = prog;
 
288
        if (( c = pexecv( _PATH_PSFILTER, filtargv )) < 0 ) {
 
289
            syslog( LOG_ERR, "%s: %s", _PATH_PSFILTER, strerror(errno) );
 
290
            exit( 2 );
 
291
        }
 
292
        syslog( LOG_INFO, "external filter[%d]", c );
 
293
        children++;
 
294
        rc = copyio();          /* external filter */
 
295
    } else {
 
296
        if ( inlen >= 2 && inbuf[ 0 ] == '%' && inbuf[ 1 ] == '!' ) {
 
297
            syslog( LOG_INFO, "PostScript" );
 
298
            rc = copyio();      /* PostScript */
 
299
        } else if ( inlen >= 2 && inbuf[ 0 ] == '\033' && inbuf[ 1 ] == '%' ) {
 
300
            syslog( LOG_INFO, "PostScript w/PJL" );
 
301
            rc = copyio();      /* PostScript */
 
302
        } else {
 
303
            syslog( LOG_INFO, "straight text" );
 
304
            rc = textps();      /* straight text */
 
305
        }
 
306
    }
 
307
 
 
308
#ifdef FUCKED
 
309
    if ( strstr( prog, "pap" ) != NULL && optind < ac && multiconn ) {
 
310
        dup2( psafileno, 1 );
 
311
        close( psafileno );
 
312
        papargv[ 2 ] = "-c";
 
313
        if ( waitidle2 ) {
 
314
            papargv[ 3 ] = "-W";
 
315
            papargv[ 4 ] = _PATH_PAGECOUNT;
 
316
            papargv[ 5 ] = 0;
 
317
        } else if ( waitidle ) {
 
318
            papargv[ 3 ] = "-w";
 
319
            papargv[ 4 ] = _PATH_PAGECOUNT;
 
320
            papargv[ 5 ] = 0;
 
321
        } else {
 
322
            papargv[ 3 ] = _PATH_PAGECOUNT;
 
323
            papargv[ 4 ] = 0;
 
324
        }
 
325
 
 
326
        if (( c = pexecv( pappath, papargv )) < 0 ) {
 
327
            syslog( LOG_ERR, "%s: %s", pappath, strerror(errno) );
 
328
            exit( 2 );
 
329
        }
 
330
        children++;
 
331
        syslog( LOG_INFO, "pagecount with pap[%d]", c );
 
332
    }
 
333
#endif /* FUCKED */
 
334
 
 
335
    if ( children ) {
 
336
        close( 1 );
 
337
    }
 
338
    while ( children ) {
 
339
        if (( c = wait3( &status, 0, 0 )) < 0 ) {
 
340
            syslog( LOG_ERR, "wait3: %s", strerror(errno) );
 
341
            exit( 1 );
 
342
        }
 
343
        if ( WIFEXITED( status )) {
 
344
#ifndef WEXITSTATUS
 
345
#define WEXITSTATUS(x)  ((x).w_status)
 
346
#endif /* WEXITSTATUS */
 
347
            if ( WEXITSTATUS( status ) != 0 ) {
 
348
                syslog( LOG_ERR, "%d died with %d", c, WEXITSTATUS( status ));
 
349
                exit( WEXITSTATUS( status ));
 
350
            } else {
 
351
                syslog( LOG_INFO, "%d done", c );
 
352
                children--;
 
353
            }
 
354
        } else {
 
355
            syslog( LOG_ERR, "%d died badly", c );
 
356
            exit( 1 );
 
357
        }
 
358
    }
 
359
 
 
360
    if ( rc == 3 ) {
 
361
        syslog( LOG_INFO, "pausing" );
 
362
        kill( getpid(), SIGSTOP );
 
363
        syslog( LOG_INFO, "restarting" );
 
364
        goto restart;
 
365
    }
 
366
 
 
367
    syslog( LOG_INFO, "done" );
 
368
    exit( rc );
 
369
}
 
370
 
 
371
int copyio()
 
372
{
 
373
    /* implement the FSM needed to do the suspend. Note that
 
374
     * the last characters will be \031\001 so don't worry
 
375
     * Fun things: 1. \031\001 should not be written to output device
 
376
     *  2. The \031 can be last char of one read, \001 first of next
 
377
     *      - we need to write \031 if not followed by \001
 
378
     */
 
379
    struct timeval      tv;
 
380
    fd_set              fdset;
 
381
    int                 ctl = 0;
 
382
 
 
383
notdone:
 
384
    do {
 
385
        /*
 
386
         * First, \031 and \001 *must* be the last things in the buffer
 
387
         * (\001 can be the first thing in the next buffer).  There's no
 
388
         * need to scan any of the intervening bytes.  Second, if there's
 
389
         * more input, the escape sequence was bogus, and we should keep
 
390
         * reading.
 
391
         */
 
392
        if ( inlen == 1 ) {
 
393
            if ( ctl == 1 ) {
 
394
                if ( inbuf[ 0 ] == '\001' ) {
 
395
                    ctl = 2;
 
396
                    break;
 
397
                }
 
398
                if ( write( 1, "\031", 1 ) != 1 ) {
 
399
                    syslog( LOG_ERR, "write: %s", strerror(errno) );
 
400
                    return( 1 );
 
401
                }
 
402
                ctl = 0;
 
403
            }
 
404
 
 
405
            if ( inbuf[ 0 ] == '\031' ) {
 
406
                ctl = 1;
 
407
            }
 
408
 
 
409
        } else {
 
410
            if ( ctl == 1 ) {
 
411
                if ( write( 1, "\031", 1 ) != 1 ) {
 
412
                    syslog( LOG_ERR, "write: %s", strerror(errno) );
 
413
                    return( 1 );
 
414
                }
 
415
            }
 
416
            ctl = 0;
 
417
            if ( inbuf[ inlen - 2 ] == '\031' &&
 
418
                    inbuf[ inlen - 1 ] == '\001' ) {
 
419
                ctl = 2;
 
420
            } else if ( inbuf[ inlen - 1 ] == '\031' ) {
 
421
                ctl = 1;
 
422
            }
 
423
        }
 
424
 
 
425
        inlen -= ctl;
 
426
        if (( inlen > 0 ) && ( write( 1, inbuf, inlen ) != inlen )) {
 
427
            syslog( LOG_ERR, "write: %s", strerror(errno) );
 
428
            return( 1 );
 
429
        }
 
430
        if ( ctl == 2 ) {
 
431
            break;
 
432
        }
 
433
    } while (( inlen = read( 0, inbuf, sizeof( inbuf ))) > 0 );
 
434
 
 
435
    if ( ctl == 2 ) {
 
436
        tv.tv_sec = 2;
 
437
        tv.tv_usec = 0;
 
438
        FD_ZERO( &fdset );
 
439
        FD_SET( 0, &fdset );
 
440
        if ( select( 1, &fdset, NULL, NULL, &tv ) != 0 ) {
 
441
            if (( inlen = read( 0, inbuf, sizeof( inbuf ))) > 0 ) {
 
442
                goto notdone;
 
443
            }
 
444
        }
 
445
    }
 
446
 
 
447
    if ( inlen < 0 ) {
 
448
        syslog( LOG_ERR, "read: %s", strerror(errno) );
 
449
        return( 1 );
 
450
    }
 
451
 
 
452
    if ( ctl == 1 ) {
 
453
        if ( write( 1, "\031", 1 ) != 1 ) {
 
454
            syslog( LOG_ERR, "write: %s", strerror(errno) );
 
455
            return( 1 );
 
456
        }
 
457
    } else if ( ctl == 2 ) {
 
458
        return( 3 );
 
459
    }
 
460
    return( 0 );
 
461
}
 
462
 
 
463
char            *font = "Courier";
 
464
int             point = 11;
 
465
 
 
466
char            pspro[] = "\
 
467
/GSV save def                                           % global VM\n\
 
468
/SP {\n\
 
469
        /SV save def                                    % save vmstate\n\
 
470
        dup /H exch def                                 % save font height\n\
 
471
        exch findfont exch scalefont setfont            % select font\n\
 
472
        ( ) stringwidth pop /W exch def                 % save font width\n\
 
473
        0.5 sub 72 mul /CY exch def                     % save start Y\n\
 
474
        pop 0.5 add 72 mul /CX exch def                 % save start X\n\
 
475
        CX CY moveto                                    % make current point\n\
 
476
} bind def\n\
 
477
/S /show load def\n\
 
478
/NL { CX CY H sub dup /CY exch def moveto } bind def\n\
 
479
/CR { CX CY moveto } bind def\n\
 
480
/B { W neg 0 rmoveto}bind def\n\
 
481
/T { W mul 0 rmoveto}bind def\n\
 
482
/EP { SV restore showpage } bind def\n\
 
483
%%EndProlog\n";
 
484
 
 
485
int textps()
 
486
{
 
487
    struct papersize    papersize;
 
488
    int                 state = 0, line = 0, col = 0, npages = 0, rc, i;
 
489
    char                *p, *end;
 
490
 
 
491
#define elements(x)     (sizeof(x)/sizeof((x)[0]))
 
492
    for ( i = 0; i < elements( papersizes ); i++ ) {
 
493
        if ( width == papersizes[ 0 ].width &&
 
494
                length == papersizes[ 0 ].length ) {
 
495
            papersize = papersizes[ i ];
 
496
            break;
 
497
        }
 
498
    }
 
499
    if ( i >= elements( papersizes )) {
 
500
        papersize = papersizes[ 0 ];            /* default */
 
501
    }
 
502
 
 
503
#define ST_AVAIL                (1<<0)
 
504
#define ST_CONTROL              (1<<1)
 
505
#define ST_PAGE                 (1<<2)
 
506
    /*
 
507
     * convert text lines to postscript.
 
508
     * A grungy little state machine. If I was more creative, I could
 
509
     * probably think of a better way of doing this...
 
510
     */
 
511
    do {
 
512
        p = inbuf;
 
513
        end = inbuf + inlen;
 
514
        while ( p < end ) {
 
515
            if (( state & ST_PAGE ) == 0 && *p != '\031' && *p != '\001' ) {
 
516
                if ( npages == 0 ) {
 
517
                    printf( "%%!PS-Adobe-2.0\n%%%%Pages: (atend)\n" );
 
518
                    printf( "%%%%DocumentFonts: %s\n", font );
 
519
                    fflush( stdout );
 
520
 
 
521
                    /* output postscript prologue: */
 
522
                    if ( write( 1, pspro, sizeof( pspro ) - 1 ) !=
 
523
                            sizeof( pspro ) - 1 ) {
 
524
                        syslog( LOG_ERR, "write prologue: %s", strerror(errno) );
 
525
                        return( 1 );
 
526
                    }
 
527
                    if ( name && host ) {
 
528
                        printf( "statusdict /jobname (%s@%s) put\n", name,
 
529
                                host );
 
530
                    }
 
531
                }
 
532
 
 
533
                printf( "%%%%Page: ? %d\n", ++npages );
 
534
                printf( "%d %f %f /%s %d SP\n", indent,
 
535
                        papersize.win, papersize.lin, font, point );
 
536
                state |= ST_PAGE;
 
537
            }
 
538
            if ( state & ST_CONTROL && *p != '\001' ) {
 
539
                /* It is a very bad thing to toss a job because it contains
 
540
                 * unprintable characters.  Instead, we will convert them to
 
541
                 * question marks.  This is adapted from a solution described
 
542
                 * by Werner Eugster <eugster@giub.unibe.ch> on his ApplePrint
 
543
                 * webpage (http://www.giub.unibe.ch/~eugster/appleprint.html).
 
544
                 *
 
545
                 * Note that this is rather ugly code.  The same change is
 
546
                 * applied identically at two different locations in this file.
 
547
                 * It would be better someday to combine the two.
 
548
                */
 
549
                if ( !literal ) {
 
550
                        fprintf( stderr,
 
551
                                "unprintable character (0x%x) converted to ?!\n",
 
552
                                (unsigned char)*p );
 
553
                        putchar( '?' ); /* Replace unprintable char with a question mark. */
 
554
                } else {
 
555
                        printf( "\\%o", (unsigned char)031 );
 
556
                }
 
557
                state &= ~ST_CONTROL;
 
558
                col++;
 
559
            }
 
560
 
 
561
            switch ( *p ) {
 
562
            case '\n' :         /* end of line */
 
563
                if ( state & ST_AVAIL ) {
 
564
                    printf( ")S\n" );
 
565
                    state &= ~ST_AVAIL;
 
566
                }
 
567
                printf( "NL\n" );
 
568
                line++;
 
569
                col = 0;
 
570
                if ( line >= length ) {
 
571
                    printf( "EP\n" );
 
572
                    state &= ~ST_PAGE;
 
573
                    line = 0;
 
574
                }
 
575
                break;
 
576
 
 
577
            case '\r' :         /* carriage return (for overtyping) */
 
578
                if ( state & ST_AVAIL ) {
 
579
                    printf( ")S CR\n" );
 
580
                    state &= ~ST_AVAIL;
 
581
                }
 
582
                col = 0;
 
583
                break;
 
584
 
 
585
            case '\f' :         /* form feed */
 
586
                if ( state & ST_AVAIL ) {
 
587
                    printf( ")S\n" );
 
588
                    state &= ~ST_AVAIL;
 
589
                }
 
590
                printf( "EP\n" );
 
591
                state &= ~ST_PAGE;
 
592
                line = 0;
 
593
                col = 0;
 
594
                break;
 
595
 
 
596
            case '\b' :         /* backspace */
 
597
                /* show line, back up one character */
 
598
                if ( state & ST_AVAIL ) {
 
599
                    printf( ")S\n" );
 
600
                    state &= ~ST_AVAIL;
 
601
                }
 
602
                printf( "B\n" );
 
603
                col--;
 
604
                break;
 
605
 
 
606
            case '\t' :         /* tab */
 
607
                if ( state & ST_AVAIL ) {
 
608
                    printf( ")S\n" );
 
609
                    state &= ~ST_AVAIL;
 
610
                }
 
611
                printf( "%d T\n", 8 - ( col % 8 ));
 
612
                col += 8 - ( col % 8 );
 
613
                break;
 
614
 
 
615
            /*
 
616
             * beginning of lpr control sequence
 
617
             */
 
618
            case '\031' :
 
619
                state |= ST_CONTROL;
 
620
                break;
 
621
 
 
622
            case '\001' :       /* lpr control sequence */
 
623
                if ( state & ST_CONTROL ) {
 
624
                    rc = 3;
 
625
                    goto out;
 
626
                }
 
627
                /* FALLTHROUGH */
 
628
 
 
629
            case '\\' :
 
630
            case ')' :
 
631
            case '(' :
 
632
                if (( state & ST_AVAIL ) == 0 ) {
 
633
                    printf( "(" );
 
634
                    state |= ST_AVAIL;
 
635
                }
 
636
                putchar( '\\' );
 
637
                /* FALLTHROUGH */
 
638
 
 
639
            default :
 
640
                if (( state & ST_AVAIL ) == 0 ) {
 
641
                    printf( "(" );
 
642
                    state |= ST_AVAIL;
 
643
                }
 
644
                if ( !isascii( *p ) || !isprint( *p )) {
 
645
                    if ( !literal ) {
 
646
                        fprintf( stderr,
 
647
                            "unprintable character (0x%x) converted to ?!\n",
 
648
                            (unsigned char)*p );
 
649
                        putchar( '?' ); /* Replace unprintable char with a question mark. */
 
650
                    } else {
 
651
                        printf( "\\%o", (unsigned char)*p );
 
652
                    }
 
653
                } else {
 
654
                    putchar( *p );
 
655
                }
 
656
                col++;
 
657
                break;
 
658
            }
 
659
        p++;
 
660
        }
 
661
    } while (( inlen = read( 0, inbuf, sizeof( inbuf ))) > 0 );
 
662
    if ( inlen < 0 ) {
 
663
        syslog( LOG_ERR, "read: %s", strerror(errno) );
 
664
        return( 1 );
 
665
    }
 
666
    rc = 0;
 
667
 
 
668
out:
 
669
    if ( state & ST_AVAIL ) {
 
670
        printf( ")S\n" );
 
671
        state &= ~ST_AVAIL;
 
672
    }
 
673
 
 
674
    if ( state & ST_PAGE ) {
 
675
        printf( "EP\n" );
 
676
        state &= ~ST_PAGE;
 
677
    }
 
678
 
 
679
    if ( npages > 0 ) {
 
680
        printf( "%%%%Trailer\nGSV restore\n%%%%Pages: %d\n%%%%EOF\n", npages );
 
681
        fflush( stdout );
 
682
    }
 
683
 
 
684
    return( rc );
 
685
}
 
686
 
 
687
/*
 
688
 * Interface to pipe and exec, for starting children in pipelines.
 
689
 *
 
690
 * Manipulates file descriptors 0, 1, and 2, such that the new child
 
691
 * is reading from the parent's output.
 
692
 */
 
693
int pexecv( path, argv )
 
694
    char        *path, *argv[];
 
695
{
 
696
    int         fd[ 2 ], c;
 
697
 
 
698
    if ( pipe( fd ) < 0 ) {
 
699
        return( -1 );
 
700
    }
 
701
 
 
702
    switch ( c = fork()) {
 
703
    case -1 :
 
704
        return( -1 );
 
705
        /* NOTREACHED */
 
706
 
 
707
    case 0 :
 
708
        if ( close( fd[ 1 ] ) < 0 ) {
 
709
            return( -1 );
 
710
        }
 
711
        if ( dup2( fd[ 0 ], 0 ) < 0 ) {
 
712
            return( -1 );
 
713
        }
 
714
        if ( close( fd[ 0 ] ) < 0 ) {
 
715
            return( -1 );
 
716
        }
 
717
        execv( path, argv );
 
718
        return( -1 );
 
719
        /* NOTREACHED */
 
720
 
 
721
    default :
 
722
        if ( close( fd[ 0 ] ) < 0 ) {
 
723
            return( -1 );
 
724
        }
 
725
        if ( dup2( fd[ 1 ], 1 ) < 0 ) {
 
726
            return( -1 );
 
727
        }
 
728
        if ( close( fd[ 1 ] ) < 0 ) {
 
729
            return( -1 );
 
730
        }
 
731
        return( c );
 
732
    }
 
733
}