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

Defined functions

account defined in line 163; used 2 times
any defined in line 344; used 4 times
chkprinter defined in line 381; used 1 times
dumpit defined in line 206; used 1 times
enter defined in line 284; used 3 times
hash defined in line 329; used 2 times
lookup defined in line 310; used 3 times
main defined in line 68; never used
qucmp defined in line 362; used 2 times
rewrite defined in line 245; used 1 times

Defined variables

acctfile defined in line 28; used 7 times
allflag defined in line 31; used 3 times
copyright defined in line 8; never used
errs defined in line 36; used 3 times
hashtab defined in line 58; used 6 times
hcount defined in line 35; used 5 times
mflag defined in line 37; used 2 times
pflag defined in line 38; used 2 times
price defined in line 30; used 4 times
price100 defined in line 39; used 2 times
printer defined in line 27; used 7 times
reverse defined in line 34; used 2 times
sccsid defined in line 14; never used
sort defined in line 32; used 2 times
sumfile defined in line 29; used 8 times
summarize defined in line 33; used 2 times

Defined struct's

hent defined in line 51; used 32 times

Defined macros

HSHSIZE defined in line 49; used 3 times
NIL defined in line 62; used 5 times
Last modified: 1987-02-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3813
Valid CSS Valid XHTML 1.0 Strict