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