]> arthur.barton.de Git - netatalk.git/blob - etc/psf/psa.c
merge papd changes from HEAD
[netatalk.git] / etc / psf / psa.c
1 /*
2  * $Id: psa.c,v 1.4 2001-06-25 20:13:45 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1995 Regents of The University of Michigan.
5  * All Rights Reserved. See COPYRIGHT.
6  *
7  * PostScript Accounting, psa.
8  *
9  * psa is invoked by psf, as output for a communication program.  The
10  * communication program is expected to send a small program before and
11  * after each job, which causes the page count to be emitted in a well
12  * known format.  psa reads its input, looking for page counts and other
13  * interesting data.  Any data that it doesn't understand, it emits to
14  * stderr, the lpd log file.  Data that it does understand may be written
15  * to a status file or logged.  Once all input has been received, psa
16  * subtracts the beginning and end page counts, and log an accounting
17  * record in the accounting file.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif /* HAVE_CONFIG_H */
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif /* HAVE_UNISTD_H */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 int main( ac, av )
32     int         ac;
33     char        **av;
34 {
35     FILE        *af;
36     char        *acc, *user, *host;
37     char        buf[ 1024 ], *p, *end;
38     int         cc, n, ipc = -1, fpc = -1;
39
40     if ( ac != 4 ) {
41         fprintf( stderr, "Usage:\t%s accounting-file user host\n", av[ 0 ] );
42         exit( 2 );
43     }
44
45     acc = av[ 1 ];
46     user = av[ 2 ];
47     host = av[ 3 ];
48
49     /*
50      * Explain n = !n ...  Is there no beauty in truth?
51      */
52     while (( cc = read( 0, buf, sizeof( buf ))) > 0 ) {
53         if ( ipc < 0 && *buf == '*' ) {
54             /* find initial pagecount */
55             for ( p = buf, end = buf + cc; p < end; p++ ) {
56                 if ( *p == '\n' || *p == '\r' ) {
57                     break;
58                 }
59             }
60             if ( p == end ) {
61                 fprintf( stderr, "Can't find initial page count!\n" );
62                 exit( 2 );
63             }
64
65             p++;
66             ipc = atoi( buf + 1 );
67             cc -= ( p - buf );
68             if ( cc != 0 ) {
69                 bcopy( p, buf, cc );
70             }
71         } else {
72             /* find final pagecount */
73             for ( p = buf + cc - 1; p >= buf; p-- ) {
74                 if ( *p != '\n' && *p != '\r' ) {
75                     break;
76                 }
77             }
78             if ( p < buf ) {
79                 fprintf( stderr, "Can't find final page count!\n" );
80                 exit( 2 );
81             }
82
83             for ( ; p >= buf; p-- ) {
84                 if ( *p == '\n' || *p == '\r' ) {
85                     break;
86                 }
87             }
88
89             if ( p < buf ) {
90                 p = buf;
91             } else {
92                 cc -= p - buf;
93                 p++;
94             }
95
96             if ( *p == '*' ) {
97                 n = atoi( p + 1 );
98 #define max(x,y)        ((x)>(y)?(x):(y))
99                 fpc = max( n, fpc );
100             }
101         }
102         if ( cc != 0 && write( 2, buf, cc ) != cc ) {
103             fprintf( stderr, "write 1: 2 %p %d\n", buf, cc );
104             perror( "write" );
105             exit( 2 );
106         }
107     }
108     if ( cc < 0 ) {
109         perror( "read" );
110         exit( 2 );
111     }
112
113     if ( ipc < 0 ) {
114         fprintf( stderr, "Didn't find initial page count!\n" );
115         exit( 2 );
116     }
117
118     if ( fpc < 0 ) {
119         fprintf( stderr, "Didn't find final page count!\n" );
120         exit( 2 );
121     }
122
123     /*
124      * Write accounting record.
125      */
126     if (( af = fopen( acc, "a" )) != NULL ) {
127         fprintf( af, "%7.2f\t%s:%s\n", (float)( fpc - ipc ), host, user );
128     } else {
129         perror( acc );
130         exit( 2 );
131     }
132
133     exit( 0 );
134 }