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