|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.