source: trunk/athena/bin/lpr/pac.c @ 7908

Revision 7908, 8.1 KB checked in by miki, 29 years ago (diff)
replaced index with strchr
Line 
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.  The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
13#ifndef lint
14static char sccsid[] = "@(#)pac.c       5.2 (Berkeley) 10/30/85";
15#endif not lint
16
17/*
18 * Do Printer accounting summary.
19 * Currently, usage is
20 *      pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...]
21 * to print the usage information for the named people.
22 */
23
24/* Currently "pac" runs only off information in /etc/printcap.
25 * If you want it to query Hesiod, #define HESIOD-PAC here.
26 */
27
28#include <stdio.h>
29#include <strings.h>
30#include "lp.local.h"
31
32char    *printer;                       /* printer name */
33char    *acctfile;                      /* accounting file (input data) */
34char    *sumfile;                       /* summary file */
35float   price = 0.02;                   /* cost per page (or what ever) */
36int     allflag = 1;                    /* Get stats on everybody */
37int     sort;                           /* Sort by cost */
38int     summarize;                      /* Compress accounting file */
39int     reverse;                        /* Reverse sort order */
40int     hcount;                         /* Count of hash entries */
41int     errs;
42int     mflag = 0;                      /* disregard machine names */
43int     pflag = 0;                      /* 1 if -p on cmd line */
44int     price100;                       /* per-page cost in 100th of a cent */
45int     pgetnum();
46#ifdef HESIOD_PAC
47char    alibuf[BUFSIZ/2];               /* buffer for printer alias */
48#endif /* HESIOD-PAC */
49
50/*
51 * Grossness follows:
52 *  Names to be accumulated are hashed into the following
53 *  table.
54 */
55
56#define HSHSIZE 97                      /* Number of hash buckets */
57
58struct hent {
59        struct  hent *h_link;           /* Forward hash link */
60        char    *h_name;                /* Name of this user */
61        float   h_feetpages;            /* Feet or pages of paper */
62        int     h_count;                /* Number of runs */
63};
64
65struct  hent    *hashtab[HSHSIZE];      /* Hash table proper */
66struct  hent    *enter();
67struct  hent    *lookup();
68
69#define NIL     ((struct hent *) 0)     /* The big zero */
70
71double  atof();
72char    *getenv();
73char    *pgetstr();
74
75main(argc, argv)
76        char **argv;
77{
78        register FILE *acct;
79        register char *cp;
80
81        while (--argc) {
82                cp = *++argv;
83                if (*cp++ == '-') {
84                        switch(*cp++) {
85                        case 'P':
86                                /*
87                                 * Printer name.
88                                 */
89                                printer = cp;
90                                continue;
91
92                        case 'p':
93                                /*
94                                 * get the price.
95                                 */
96                                price = atof(cp);
97                                pflag = 1;
98                                continue;
99
100                        case 's':
101                                /*
102                                 * Summarize and compress accounting file.
103                                 */
104                                summarize++;
105                                continue;
106
107                        case 'c':
108                                /*
109                                 * Sort by cost.
110                                 */
111                                sort++;
112                                continue;
113
114                        case 'm':
115                                /*
116                                 * disregard machine names for each user
117                                 */
118                                mflag = 1;
119                                continue;
120
121                        case 'r':
122                                /*
123                                 * Reverse sorting order.
124                                 */
125                                reverse++;
126                                continue;
127
128                        default:
129fprintf(stderr,
130    "usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n");
131                                exit(1);
132                        }
133                }
134                (void) enter(--cp);
135                allflag = 0;
136        }
137        if (printer == NULL) {
138          if ((printer = getenv("PRINTER")) == NULL) printer = DEFLP;
139        }
140        if (!chkprinter()) {
141                printf("pac: unknown printer %s\n", printer);
142                exit(2);
143        }
144
145        if ((acct = fopen(acctfile, "r")) == NULL) {
146                perror(acctfile);
147                exit(1);
148        }
149        account(acct);
150        fclose(acct);
151        if ((acct = fopen(sumfile, "r")) != NULL) {
152                account(acct);
153                fclose(acct);
154        }
155        if (summarize)
156                rewrite();
157        else
158                dumpit();
159        exit(errs);
160}
161
162/*
163 * Read the entire accounting file, accumulating statistics
164 * for the users that we have in the hash table.  If allflag
165 * is set, then just gather the facts on everyone.
166 * Note that we must accomodate both the active and summary file
167 * formats here.
168 * Host names are ignored if the -m flag is present.
169 */
170
171account(acct)
172        register FILE *acct;
173{
174        char linebuf[BUFSIZ];
175        double t;
176        register char *cp, *cp2;
177        register struct hent *hp;
178        register int ic;
179
180        while (fgets(linebuf, BUFSIZ, acct) != NULL) {
181                cp = linebuf;
182                while (any(*cp, " t\t"))
183                        cp++;
184                t = atof(cp);
185                while (any(*cp, ".0123456789"))
186                        cp++;
187                while (any(*cp, " \t"))
188                        cp++;
189                for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
190                        ;
191                ic = atoi(cp2);
192                *cp2 = '\0';
193                if (mflag && strchr(cp, ':'))
194                    cp = strchr(cp, ':') + 1;
195                hp = lookup(cp);
196                if (hp == NIL) {
197                        if (!allflag)
198                                continue;
199                        hp = enter(cp);
200                }
201                hp->h_feetpages += t;
202                if (ic)
203                        hp->h_count += ic;
204                else
205                        hp->h_count++;
206        }
207}
208
209/*
210 * Sort the hashed entries by name or footage
211 * and print it all out.
212 */
213
214dumpit()
215{
216        struct hent **base;
217        register struct hent *hp, **ap;
218        register int hno, c, runs;
219        float feet;
220        int qucmp();
221
222        hp = hashtab[0];
223        hno = 1;
224        base = (struct hent **) calloc(sizeof hp, hcount);
225        for (ap = base, c = hcount; c--; ap++) {
226                while (hp == NIL)
227                        hp = hashtab[hno++];
228                *ap = hp;
229                hp = hp->h_link;
230        }
231        qsort(base, hcount, sizeof hp, qucmp);
232        printf("  Login               pages/feet   runs    price\n");
233        feet = 0.0;
234        runs = 0;
235        for (ap = base, c = hcount; c--; ap++) {
236                hp = *ap;
237                runs += hp->h_count;
238                feet += hp->h_feetpages;
239                printf("%-24s %7.2f %4d   $%6.2f\n", hp->h_name,
240                    hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
241        }
242        if (allflag) {
243                printf("\n");
244                printf("%-24s %7.2f %4d   $%6.2f\n", "total", feet,
245                    runs, feet * price);
246        }
247}
248
249/*
250 * Rewrite the summary file with the summary information we have accumulated.
251 */
252
253rewrite()
254{
255        register struct hent *hp;
256        register int i;
257        register FILE *acctf;
258
259        if ((acctf = fopen(sumfile, "w")) == NULL) {
260                perror(sumfile);
261                errs++;
262                return;
263        }
264        for (i = 0; i < HSHSIZE; i++) {
265                hp = hashtab[i];
266                while (hp != NULL) {
267                        fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
268                            hp->h_name, hp->h_count);
269                        hp = hp->h_link;
270                }
271        }
272        fflush(acctf);
273        if (ferror(acctf)) {
274                perror(sumfile);
275                errs++;
276        }
277        fclose(acctf);
278        if ((acctf = fopen(acctfile, "w")) == NULL)
279                perror(acctfile);
280        else
281                fclose(acctf);
282}
283
284/*
285 * Hashing routines.
286 */
287
288/*
289 * Enter the name into the hash table and return the pointer allocated.
290 */
291
292struct hent *
293enter(name)
294        char name[];
295{
296        register struct hent *hp;
297        register int h;
298
299        if ((hp = lookup(name)) != NIL)
300                return(hp);
301        h = hash(name);
302        hcount++;
303        hp = (struct hent *) calloc(sizeof *hp, 1);
304        hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1);
305        strcpy(hp->h_name, name);
306        hp->h_feetpages = 0.0;
307        hp->h_count = 0;
308        hp->h_link = hashtab[h];
309        hashtab[h] = hp;
310        return(hp);
311}
312
313/*
314 * Lookup a name in the hash table and return a pointer
315 * to it.
316 */
317
318struct hent *
319lookup(name)
320        char name[];
321{
322        register int h;
323        register struct hent *hp;
324
325        h = hash(name);
326        for (hp = hashtab[h]; hp != NIL; hp = hp->h_link)
327                if (strcmp(hp->h_name, name) == 0)
328                        return(hp);
329        return(NIL);
330}
331
332/*
333 * Hash the passed name and return the index in
334 * the hash table to begin the search.
335 */
336
337hash(name)
338        char name[];
339{
340        register int h;
341        register char *cp;
342
343        for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
344                ;
345        return((h & 0x7fffffff) % HSHSIZE);
346}
347
348/*
349 * Other stuff
350 */
351
352any(ch, str)
353        char str[];
354{
355        register int c = ch;
356        register char *cp = str;
357
358        while (*cp)
359                if (*cp++ == c)
360                        return(1);
361        return(0);
362}
363
364/*
365 * The qsort comparison routine.
366 * The comparison is ascii collating order
367 * or by feet of typesetter film, according to sort.
368 */
369
370qucmp(left, right)
371        struct hent **left, **right;
372{
373        register struct hent *h1, *h2;
374        register int r;
375
376        h1 = *left;
377        h2 = *right;
378        if (sort)
379                r = h1->h_feetpages < h2->h_feetpages ? -1 : h1->h_feetpages >
380h2->h_feetpages;
381        else
382                r = strcmp(h1->h_name, h2->h_name);
383        return(reverse ? -r : r);
384}
385
386/*
387 * Perform lookup for printer name or abbreviation --
388 */
389chkprinter()
390{
391        static char buf[BUFSIZ/2];
392        char b[BUFSIZ];
393        int stat;
394        char *bp = buf;
395
396#ifdef HESIOD_PAC
397        if ((stat = pgetent(b, printer)) <= 0) {
398                if (pralias(alibuf, printer))
399                        printer = alibuf;
400                if ((stat = hpgetent(b, printer)) < 1)
401                        return(0);
402        }
403#else
404        if ((stat = pgetent(b, printer)) < 0) {
405                printf("pac: can't open printer description file\n");
406                exit(3);
407        } else if (stat == 0)
408                return(0);
409#endif /* HESIOD_PAC */
410        if ((acctfile = pgetstr("af", &bp)) == NULL) {
411                printf("accounting not enabled for printer %s\n", printer);
412                exit(2);
413        }
414        if (!pflag && (price100 = pgetnum("pc")) > 0)
415                price = price100/10000.0;
416        sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
417        if (sumfile == NULL) {
418                perror("pac");
419                exit(1);
420        }
421        strcpy(sumfile, acctfile);
422        strcat(sumfile, "_sum");
423        return(1);
424}
Note: See TracBrowser for help on using the repository browser.