* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
static char sccsid
[] = "@(#)pac.c 5.5 (Berkeley) 6/1/90";
* Do Printer accounting summary.
* pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...]
* to print the usage information for the named people.
char *printer
; /* printer name */
char *acctfile
; /* accounting file (input data) */
char *sumfile
; /* summary file */
float price
= 0.02; /* cost per page (or what ever) */
int allflag
= 1; /* Get stats on everybody */
int sort
; /* Sort by cost */
int summarize
; /* Compress accounting file */
int reverse
; /* Reverse sort order */
int hcount
; /* Count of hash entries */
int mflag
= 0; /* disregard machine names */
int pflag
= 0; /* 1 if -p on cmd line */
int price100
; /* per-page cost in 100th of a cent */
* Names to be accumulated are hashed into the following
#define HSHSIZE 97 /* Number of hash buckets */
struct hent
*h_link
; /* Forward hash link */
char *h_name
; /* Name of this user */
float h_feetpages
; /* Feet or pages of paper */
int h_count
; /* Number of runs */
struct hent
*hashtab
[HSHSIZE
]; /* Hash table proper */
#define NIL ((struct hent *) 0) /* The big zero */
* Summarize and compress accounting file.
* disregard machine names for each user
"usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n");
if (printer
== NULL
&& (printer
= getenv("PRINTER")) == NULL
)
if (!chkprinter(printer
)) {
printf("pac: unknown printer %s\n", printer
);
if ((acct
= fopen(acctfile
, "r")) == NULL
) {
if ((acct
= fopen(sumfile
, "r")) != NULL
) {
* Read the entire accounting file, accumulating statistics
* for the users that we have in the hash table. If allflag
* is set, then just gather the facts on everyone.
* Note that we must accomodate both the active and summary file
* Host names are ignored if the -m flag is present.
register struct hent
*hp
;
while (fgets(linebuf
, BUFSIZ
, acct
) != NULL
) {
while (any(*cp
, ".0123456789"))
for (cp2
= cp
; !any(*cp2
, " \t\n"); cp2
++)
if (mflag
&& index(cp
, ':'))
* Sort the hashed entries by name or footage
register struct hent
*hp
, **ap
;
register int hno
, c
, runs
;
base
= (struct hent
**) calloc(sizeof hp
, hcount
);
for (ap
= base
, c
= hcount
; c
--; ap
++) {
qsort(base
, hcount
, sizeof hp
, qucmp
);
printf(" Login pages/feet runs price\n");
for (ap
= base
, c
= hcount
; c
--; ap
++) {
printf("%-24s %7.2f %4d $%6.2f\n", hp
->h_name
,
hp
->h_feetpages
, hp
->h_count
, hp
->h_feetpages
* price
);
printf("%-24s %7.2f %4d $%6.2f\n", "total", feet
,
* Rewrite the summary file with the summary information we have accumulated.
register struct hent
*hp
;
if ((acctf
= fopen(sumfile
, "w")) == NULL
) {
for (i
= 0; i
< HSHSIZE
; i
++) {
fprintf(acctf
, "%7.2f\t%s\t%d\n", hp
->h_feetpages
,
hp
->h_name
, hp
->h_count
);
if ((acctf
= fopen(acctfile
, "w")) == NULL
)
* Enter the name into the hash table and return the pointer allocated.
register struct hent
*hp
;
if ((hp
= lookup(name
)) != NIL
)
hp
= (struct hent
*) calloc(sizeof *hp
, 1);
hp
->h_name
= (char *) calloc(sizeof(char), strlen(name
)+1);
strcpy(hp
->h_name
, name
);
* Lookup a name in the hash table and return a pointer
register struct hent
*hp
;
for (hp
= hashtab
[h
]; hp
!= NIL
; hp
= hp
->h_link
)
if (strcmp(hp
->h_name
, name
) == 0)
* Hash the passed name and return the index in
* the hash table to begin the search.
for (cp
= name
, h
= 0; *cp
; h
= (h
<< 2) + *cp
++)
return((h
& 0x7fffffff) % HSHSIZE
);
* The qsort comparison routine.
* The comparison is ascii collating order
* or by feet of typesetter film, according to sort.
struct hent
**left
, **right
;
register struct hent
*h1
, *h2
;
r
= h1
->h_feetpages
< h2
->h_feetpages
? -1 : h1
->h_feetpages
>
r
= strcmp(h1
->h_name
, h2
->h_name
);
return(reverse
? -r
: r
);
* Perform lookup for printer name or abbreviation --
static char buf
[BUFSIZ
/2];
if ((stat
= pgetent(b
, s
)) < 0) {
printf("pac: can't open printer description file\n");
if ((acctfile
= pgetstr("af", &bp
)) == NULL
) {
printf("accounting not enabled for printer %s\n", printer
);
if (!pflag
&& (price100
= pgetnum("pc")) > 0)
price
= price100
/10000.0;
sumfile
= (char *) calloc(sizeof(char), strlen(acctfile
)+5);
strcpy(sumfile
, acctfile
);