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