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: }

Defined functions

account defined in line 136; used 2 times
any defined in line 319; used 4 times
dumpit defined in line 176; used 1 times
enter defined in line 256; used 3 times
hash defined in line 300; used 2 times
ignore defined in line 335; used 1 times
lookup defined in line 281; used 3 times
main defined in line 54; never used
qucmp defined in line 345; used 2 times
rewrite defined in line 216; used 1 times

Defined variables

acctfile defined in line 18; used 6 times
allflag defined in line 46; used 3 times
errs defined in line 12; used 3 times
hashtab defined in line 40; used 6 times
hcount defined in line 52; used 5 times
price defined in line 23; used 4 times
reverse defined in line 49; used 2 times
sccsid defined in line 1; never used
sort defined in line 47; used 2 times
sumfile defined in line 19; used 6 times
summarize defined in line 48; used 2 times
wide defined in line 50; used 2 times

Defined struct's

hent defined in line 33; used 34 times

Defined macros

HSHSIZE defined in line 31; used 3 times
NIL defined in line 44; used 6 times
VAACCT defined in line 14; used 1 times
  • in line 61
VAPRICE defined in line 21; used 1 times
  • in line 63
VASUM defined in line 15; used 1 times
  • in line 62
VPACCT defined in line 16; used 1 times
  • in line 96
VPPRICE defined in line 22; used 1 times
  • in line 98
VPSUM defined in line 17; used 1 times
  • in line 97
Last modified: 1982-08-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1810
Valid CSS Valid XHTML 1.0 Strict