]> arthur.barton.de Git - netatalk.git/blob - etc/psf/psa.c
2606a7c51060d5be82169b1ca30520951dd165db
[netatalk.git] / etc / psf / psa.c
1 /*
2  * $Id: psa.c,v 1.5 2009-10-13 22:55:37 didg 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( int ac, char **av)
32 {
33     FILE        *af;
34     char        *acc, *user, *host;
35     char        buf[ 1024 ], *p, *end;
36     int         cc, n, ipc = -1, fpc = -1;
37
38     if ( ac != 4 ) {
39         fprintf( stderr, "Usage:\t%s accounting-file user host\n", av[ 0 ] );
40         exit( 2 );
41     }
42
43     acc = av[ 1 ];
44     user = av[ 2 ];
45     host = av[ 3 ];
46
47     /*
48      * Explain n = !n ...  Is there no beauty in truth?
49      */
50     while (( cc = read( 0, buf, sizeof( buf ))) > 0 ) {
51         if ( ipc < 0 && *buf == '*' ) {
52             /* find initial pagecount */
53             for ( p = buf, end = buf + cc; p < end; p++ ) {
54                 if ( *p == '\n' || *p == '\r' ) {
55                     break;
56                 }
57             }
58             if ( p == end ) {
59                 fprintf( stderr, "Can't find initial page count!\n" );
60                 exit( 2 );
61             }
62
63             p++;
64             ipc = atoi( buf + 1 );
65             cc -= ( p - buf );
66             if ( cc != 0 ) {
67                 bcopy( p, buf, cc );
68             }
69         } else {
70             /* find final pagecount */
71             for ( p = buf + cc - 1; p >= buf; p-- ) {
72                 if ( *p != '\n' && *p != '\r' ) {
73                     break;
74                 }
75             }
76             if ( p < buf ) {
77                 fprintf( stderr, "Can't find final page count!\n" );
78                 exit( 2 );
79             }
80
81             for ( ; p >= buf; p-- ) {
82                 if ( *p == '\n' || *p == '\r' ) {
83                     break;
84                 }
85             }
86
87             if ( p < buf ) {
88                 p = buf;
89             } else {
90                 cc -= p - buf;
91                 p++;
92             }
93
94             if ( *p == '*' ) {
95                 n = atoi( p + 1 );
96 #define max(x,y)        ((x)>(y)?(x):(y))
97                 fpc = max( n, fpc );
98             }
99         }
100         if ( cc != 0 && write( 2, buf, cc ) != cc ) {
101             fprintf( stderr, "write 1: 2 %p %d\n", buf, cc );
102             perror( "write" );
103             exit( 2 );
104         }
105     }
106     if ( cc < 0 ) {
107         perror( "read" );
108         exit( 2 );
109     }
110
111     if ( ipc < 0 ) {
112         fprintf( stderr, "Didn't find initial page count!\n" );
113         exit( 2 );
114     }
115
116     if ( fpc < 0 ) {
117         fprintf( stderr, "Didn't find final page count!\n" );
118         exit( 2 );
119     }
120
121     /*
122      * Write accounting record.
123      */
124     if (( af = fopen( acc, "a" )) != NULL ) {
125         fprintf( af, "%7.2f\t%s:%s\n", (float)( fpc - ipc ), host, user );
126     } else {
127         perror( acc );
128         exit( 2 );
129     }
130
131     exit( 0 );
132 }