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