BSD 3 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Thu, 12 Jul 1979 04:41:28 +0000 (20:41 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Thu, 12 Jul 1979 04:41:28 +0000 (20:41 -0800)
Work on file usr/src/cmd/versatec/vpac.c

Synthesized-from: 3bsd

usr/src/cmd/versatec/vpac.c [new file with mode: 0644]

diff --git a/usr/src/cmd/versatec/vpac.c b/usr/src/cmd/versatec/vpac.c
new file mode 100644 (file)
index 0000000..589897c
--- /dev/null
@@ -0,0 +1,337 @@
+#
+
+#include <stdio.h>
+
+/*
+ * Do Versatec accounting summary.
+ * Currently, usage is
+ *     vpac user ...
+ * to print the usage information for the named people.
+ */
+
+int    errs;
+char   vpacct[]        = "/usr/adm/vpacct";
+char   sumfile[]       = "/usr/adm/vp_sum";
+
+#define        PRICE   0.08                    /* Dollars per foot of paper */
+
+/*
+ * Grossness follows:
+ *  Names to be accumulated are hashed into the following
+ *  table.
+ */
+
+#define        HSHSIZE 97                      /* Number of hash buckets */
+
+struct hent {
+       struct  hent *h_link;           /* Forward hash link */
+       char    h_name[9];              /* Name of this user */
+       float   h_feet;                 /* Feet of typesetter film */
+       int     h_count;                /* Number of runs */
+};
+
+struct hent    *hashtab[HSHSIZE];      /* Hash table proper */
+struct hent    *enter();
+struct hent    *lookup();
+
+#define        NIL     ((struct hent *) 0)     /* The big zero */
+
+int    allflag;                        /* Get stats on everybody */
+int    sort;                           /* Sort by cost */
+int    summarize;                      /* Compress accounting file */
+int    reverse;                        /* Reverse sort order */
+
+int    hcount;                         /* Count of hash entries */
+
+main(argc, argv)
+       char **argv;
+{
+       register FILE *acct;
+       register char *cp;
+       register int gotcha = 0;
+
+       if ((acct = fopen(vpacct, "r")) == NULL) {
+               perror(vpacct);
+               exit(1);
+       }
+       if (argc >= 2)
+               while (--argc) {
+                       cp = *++argv;
+                       if (*cp++ == '-') {
+                               while (*cp) switch(*cp++) {
+                               case 's':
+                                       /*
+                                        * Summarize and compress
+                                        * accounting file.
+                                        */
+                                       summarize++;
+                                       break;
+
+                               case 't':
+                                       /*
+                                        * Sort by feet of typesetter film.
+                                        */
+                                       sort++;
+                                       break;
+
+                               case 'r':
+                                       /*
+                                        * Reverse sorting order.
+                                        */
+                                       reverse++;
+                                       break;
+
+                               default:
+                                       fprintf(stderr, "%s?\n", *argv);
+                                       exit(1);
+                               }
+                               continue;
+                       }
+                       ignore(enter(--cp));
+                       gotcha++;
+               }
+       allflag = gotcha == 0;
+       account(acct);
+       fclose(acct);
+       if ((acct = fopen(sumfile, "r")) != NULL) {
+               account(acct);
+               fclose(acct);
+       }
+       if (summarize)
+               rewrite();
+       else
+               dumpit();
+       exit(errs);
+}
+
+/*
+ * Read the entire accounting file, accumulating statistics
+ * for the users that we have in the hash table.  If allflag
+ * is set, then just gather the facts on everyone.
+ * Note that we must accomodate both the active and summary file
+ * formats here.
+ */
+
+account(acct)
+       register FILE *acct;
+{
+       char linebuf[BUFSIZ];
+       float t, atof();
+       register char *cp, *cp2;
+       register struct hent *hp;
+       register int ic;
+
+       while (fgets(linebuf, BUFSIZ, acct) != NULL) {
+               cp = linebuf;
+               while (any(*cp, " t\t"))
+                       cp++;
+               t = atof(cp);
+               while (any(*cp, ".0123456789"))
+                       cp++;
+               while (any(*cp, " \t"))
+                       cp++;
+               for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
+                       ;
+               ic = atoi(cp2);
+               *cp2 = '\0';
+               hp = lookup(cp);
+               if (hp == NIL && !allflag)
+                       continue;
+               if (hp == NIL)
+                       hp = enter(cp);
+               hp->h_feet += t;
+               if (ic)
+                       hp->h_count += ic;
+               else
+                       hp->h_count++;
+       }
+}
+
+/*
+ * Sort the hashed entries by name or footage
+ * and print it all out.
+ */
+
+dumpit()
+{
+       struct hent **base;
+       register struct hent *hp, **ap;
+       register int hno, c, runs;
+       float feet;
+       int qucmp();
+
+       hp = hashtab[0];
+       hno = 1;
+       base = (struct hent **) calloc(sizeof hp, hcount+4);
+       for (ap = base, c = hcount; c--; ap++) {
+               while (hp == NIL)
+                       hp = hashtab[hno++];
+               *ap = hp;
+               hp = hp->h_link;
+       }
+       qsort(base, hcount, sizeof hp, qucmp);
+       printf(" Login    feet   runs    price\n");
+       feet = 0.0;
+       runs = 0;
+       for (ap = base, c = hcount; c--; ap++) {
+               hp = *ap;
+               runs += hp->h_count;
+               feet += hp->h_feet;
+               printf("%-8s %7.2f %4d   $%6.2f\n", hp->h_name, hp->h_feet,
+                   hp->h_count, hp->h_feet * PRICE);
+       }
+       if (allflag) {
+               printf("\n");
+               printf("%-8s %7.2f %4d   $%6.2f\n", "total", feet, 
+                   runs, feet * PRICE);
+       }
+}
+
+/*
+ * Rewrite the Versatec printer summary file with the summary
+ * information we have accumulated.
+ */
+
+rewrite()
+{
+       register struct hent *hp;
+       register int i;
+       register FILE *acctf;
+
+       if ((acctf = fopen(sumfile, "w")) == NULL) {
+               perror(sumfile);
+               errs++;
+               return;
+       }
+       for (i = 0; i < HSHSIZE; i++) {
+               hp = hashtab[i];
+               while (hp != NULL) {
+                       fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feet,
+                           hp->h_name, hp->h_count);
+                       hp = hp->h_link;
+               }
+       }
+       fflush(acctf);
+       if (ferror(acctf)) {
+               perror(sumfile);
+               errs++;
+       }
+       fclose(acctf);
+       if ((acctf = fopen(vpacct, "w")) == NULL)
+               perror(vpacct);
+       else
+               fclose(acctf);
+}
+
+/*
+ * Hashing routines.
+ */
+
+/*
+ * Enter the passed name into the hash table
+ * and returns the pointer allocated.
+ */
+
+struct hent *
+enter(name)
+       char name[];
+{
+       register struct hent *hp;
+       register int h;
+
+       if ((hp = lookup(name)) != NIL)
+               return(hp);
+       h = hash(name);
+       hcount++;
+       hp = (struct hent *) calloc(sizeof *hp, 1);
+       strcpy(hp->h_name, name);
+       hp->h_feet = 0.0;
+       hp->h_count = 0;
+       hp->h_link = hashtab[h];
+       hashtab[h] = hp;
+       return(hp);
+}
+
+/*
+ * Lookup a name in the hash table and return a pointer
+ * to it.
+ */
+
+struct hent *
+lookup(name)
+       char name[];
+{
+       register int h;
+       register struct hent *hp;
+
+       h = hash(name);
+       for (hp = hashtab[h]; hp != NIL; hp = hp->h_link)
+               if (strcmp(hp->h_name, name) == 0)
+                       return(hp);
+       return(NIL);
+}
+
+/*
+ * Hash the passed name and return the index in
+ * the hash table to begin the search.
+ */
+
+hash(name)
+       char name[];
+{
+       register int h;
+       register char *cp;
+
+       for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
+               ;
+       if (h < 0)
+               h = -h;
+       if (h < 0)
+               h = 0;
+       return(h % HSHSIZE);
+}
+
+/*
+ * Other stuff
+ */
+
+any(ch, str)
+       char str[];
+{
+       register int c = ch;
+       register char *cp = str;
+
+       while (*cp)
+               if (*cp++ == c)
+                       return(1);
+       return(0);
+}
+
+/*
+ * Throw away a hash pointer.
+ */
+
+ignore(p)
+       struct hent *p;
+{;}
+
+/*
+ * The qsort comparison routine.
+ * The comparison is ascii collating order
+ * or by feet of typesetter film, according to sort.
+ */
+
+qucmp(left, right)
+       struct hent **left, **right;
+{
+       register struct hent *h1, *h2;
+       register int r;
+
+       h1 = *left;
+       h2 = *right;
+       if (sort)
+               r = h1->h_feet < h2->h_feet ? -1 : h1->h_feet > h2->h_feet;
+       else
+               r = strcmp(h1->h_name, h2->h_name);
+       return(reverse ? -r : r);
+}