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