|
|
1.1 ! root 1: static char sccsid[] = "@(#)vpac.c 1.2 (Berkeley) 8/8/82"; ! 2: ! 3: #include <stdio.h> ! 4: ! 5: /* ! 6: * Do Versatec and Varian accounting summary. ! 7: * Currently, usage is ! 8: * vpac [-srW] [user] ... ! 9: * to print the usage information for the named people. ! 10: */ ! 11: ! 12: int errs; ! 13: ! 14: #define VAACCT "/usr/adm/vaacct" ! 15: #define VASUM "/usr/adm/va_sum" ! 16: #define VPACCT "/usr/adm/vpacct" ! 17: #define VPSUM "/usr/adm/vp_sum" ! 18: char *acctfile; ! 19: char *sumfile; ! 20: ! 21: #define VAPRICE 0.02 /* Dollars per page */ ! 22: #define VPPRICE 0.08 /* Dollars per foot of paper */ ! 23: float price; ! 24: ! 25: /* ! 26: * Grossness follows: ! 27: * Names to be accumulated are hashed into the following ! 28: * table. ! 29: */ ! 30: ! 31: #define HSHSIZE 97 /* Number of hash buckets */ ! 32: ! 33: struct hent { ! 34: struct hent *h_link; /* Forward hash link */ ! 35: char h_name[9]; /* Name of this user */ ! 36: float h_feetpages; /* Feet or pages of paper */ ! 37: int h_count; /* Number of runs */ ! 38: }; ! 39: ! 40: struct hent *hashtab[HSHSIZE]; /* Hash table proper */ ! 41: struct hent *enter(); ! 42: struct hent *lookup(); ! 43: ! 44: #define NIL ((struct hent *) 0) /* The big zero */ ! 45: ! 46: int allflag; /* Get stats on everybody */ ! 47: int sort; /* Sort by cost */ ! 48: int summarize; /* Compress accounting file */ ! 49: int reverse; /* Reverse sort order */ ! 50: int wide; /* wide paper (Versatec) accounting. */ ! 51: ! 52: int hcount; /* Count of hash entries */ ! 53: ! 54: main(argc, argv) ! 55: char **argv; ! 56: { ! 57: register FILE *acct; ! 58: register char *cp; ! 59: register int gotcha = 0; ! 60: ! 61: acctfile = VAACCT; ! 62: sumfile = VASUM; ! 63: price = VAPRICE; ! 64: if (argc >= 2) ! 65: while (--argc) { ! 66: cp = *++argv; ! 67: if (*cp++ == '-') { ! 68: while (*cp) switch(*cp++) { ! 69: case 's': ! 70: /* ! 71: * Summarize and compress ! 72: * accounting file. ! 73: */ ! 74: summarize++; ! 75: break; ! 76: ! 77: case 't': ! 78: /* ! 79: * Sort by feet of typesetter film. ! 80: */ ! 81: sort++; ! 82: break; ! 83: ! 84: case 'r': ! 85: /* ! 86: * Reverse sorting order. ! 87: */ ! 88: reverse++; ! 89: break; ! 90: ! 91: case 'W': ! 92: /* ! 93: * Versatec, not Varian accounting. ! 94: */ ! 95: wide++; ! 96: acctfile = VPACCT; ! 97: sumfile = VPSUM; ! 98: price = VPPRICE; ! 99: break; ! 100: default: ! 101: fprintf(stderr, "%s?\n", *argv); ! 102: exit(1); ! 103: } ! 104: continue; ! 105: } ! 106: ignore(enter(--cp)); ! 107: gotcha++; ! 108: } ! 109: allflag = gotcha == 0; ! 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: float t, atof(); ! 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 && !allflag) ! 160: continue; ! 161: if (hp == NIL) ! 162: hp = enter(cp); ! 163: hp->h_feetpages += t; ! 164: if (ic) ! 165: hp->h_count += ic; ! 166: else ! 167: hp->h_count++; ! 168: } ! 169: } ! 170: ! 171: /* ! 172: * Sort the hashed entries by name or footage ! 173: * and print it all out. ! 174: */ ! 175: ! 176: dumpit() ! 177: { ! 178: struct hent **base; ! 179: register struct hent *hp, **ap; ! 180: register int hno, c, runs; ! 181: float feet; ! 182: int qucmp(); ! 183: ! 184: hp = hashtab[0]; ! 185: hno = 1; ! 186: base = (struct hent **) calloc(sizeof hp, hcount+4); ! 187: for (ap = base, c = hcount; c--; ap++) { ! 188: while (hp == NIL) ! 189: hp = hashtab[hno++]; ! 190: *ap = hp; ! 191: hp = hp->h_link; ! 192: } ! 193: qsort(base, hcount, sizeof hp, qucmp); ! 194: printf(wide ? " Login feet runs price\n" ! 195: : " Login pages 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("%-8s %7.2f %4d $%6.2f\n", hp->h_name, hp->h_feetpages, ! 203: hp->h_count, hp->h_feetpages * price); ! 204: } ! 205: if (allflag) { ! 206: printf("\n"); ! 207: printf("%-8s %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 passed name into the hash table ! 253: * and returns the pointer allocated. ! 254: */ ! 255: ! 256: struct hent * ! 257: enter(name) ! 258: char name[]; ! 259: { ! 260: register struct hent *hp; ! 261: register int h; ! 262: ! 263: if ((hp = lookup(name)) != NIL) ! 264: return(hp); ! 265: h = hash(name); ! 266: hcount++; ! 267: hp = (struct hent *) calloc(sizeof *hp, 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: if (h < 0) ! 309: h = -h; ! 310: if (h < 0) ! 311: h = 0; ! 312: return(h % HSHSIZE); ! 313: } ! 314: ! 315: /* ! 316: * Other stuff ! 317: */ ! 318: ! 319: any(ch, str) ! 320: char str[]; ! 321: { ! 322: register int c = ch; ! 323: register char *cp = str; ! 324: ! 325: while (*cp) ! 326: if (*cp++ == c) ! 327: return(1); ! 328: return(0); ! 329: } ! 330: ! 331: /* ! 332: * Throw away a hash pointer. ! 333: */ ! 334: ! 335: ignore(p) ! 336: struct hent *p; ! 337: {;} ! 338: ! 339: /* ! 340: * The qsort comparison routine. ! 341: * The comparison is ascii collating order ! 342: * or by feet of typesetter film, according to sort. ! 343: */ ! 344: ! 345: qucmp(left, right) ! 346: struct hent **left, **right; ! 347: { ! 348: register struct hent *h1, *h2; ! 349: register int r; ! 350: ! 351: h1 = *left; ! 352: h2 = *right; ! 353: if (sort) ! 354: r = h1->h_feetpages < h2->h_feetpages ? -1 : h1->h_feetpages > h2->h_feetpages; ! 355: else ! 356: r = strcmp(h1->h_name, h2->h_name); ! 357: return(reverse ? -r : r); ! 358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.