1*7691Smckusick static char sccsid[] = "@(#)vpac.c 1.2 (Berkeley) 08/08/82";
21848Sroot
31848Sroot #include <stdio.h>
41848Sroot
51848Sroot /*
61848Sroot * Do Versatec and Varian accounting summary.
71848Sroot * Currently, usage is
81848Sroot * vpac [-srW] [user] ...
91848Sroot * to print the usage information for the named people.
101848Sroot */
111848Sroot
121848Sroot int errs;
131848Sroot
141848Sroot #define VAACCT "/usr/adm/vaacct"
151848Sroot #define VASUM "/usr/adm/va_sum"
161848Sroot #define VPACCT "/usr/adm/vpacct"
171848Sroot #define VPSUM "/usr/adm/vp_sum"
181848Sroot char *acctfile;
191848Sroot char *sumfile;
201848Sroot
211848Sroot #define VAPRICE 0.02 /* Dollars per page */
221848Sroot #define VPPRICE 0.08 /* Dollars per foot of paper */
231848Sroot float price;
241848Sroot
251848Sroot /*
261848Sroot * Grossness follows:
271848Sroot * Names to be accumulated are hashed into the following
281848Sroot * table.
291848Sroot */
301848Sroot
311848Sroot #define HSHSIZE 97 /* Number of hash buckets */
321848Sroot
331848Sroot struct hent {
341848Sroot struct hent *h_link; /* Forward hash link */
351848Sroot char h_name[9]; /* Name of this user */
361848Sroot float h_feetpages; /* Feet or pages of paper */
371848Sroot int h_count; /* Number of runs */
381848Sroot };
391848Sroot
401848Sroot struct hent *hashtab[HSHSIZE]; /* Hash table proper */
411848Sroot struct hent *enter();
421848Sroot struct hent *lookup();
431848Sroot
441848Sroot #define NIL ((struct hent *) 0) /* The big zero */
451848Sroot
461848Sroot int allflag; /* Get stats on everybody */
471848Sroot int sort; /* Sort by cost */
481848Sroot int summarize; /* Compress accounting file */
491848Sroot int reverse; /* Reverse sort order */
501848Sroot int wide; /* wide paper (Versatec) accounting. */
511848Sroot
521848Sroot int hcount; /* Count of hash entries */
531848Sroot
main(argc,argv)541848Sroot main(argc, argv)
551848Sroot char **argv;
561848Sroot {
571848Sroot register FILE *acct;
581848Sroot register char *cp;
591848Sroot register int gotcha = 0;
601848Sroot
611848Sroot acctfile = VAACCT;
621848Sroot sumfile = VASUM;
631848Sroot price = VAPRICE;
641848Sroot if (argc >= 2)
651848Sroot while (--argc) {
661848Sroot cp = *++argv;
671848Sroot if (*cp++ == '-') {
681848Sroot while (*cp) switch(*cp++) {
691848Sroot case 's':
701848Sroot /*
711848Sroot * Summarize and compress
721848Sroot * accounting file.
731848Sroot */
741848Sroot summarize++;
751848Sroot break;
761848Sroot
771848Sroot case 't':
781848Sroot /*
791848Sroot * Sort by feet of typesetter film.
801848Sroot */
811848Sroot sort++;
821848Sroot break;
831848Sroot
841848Sroot case 'r':
851848Sroot /*
861848Sroot * Reverse sorting order.
871848Sroot */
881848Sroot reverse++;
891848Sroot break;
901848Sroot
911848Sroot case 'W':
921848Sroot /*
931848Sroot * Versatec, not Varian accounting.
941848Sroot */
951848Sroot wide++;
961848Sroot acctfile = VPACCT;
971848Sroot sumfile = VPSUM;
981848Sroot price = VPPRICE;
991848Sroot break;
1001848Sroot default:
1011848Sroot fprintf(stderr, "%s?\n", *argv);
1021848Sroot exit(1);
1031848Sroot }
1041848Sroot continue;
1051848Sroot }
1061848Sroot ignore(enter(--cp));
1071848Sroot gotcha++;
1081848Sroot }
1091848Sroot allflag = gotcha == 0;
1101848Sroot
1111848Sroot if ((acct = fopen(acctfile, "r")) == NULL) {
1121848Sroot perror(acctfile);
1131848Sroot exit(1);
1141848Sroot }
1151848Sroot account(acct);
1161848Sroot fclose(acct);
1171848Sroot if ((acct = fopen(sumfile, "r")) != NULL) {
1181848Sroot account(acct);
1191848Sroot fclose(acct);
1201848Sroot }
1211848Sroot if (summarize)
1221848Sroot rewrite();
1231848Sroot else
1241848Sroot dumpit();
1251848Sroot exit(errs);
1261848Sroot }
1271848Sroot
1281848Sroot /*
1291848Sroot * Read the entire accounting file, accumulating statistics
1301848Sroot * for the users that we have in the hash table. If allflag
1311848Sroot * is set, then just gather the facts on everyone.
1321848Sroot * Note that we must accomodate both the active and summary file
1331848Sroot * formats here.
1341848Sroot */
1351848Sroot
account(acct)1361848Sroot account(acct)
1371848Sroot register FILE *acct;
1381848Sroot {
1391848Sroot char linebuf[BUFSIZ];
1401848Sroot float t, atof();
1411848Sroot register char *cp, *cp2;
1421848Sroot register struct hent *hp;
1431848Sroot register int ic;
1441848Sroot
1451848Sroot while (fgets(linebuf, BUFSIZ, acct) != NULL) {
1461848Sroot cp = linebuf;
1471848Sroot while (any(*cp, " t\t"))
1481848Sroot cp++;
1491848Sroot t = atof(cp);
1501848Sroot while (any(*cp, ".0123456789"))
1511848Sroot cp++;
1521848Sroot while (any(*cp, " \t"))
1531848Sroot cp++;
1541848Sroot for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
1551848Sroot ;
1561848Sroot ic = atoi(cp2);
1571848Sroot *cp2 = '\0';
1581848Sroot hp = lookup(cp);
1591848Sroot if (hp == NIL && !allflag)
1601848Sroot continue;
1611848Sroot if (hp == NIL)
1621848Sroot hp = enter(cp);
1631848Sroot hp->h_feetpages += t;
1641848Sroot if (ic)
1651848Sroot hp->h_count += ic;
1661848Sroot else
1671848Sroot hp->h_count++;
1681848Sroot }
1691848Sroot }
1701848Sroot
1711848Sroot /*
1721848Sroot * Sort the hashed entries by name or footage
1731848Sroot * and print it all out.
1741848Sroot */
1751848Sroot
dumpit()1761848Sroot dumpit()
1771848Sroot {
1781848Sroot struct hent **base;
1791848Sroot register struct hent *hp, **ap;
1801848Sroot register int hno, c, runs;
1811848Sroot float feet;
1821848Sroot int qucmp();
1831848Sroot
1841848Sroot hp = hashtab[0];
1851848Sroot hno = 1;
1861848Sroot base = (struct hent **) calloc(sizeof hp, hcount+4);
1871848Sroot for (ap = base, c = hcount; c--; ap++) {
1881848Sroot while (hp == NIL)
1891848Sroot hp = hashtab[hno++];
1901848Sroot *ap = hp;
1911848Sroot hp = hp->h_link;
1921848Sroot }
1931848Sroot qsort(base, hcount, sizeof hp, qucmp);
1941848Sroot printf(wide ? " Login feet runs price\n"
1951848Sroot : " Login pages runs price\n");
1961848Sroot feet = 0.0;
1971848Sroot runs = 0;
1981848Sroot for (ap = base, c = hcount; c--; ap++) {
1991848Sroot hp = *ap;
2001848Sroot runs += hp->h_count;
2011848Sroot feet += hp->h_feetpages;
2021848Sroot printf("%-8s %7.2f %4d $%6.2f\n", hp->h_name, hp->h_feetpages,
2031848Sroot hp->h_count, hp->h_feetpages * price);
2041848Sroot }
2051848Sroot if (allflag) {
2061848Sroot printf("\n");
2071848Sroot printf("%-8s %7.2f %4d $%6.2f\n", "total", feet,
2081848Sroot runs, feet * price);
2091848Sroot }
2101848Sroot }
2111848Sroot
2121848Sroot /*
2131848Sroot * Rewrite the summary file with the summary information we have accumulated.
2141848Sroot */
2151848Sroot
rewrite()2161848Sroot rewrite()
2171848Sroot {
2181848Sroot register struct hent *hp;
2191848Sroot register int i;
2201848Sroot register FILE *acctf;
2211848Sroot
2221848Sroot if ((acctf = fopen(sumfile, "w")) == NULL) {
2231848Sroot perror(sumfile);
2241848Sroot errs++;
2251848Sroot return;
2261848Sroot }
2271848Sroot for (i = 0; i < HSHSIZE; i++) {
2281848Sroot hp = hashtab[i];
2291848Sroot while (hp != NULL) {
2301848Sroot fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
2311848Sroot hp->h_name, hp->h_count);
2321848Sroot hp = hp->h_link;
2331848Sroot }
2341848Sroot }
2351848Sroot fflush(acctf);
2361848Sroot if (ferror(acctf)) {
2371848Sroot perror(sumfile);
2381848Sroot errs++;
2391848Sroot }
2401848Sroot fclose(acctf);
2411848Sroot if ((acctf = fopen(acctfile, "w")) == NULL)
2421848Sroot perror(acctfile);
2431848Sroot else
2441848Sroot fclose(acctf);
2451848Sroot }
2461848Sroot
2471848Sroot /*
2481848Sroot * Hashing routines.
2491848Sroot */
2501848Sroot
2511848Sroot /*
2521848Sroot * Enter the passed name into the hash table
2531848Sroot * and returns the pointer allocated.
2541848Sroot */
2551848Sroot
2561848Sroot struct hent *
enter(name)2571848Sroot enter(name)
2581848Sroot char name[];
2591848Sroot {
2601848Sroot register struct hent *hp;
2611848Sroot register int h;
2621848Sroot
2631848Sroot if ((hp = lookup(name)) != NIL)
2641848Sroot return(hp);
2651848Sroot h = hash(name);
2661848Sroot hcount++;
2671848Sroot hp = (struct hent *) calloc(sizeof *hp, 1);
2681848Sroot strcpy(hp->h_name, name);
2691848Sroot hp->h_feetpages = 0.0;
2701848Sroot hp->h_count = 0;
2711848Sroot hp->h_link = hashtab[h];
2721848Sroot hashtab[h] = hp;
2731848Sroot return(hp);
2741848Sroot }
2751848Sroot
2761848Sroot /*
2771848Sroot * Lookup a name in the hash table and return a pointer
2781848Sroot * to it.
2791848Sroot */
2801848Sroot
2811848Sroot struct hent *
lookup(name)2821848Sroot lookup(name)
2831848Sroot char name[];
2841848Sroot {
2851848Sroot register int h;
2861848Sroot register struct hent *hp;
2871848Sroot
2881848Sroot h = hash(name);
2891848Sroot for (hp = hashtab[h]; hp != NIL; hp = hp->h_link)
2901848Sroot if (strcmp(hp->h_name, name) == 0)
2911848Sroot return(hp);
2921848Sroot return(NIL);
2931848Sroot }
2941848Sroot
2951848Sroot /*
2961848Sroot * Hash the passed name and return the index in
2971848Sroot * the hash table to begin the search.
2981848Sroot */
2991848Sroot
hash(name)3001848Sroot hash(name)
3011848Sroot char name[];
3021848Sroot {
3031848Sroot register int h;
3041848Sroot register char *cp;
3051848Sroot
3061848Sroot for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
3071848Sroot ;
3081848Sroot if (h < 0)
3091848Sroot h = -h;
3101848Sroot if (h < 0)
3111848Sroot h = 0;
3121848Sroot return(h % HSHSIZE);
3131848Sroot }
3141848Sroot
3151848Sroot /*
3161848Sroot * Other stuff
3171848Sroot */
3181848Sroot
any(ch,str)3191848Sroot any(ch, str)
3201848Sroot char str[];
3211848Sroot {
3221848Sroot register int c = ch;
3231848Sroot register char *cp = str;
3241848Sroot
3251848Sroot while (*cp)
3261848Sroot if (*cp++ == c)
3271848Sroot return(1);
3281848Sroot return(0);
3291848Sroot }
3301848Sroot
3311848Sroot /*
3321848Sroot * Throw away a hash pointer.
3331848Sroot */
3341848Sroot
3351848Sroot ignore(p)
3361848Sroot struct hent *p;
3371848Sroot {;}
3381848Sroot
3391848Sroot /*
3401848Sroot * The qsort comparison routine.
3411848Sroot * The comparison is ascii collating order
3421848Sroot * or by feet of typesetter film, according to sort.
3431848Sroot */
3441848Sroot
3451848Sroot qucmp(left, right)
3461848Sroot struct hent **left, **right;
3471848Sroot {
3481848Sroot register struct hent *h1, *h2;
3491848Sroot register int r;
3501848Sroot
3511848Sroot h1 = *left;
3521848Sroot h2 = *right;
3531848Sroot if (sort)
3541848Sroot r = h1->h_feetpages < h2->h_feetpages ? -1 : h1->h_feetpages > h2->h_feetpages;
3551848Sroot else
3561848Sroot r = strcmp(h1->h_name, h2->h_name);
3571848Sroot return(reverse ? -r : r);
3581848Sroot }
359