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