1
/* $OpenBSD: pac.c,v 1.9 1997/07/17 09:08:43 deraadt Exp $ */
2
/* $NetBSD: pac.c,v 1.7 1996/03/21 18:21:20 jtc Exp $ */
5
* Copyright (c) 1983, 1993
6
* The Regents of the University of California. All rights reserved.
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
* 3. All advertising materials mentioning features or use of this software
18
* must display the following acknowledgement:
19
* This product includes software developed by the University of
20
* California, Berkeley and its contributors.
21
* 4. Neither the name of the University nor the names of its contributors
22
* may be used to endorse or promote products derived from this software
23
* without specific prior written permission.
25
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39
static char copyright[] =
40
"@(#) Copyright (c) 1983, 1993\n\
41
The Regents of the University of California. All rights reserved.\n";
46
static char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93";
48
static char rcsid[] = "$OpenBSD: pac.c,v 1.9 1997/07/17 09:08:43 deraadt Exp $";
53
* Do Printer accounting summary.
55
* pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...]
56
* to print the usage information for the named people.
59
#include <sys/param.h>
69
static char *acctfile; /* accounting file (input data) */
70
static int allflag = 1; /* Get stats on everybody */
72
static int hcount; /* Count of hash entries */
73
static int mflag = 0; /* disregard machine names */
74
static int pflag = 0; /* 1 if -p on cmd line */
75
static float price = 0.02; /* cost per page (or what ever) */
76
static long price100; /* per-page cost in 100th of a cent */
77
static int reverse; /* Reverse sort order */
78
static int sort; /* Sort by cost */
79
static char *sumfile; /* summary file */
80
static int summarize; /* Compress accounting file */
86
* Names to be accumulated are hashed into the following
90
#define HSHSIZE 97 /* Number of hash buckets */
93
struct hent *h_link; /* Forward hash link */
94
char *h_name; /* Name of this user */
95
float h_feetpages; /* Feet or pages of paper */
96
int h_count; /* Number of runs */
99
static struct hent *hashtab[HSHSIZE]; /* Hash table proper */
101
static void account __P((FILE *));
102
static int any __P((int, char []));
103
static int chkprinter __P((char *));
104
static void dumpit __P((void));
105
static int hash __P((char []));
106
static struct hent *enter __P((char []));
107
static struct hent *lookup __P((char []));
108
static int qucmp __P((const void *, const void *));
109
static void rewrite __P((void));
119
euid = geteuid(); /* these aren't used in pac(1) */
142
* Summarize and compress accounting file.
156
* disregard machine names for each user
163
* Reverse sorting order.
170
"usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n");
177
if (printer == NULL) {
181
if ((p = getenv("PRINTER")) != NULL)
184
if (!chkprinter(printer)) {
185
printf("pac: unknown printer %s\n", printer);
189
if ((acct = fopen(acctfile, "r")) == NULL) {
195
if ((acct = fopen(sumfile, "r")) != NULL) {
207
* Read the entire accounting file, accumulating statistics
208
* for the users that we have in the hash table. If allflag
209
* is set, then just gather the facts on everyone.
210
* Note that we must accomodate both the active and summary file
212
* Host names are ignored if the -m flag is present.
218
char linebuf[BUFSIZ];
220
register char *cp, *cp2;
221
register struct hent *hp;
224
while (fgets(linebuf, BUFSIZ, acct) != NULL) {
226
while (any(*cp, " \t"))
229
while (any(*cp, ".0123456789"))
231
while (any(*cp, " \t"))
233
for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
237
if (mflag && strchr(cp, ':'))
238
cp = strchr(cp, ':') + 1;
245
hp->h_feetpages += t;
254
* Sort the hashed entries by name or footage
255
* and print it all out.
261
register struct hent *hp, **ap;
262
register int hno, c, runs;
267
base = (struct hent **) calloc(sizeof hp, hcount);
268
for (ap = base, c = hcount; c--; ap++) {
274
qsort(base, hcount, sizeof hp, qucmp);
275
printf(" Login pages/feet runs price\n");
278
for (ap = base, c = hcount; c--; ap++) {
281
feet += hp->h_feetpages;
282
printf("%-24s %7.2f %4d $%6.2f\n", hp->h_name,
283
hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
287
printf("%-24s %7.2f %4d $%6.2f\n", "total", feet,
293
* Rewrite the summary file with the summary information we have accumulated.
298
register struct hent *hp;
300
register FILE *acctf;
302
if ((acctf = fopen(sumfile, "w")) == NULL) {
307
for (i = 0; i < HSHSIZE; i++) {
310
fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
311
hp->h_name, hp->h_count);
321
if ((acctf = fopen(acctfile, "w")) == NULL)
332
* Enter the name into the hash table and return the pointer allocated.
339
register struct hent *hp;
342
if ((hp = lookup(name)) != NULL)
346
hp = (struct hent *) calloc(sizeof *hp, 1);
347
hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1);
348
strcpy(hp->h_name, name);
349
hp->h_feetpages = 0.0;
351
hp->h_link = hashtab[h];
357
* Lookup a name in the hash table and return a pointer
366
register struct hent *hp;
369
for (hp = hashtab[h]; hp != NULL; hp = hp->h_link)
370
if (strcmp(hp->h_name, name) == 0)
376
* Hash the passed name and return the index in
377
* the hash table to begin the search.
386
for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
388
return((h & 0x7fffffff) % HSHSIZE);
400
register char *cp = str;
409
* The qsort comparison routine.
410
* The comparison is ascii collating order
411
* or by feet of typesetter film, according to sort.
417
register struct hent *h1, *h2;
420
h1 = *(struct hent **)a;
421
h2 = *(struct hent **)b;
423
r = h1->h_feetpages < h2->h_feetpages ?
424
-1 : h1->h_feetpages > h2->h_feetpages;
426
r = strcmp(h1->h_name, h2->h_name);
427
return(reverse ? -r : r);
431
* Perform lookup for printer name or abbreviation --
439
if ((stat = cgetent(&bp, printcapdb, s)) == -2) {
440
printf("pac: can't open printer description file\n");
442
} else if (stat == -1)
445
fatal("potential reference loop detected in printcap file");
447
if (cgetstr(bp, "af", &acctfile) == -1) {
448
printf("accounting not enabled for printer %s\n", printer);
451
if (!pflag && (cgetnum(bp, "pc", &price100) == 0))
452
price = price100/10000.0;
453
sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
454
if (sumfile == NULL) {
458
strcpy(sumfile, acctfile);
459
strcat(sumfile, "_sum");