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