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 31int 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} 133