]> arthur.barton.de Git - netatalk.git/blob - bin/psorder/psorder.c
Warning fixes.
[netatalk.git] / bin / psorder / psorder.c
1 /*
2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
3  * All Rights Reserved.
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both that copyright notice and this permission notice appear
9  * in supporting documentation, and that the name of The University
10  * of Michigan not be used in advertising or publicity pertaining to
11  * distribution of the software without specific, written prior
12  * permission. This software is supplied as is without expressed or
13  * implied warranties of any kind.
14  *
15  *      Research Systems Unix Group
16  *      The University of Michigan
17  *      c/o Mike Clark
18  *      535 W. William Street
19  *      Ann Arbor, Michigan
20  *      +1-313-763-0525
21  *      netatalk@itd.umich.edu
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/stat.h>
33 #include <sys/uio.h>
34 #include <sys/file.h>
35 #include <ctype.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <dirent.h>
40 #include <unistd.h>
41 #include "pa.h"
42 #include "psorder.h"
43
44 #include <atalk/paths.h>
45
46 /*
47  *                      Global Variables
48  */
49
50 u_char                  psbuf[ 8192 ];
51 struct psinfo_st        psinfo;
52 int                     orderflag, forceflag;
53
54 int main( argc, argv )
55     int         argc;
56     char        **argv;
57 {
58     extern int  optind;
59     char        *progname;
60     int         errflag = 0;
61     int         c;
62
63     while (( c = getopt( argc, argv, OPTSTR )) != -1 ) {
64         switch ( c ) {
65         case REVCHAR:
66             if ( orderflag ) errflag++;
67             else orderflag = REVERSE;
68             break;
69         case FORWCHAR:
70             if ( orderflag ) errflag++;
71             else orderflag = FORWARD;
72             break;
73         case FORCECHAR:
74             if ( forceflag ) errflag++;
75             else forceflag++;
76             break;
77         }
78     }
79     if ( errflag ) {
80         if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
81             progname = argv[ 0 ];
82         } else progname++;
83         fprintf( stderr, "usage: %s [-duf] [sourcefile]\n", progname );
84         return( -1 );
85     } else if ( !orderflag ) orderflag = FORWARD;
86
87     if ( optind >= argc ) {
88         return( psorder( STDIN ));
89     }
90     return( psorder( argv[ optind ] ));
91 }
92
93 int
94 psorder( path )
95     char        *path;
96 {
97     int                 tempfd;
98     int                 inputfd;
99     char                tempfile[MAXNAMLEN];
100
101     filesetup( path, &inputfd, tempfile, &tempfd );
102     readps( inputfd, tempfd, tempfile );
103     if ( lseek( tempfd, REWIND, SEEK_SET ) < 0 ) {
104         perror( tempfile );
105         filecleanup( -1, tempfd, tempfile );
106     }
107     writeps( tempfd, tempfile );
108     filecleanup( 0, tempfd, tempfile );
109     return( 0 );
110 }
111
112 void
113 filesetup( inputfile, infd, tfile, tfd )
114     char        *inputfile;
115     int         *infd;
116     char        *tfile;
117     int         *tfd;
118 {
119     struct stat         st;
120     char                *template = _PATH_TMPPAGEORDER;
121
122     if ( strcmp( inputfile, STDIN ) != 0 ) {
123         if ( stat( inputfile, &st ) < 0 ) {
124             perror( inputfile );
125             filecleanup( -1, -1, "" );
126         }
127         if ( st.st_mode & S_IFMT & S_IFDIR ) {
128             fprintf( stderr, "%s is a directory.\n", inputfile );
129             filecleanup( 0, -1, "" );
130         }
131         if (( *infd = open( inputfile, O_RDONLY, 0600 )) < 0 ) {
132             perror( inputfile );
133             filecleanup( -1, -1, "" );
134         }
135     } else {
136         *infd = 0;
137     }
138
139 #if DEBUG
140     fprintf( stderr, "Input file or stdin and stdout opened.\n" );
141     fprintf( stderr, "Input file descriptor is %d .\n", *infd );
142 #endif
143
144 /*
145         make temporary file
146  */
147
148     (void *)strncpy( tfile, template, MAXNAMLEN );
149     if (( *tfd = mkstemp( tfile )) == -1 ) {
150         fprintf( stderr, "can't create temporary file %s\n", tfile );
151         filecleanup( -1, -1, "" );
152     }
153
154 #if DEBUG
155     fprintf( stderr, "Temporary file %s created and opened.\n", tfile );
156     fprintf( stderr, "Temporary file descriptor is %d .\n", *tfd );
157 #endif
158
159     psinfo.firstpage = NULL;
160     psinfo.lastpage = NULL;
161     psinfo.trailer = 0;
162     psinfo.pages.offset = 0;
163     psinfo.pages.end = 0;
164     psinfo.pages.num[0] = '\0';
165     psinfo.pages.order[0] = '\0';
166
167     return;
168 }
169
170 void
171 readps( inputfd, tempfd, tempfile )
172     int                 inputfd;
173     int                 tempfd;
174     char                *tempfile;
175 {
176     off_t               ccread = 0;
177     off_t               ccmatch;
178     char                *curtok = 0;
179     FILE                *tempstream;
180     pa_buf_t            *pb;
181     int                 n;
182     char                c = -1;
183     char                pc, cc = 0;
184
185     pb = pa_init( inputfd );
186     if (( tempstream = fdopen( tempfd, "w" )) == NULL ) {
187         perror( "fdopen fails for tempfile" );
188         filecleanup( -1, tempfd, tempfile );
189     }
190
191     if (( c = pa_getchar( pb )) != 0 ) {
192         ccread++;
193         (void)putc( c, tempstream );
194         pc = 0;
195         cc = c;
196         pa_match( pb );
197         n = strlen( PPSADOBE );
198         for ( ; ( n > 0 ) && (( c = pa_getchar( pb )) != 0 ) ; n-- ) {
199             ccread++ ;
200             (void)putc( c, tempstream );
201             pc = cc;
202             cc = c;
203         }
204         curtok = pa_gettok( pb );
205     }
206 #if DEBUG
207     fprintf( stderr, "%s\n", curtok );
208 #endif
209
210 /*
211  * not postscript
212  */
213     if ( strcmp( curtok, PPSADOBE ) != 0 ) {
214 #if DEBUG
215     fprintf( stderr, "in the not postscript section of readps\n" );
216 #endif
217         while (( c = pa_getchar( pb )) != 0 ) {
218             ccread++;
219             (void)putc( c, tempstream );
220             pc = cc;
221             cc = c;
222         }
223
224         (void)fflush( tempstream );
225         return;
226     }
227
228 /*
229  * postscript
230  */
231 #if DEBUG
232     fprintf( stderr, "in the postscript section of readps\n" );
233 #endif
234     while (( c = pa_getchar( pb )) != 0 ) {
235         ccread++;
236         (void)putc( c, tempstream );
237         pc = cc;
238         cc = c;
239         if ((( pc == '\r' ) || ( pc == '\n' )) && ( cc == '%' )) {
240 #if DEBUG
241             fprintf( stderr, "supposed start of match, cc = %c\n", cc );
242 #endif
243             pa_match( pb );
244             ccmatch = ccread - 1;
245             while ( ( c = pa_getchar( pb ) ) ) {
246                 if ( c != 0 ) {
247                     ccread++;
248                     (void)putc( c, tempstream );
249                     pc = cc;
250                     cc = c;
251                 }
252                 if (( c == '\r' ) || ( c == '\n' ) || ( cc == '\0' )) {
253                     curtok = pa_gettok( pb );
254 #if DEBUG
255                     fprintf( stderr, "%s\n", curtok );
256 #endif
257                     if ( handletok( ccmatch, curtok ) < 0 ) {
258                         perror( "malloc died" );
259                         filecleanup( -1, tempfd, tempfile );
260                     }
261                     break;
262                 }
263                 if ( c == 0 ) break;
264             }
265             if ( c == 0 ) break;
266         }
267     }
268
269     (void)fflush( tempstream );
270     return;
271 }
272
273 int
274 handletok( count, token )
275     off_t               count;
276     char                *token;
277 {
278     int                 incdoc = 0;
279     struct pspage_st    *newpage;
280     char                *tmp;
281
282     if (( strncmp( PENDDOC, token, strlen( PENDDOC )) == 0 ) && incdoc ) {
283         incdoc--;
284 #if DEBUG
285         fprintf( stderr, "found an EndDoc\n" );
286 #endif
287
288     } else if ( strncmp( PBEGINDOC, token, strlen( PBEGINDOC )) == 0 ) {
289         incdoc++;
290 #if DEBUG
291         fprintf( stderr, "found a BeginDoc\n" );
292 #endif
293
294     } else if ( !incdoc && 
295             ( strncmp( PPAGE, token, strlen( PPAGE )) == 0 )) {
296 #if DEBUG
297         fprintf( stderr, "found a Page\n" );
298 #endif
299         if (( newpage = getpspage( count )) == NULL ) {
300             return( -1 );
301         }
302         if ( psinfo.firstpage == NULL ) {
303             newpage->prevpage = NULL;
304             psinfo.firstpage = newpage;
305         } else {
306             newpage->prevpage = psinfo.lastpage;
307             psinfo.lastpage->nextpage = newpage;
308         }
309         psinfo.lastpage = newpage;
310         while ( *token++ != ':' );
311         if (( tmp = strtok( token, WHITESPACE )) != NULL ) {
312             (void)strncpy( newpage->lable, tmp, NUMLEN );
313             if (( tmp = strtok( NULL, WHITESPACE )) != NULL ) {
314                 (void)strncpy( newpage->ord, tmp, ORDLEN );
315             }
316         }
317 #if DEBUG
318         fprintf( stderr, "page lable %s, page ord %s\n", newpage->lable,
319                 newpage->ord );
320 #endif
321
322     } else if ( !incdoc && 
323             ( strncmp( PPAGES, token, strlen( PPAGES )) == 0 )) {
324 #if DEBUG
325         fprintf( stderr, "found a Pages\n" );
326 #endif
327         psinfo.pages.offset = count;
328         psinfo.pages.end = strlen( token ) + count;
329         while ( *token++ != ':' );
330         while ( isspace( *token )) token++;
331         if ( strncmp( ATEND, token, strlen( ATEND )) == 0 ) {
332 #if DEBUG
333             fprintf( stderr, "it is a Pages: (atend)\n" );
334 #endif
335             psinfo.pages.offset = 0;
336             psinfo.pages.end = 0;
337         } else {
338             if (( tmp = strtok( token, WHITESPACE )) != NULL ) {
339                 (void)strncpy( psinfo.pages.num, tmp, NUMLEN );
340                 if (( tmp = strtok( NULL, WHITESPACE )) != NULL ) {
341                     (void)strncpy( psinfo.pages.order, tmp, ORDERLEN );
342                 }
343             }
344 #if DEBUG
345             fprintf( stderr, "number of pages %s\n", psinfo.pages.num );
346             fprintf( stderr, "order control number %s\n", psinfo.pages.order );
347 #endif
348         }
349
350     } else if ( !incdoc && 
351             ( strncmp( PTRAILER, token, strlen( PTRAILER )) == 0 )) {
352 #if DEBUG
353         fprintf( stderr, "found the Trailer\n" );
354 #endif
355         if  ( psinfo.trailer == 0 ) {
356             psinfo.trailer = count;
357         }
358     }
359
360     return( 0 );
361 }
362
363 void
364 writeps( tempfd, tempfile )
365     int                 tempfd;
366     char                *tempfile;
367 {
368     struct stat         st;
369     off_t               endofpage;
370     int                 order;
371
372     if ( stat( tempfile, &st ) < 0 ) {
373         perror( "stat failed" );
374         filecleanup( -1, tempfd, tempfile );
375     }
376     if ( psinfo.trailer == 0 ) {
377         endofpage = st.st_size;
378     } else endofpage = psinfo.trailer;
379
380     if (( psinfo.firstpage == NULL ) || 
381             ( psinfo.firstpage == psinfo.lastpage )) {
382         order = FORWARD;
383     } else if ( psinfo.pages.offset == 0 ) {
384         order = orderflag;
385     } else if (( strncmp( psinfo.pages.order, "", ORDERLEN ) == 0 ) ||
386             ( strncmp( psinfo.pages.order, "1", ORDERLEN ) == 0 )) {
387         order = orderflag;
388         if ( order == REVERSE ) strcpy( psinfo.pages.order, "-1" );
389     } else if ( strncmp( psinfo.pages.order, "-1", ORDERLEN ) == 0 ) {
390         if ( orderflag == FORWARD ) {
391             order = REVERSE;
392             strcpy( psinfo.pages.order, "1" );
393         } else order = FORWARD;
394     } else if (( strncmp( psinfo.pages.order, "0", ORDERLEN ) == 0 ) &&
395             forceflag ) {
396         order = orderflag;
397     } else order = FORWARD;
398
399     if ( order == FORWARD ) {
400         temp2out( tempfd, tempfile, st.st_size );
401     } else {
402 /*
403  *      output the header stuff and rewrite the $$Pages line
404  *      if it is in the header and not %%Pages: (atend)
405  */
406         if ( psinfo.firstpage->offset > 0 ) {
407             if (( psinfo.firstpage->offset > psinfo.pages.offset ) &&
408                     ( psinfo.pages.offset != 0 )) {
409                 temp2out( tempfd, tempfile, psinfo.pages.offset );
410                 writelable( tempfd, tempfile, PPAGES );
411                 if ( lseek( tempfd, psinfo.pages.end, SEEK_SET ) < 0 ) {
412                     perror( tempfile );
413                     filecleanup( -1, tempfd, tempfile );
414                 }
415                 temp2out( tempfd, tempfile, 
416                         psinfo.firstpage->offset - psinfo.pages.end );
417             } else temp2out( tempfd, tempfile, psinfo.firstpage->offset );
418         }
419 /*
420  *      output the pages, last to first
421  */
422         while ( psinfo.lastpage != NULL ) {
423             if ( lseek( tempfd, psinfo.lastpage->offset, SEEK_SET ) < 0 ) {
424                 perror( tempfile );
425                 filecleanup( -1, tempfd, tempfile );
426             }
427             temp2out( tempfd, tempfile, endofpage - psinfo.lastpage->offset );
428             endofpage = psinfo.lastpage->offset;
429             psinfo.lastpage = psinfo.lastpage->prevpage;
430             if ( psinfo.lastpage != NULL ) {
431                 (void)free( psinfo.lastpage->nextpage );
432                 psinfo.lastpage->nextpage = NULL;
433             }
434         }
435 /*
436  *      output the trailer stuff and rewrite the $$Pages line
437  *      if it is in the trailer
438  */
439         if ( psinfo.trailer != 0 ) {
440             if ( lseek( tempfd, psinfo.trailer, SEEK_SET ) < 0 ) {
441                 perror( tempfile );
442                 filecleanup( -1, tempfd, tempfile );
443             }
444             if ( psinfo.trailer < psinfo.pages.offset ) {
445                 temp2out( tempfd, tempfile,
446                         psinfo.pages.offset - psinfo.trailer );
447                 writelable( tempfd, tempfile, PPAGES );
448                 if ( lseek( tempfd, psinfo.pages.end, SEEK_SET ) < 0 ) {
449                     perror( tempfile );
450                     filecleanup( -1, tempfd, tempfile );
451                 }
452                 temp2out( tempfd, tempfile, st.st_size - psinfo.pages.end );
453             } else temp2out( tempfd, tempfile, st.st_size - psinfo.trailer );
454         }
455     }
456
457     return;
458 }
459
460 void
461 writelable( tempfd, tempfile, lable )
462     int                 tempfd;
463     char                *tempfile;
464     char                *lable;
465 {
466     char                line[256];
467     int                 ccwrite;
468     int                 linelen;
469     char                *argone;
470     char                *argtwo;
471
472     if ( strcmp( lable, PPAGES ) == 0 ) {
473         argone = psinfo.pages.num;
474         argtwo = psinfo.pages.order;
475     } else {
476         argone = argtwo = NULL;
477     }
478     (void)sprintf( line, "%s %s %s", lable, argone, argtwo );
479     linelen = strlen( line );
480
481     ccwrite = write( 1, line, linelen );
482     if ( ccwrite < 0 ) {
483         perror( "stdout" );
484         filecleanup( ccwrite, tempfd, tempfile );
485     } else {
486         linelen -= ccwrite;
487     }
488 }
489
490 void
491 temp2out( tempfd, tempfile, length )
492     int                 tempfd;
493     char                *tempfile;
494     off_t               length;
495 {
496     int                 ccread;
497     int                 ccwrite;
498     int                 size;
499
500     while ( length > 0 ) {
501         if ( length > sizeof( psbuf )) {
502             size = sizeof( psbuf );
503         } else size = length;
504         if (( ccread = read( tempfd, psbuf, size )) > 0 ) {
505             size = ccread;
506             while ( ccread > 0 ) {
507                 ccwrite = write( 1, psbuf, ccread );
508                 if ( ccwrite < 0 ) {
509                     perror( "stdout" );
510                     filecleanup( ccwrite, tempfd, tempfile );
511                 } else {
512                     ccread -= ccwrite;
513                 }
514             }
515         }
516         if ( ccread < 0 ) {
517             perror( "temporary file" );
518             filecleanup( ccread, tempfd, tempfile );
519         }
520         length -= size;
521     }
522 }
523
524 struct pspage_st
525 *getpspage( off )
526     off_t               off;
527 {
528     struct pspage_st    *newpspage;
529
530     newpspage = (struct pspage_st *)malloc( sizeof( struct pspage_st )); 
531     if ( newpspage != NULL ) {
532         newpspage->offset = off;
533         newpspage->nextpage = NULL;
534         *newpspage->lable = '\0';
535         *newpspage->ord = '\0';
536     }
537     return( newpspage );
538 }
539
540 void
541 filecleanup( errorcode, tfd, tfile )
542     int                 errorcode;
543     int                 tfd;
544     char                *tfile;
545 {
546
547 /*
548         Close and unlink the temporary file.
549  */
550
551     if ( tfd != 0 ) {
552         if ( close( tfd ) != 0 ) {
553             perror( tfile );
554             exit( errorcode );
555         }
556         if ( unlink( tfile ) != 0 ) {
557             perror( tfile );
558             exit( errorcode );
559         }
560     }
561
562     exit( errorcode );
563 }