Annotation of 3BSD/cmd/versatec/vpac.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.