Annotation of 43BSD/usr.lib/lpr/pac.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)pac.c      5.2 (Berkeley) 10/30/85";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * Do Printer accounting summary.
                     19:  * Currently, usage is
                     20:  *     pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...]
                     21:  * to print the usage information for the named people.
                     22:  */
                     23: 
                     24: #include <stdio.h>
                     25: #include "lp.local.h"
                     26: 
                     27: char   *printer;                       /* printer name */
                     28: char   *acctfile;                      /* accounting file (input data) */
                     29: char   *sumfile;                       /* summary file */
                     30: float  price = 0.02;                   /* cost per page (or what ever) */
                     31: int    allflag = 1;                    /* Get stats on everybody */
                     32: int    sort;                           /* Sort by cost */
                     33: int    summarize;                      /* Compress accounting file */
                     34: int    reverse;                        /* Reverse sort order */
                     35: int    hcount;                         /* Count of hash entries */
                     36: int    errs;
                     37: int    mflag = 0;                      /* disregard machine names */
                     38: int    pflag = 0;                      /* 1 if -p on cmd line */
                     39: int    price100;                       /* per-page cost in 100th of a cent */
                     40: char   *index();
                     41: int    pgetnum();
                     42: 
                     43: /*
                     44:  * Grossness follows:
                     45:  *  Names to be accumulated are hashed into the following
                     46:  *  table.
                     47:  */
                     48: 
                     49: #define        HSHSIZE 97                      /* Number of hash buckets */
                     50: 
                     51: struct hent {
                     52:        struct  hent *h_link;           /* Forward hash link */
                     53:        char    *h_name;                /* Name of this user */
                     54:        float   h_feetpages;            /* Feet or pages of paper */
                     55:        int     h_count;                /* Number of runs */
                     56: };
                     57: 
                     58: struct hent    *hashtab[HSHSIZE];      /* Hash table proper */
                     59: struct hent    *enter();
                     60: struct hent    *lookup();
                     61: 
                     62: #define        NIL     ((struct hent *) 0)     /* The big zero */
                     63: 
                     64: double atof();
                     65: char   *getenv();
                     66: char   *pgetstr();
                     67: 
                     68: main(argc, argv)
                     69:        char **argv;
                     70: {
                     71:        register FILE *acct;
                     72:        register char *cp;
                     73: 
                     74:        while (--argc) {
                     75:                cp = *++argv;
                     76:                if (*cp++ == '-') {
                     77:                        switch(*cp++) {
                     78:                        case 'P':
                     79:                                /*
                     80:                                 * Printer name.
                     81:                                 */
                     82:                                printer = cp;
                     83:                                continue;
                     84: 
                     85:                        case 'p':
                     86:                                /*
                     87:                                 * get the price.
                     88:                                 */
                     89:                                price = atof(cp);
                     90:                                pflag = 1;
                     91:                                continue;
                     92: 
                     93:                        case 's':
                     94:                                /*
                     95:                                 * Summarize and compress accounting file.
                     96:                                 */
                     97:                                summarize++;
                     98:                                continue;
                     99: 
                    100:                        case 'c':
                    101:                                /*
                    102:                                 * Sort by cost.
                    103:                                 */
                    104:                                sort++;
                    105:                                continue;
                    106: 
                    107:                        case 'm':
                    108:                                /*
                    109:                                 * disregard machine names for each user
                    110:                                 */
                    111:                                mflag = 1;
                    112:                                continue;
                    113: 
                    114:                        case 'r':
                    115:                                /*
                    116:                                 * Reverse sorting order.
                    117:                                 */
                    118:                                reverse++;
                    119:                                continue;
                    120: 
                    121:                        default:
                    122: fprintf(stderr,
                    123:     "usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n");
                    124:                                exit(1);
                    125:                        }
                    126:                }
                    127:                (void) enter(--cp);
                    128:                allflag = 0;
                    129:        }
                    130:        if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
                    131:                printer = DEFLP;
                    132:        if (!chkprinter(printer)) {
                    133:                printf("pac: unknown printer %s\n", printer);
                    134:                exit(2);
                    135:        }
                    136: 
                    137:        if ((acct = fopen(acctfile, "r")) == NULL) {
                    138:                perror(acctfile);
                    139:                exit(1);
                    140:        }
                    141:        account(acct);
                    142:        fclose(acct);
                    143:        if ((acct = fopen(sumfile, "r")) != NULL) {
                    144:                account(acct);
                    145:                fclose(acct);
                    146:        }
                    147:        if (summarize)
                    148:                rewrite();
                    149:        else
                    150:                dumpit();
                    151:        exit(errs);
                    152: }
                    153: 
                    154: /*
                    155:  * Read the entire accounting file, accumulating statistics
                    156:  * for the users that we have in the hash table.  If allflag
                    157:  * is set, then just gather the facts on everyone.
                    158:  * Note that we must accomodate both the active and summary file
                    159:  * formats here.
                    160:  * Host names are ignored if the -m flag is present.
                    161:  */
                    162: 
                    163: account(acct)
                    164:        register FILE *acct;
                    165: {
                    166:        char linebuf[BUFSIZ];
                    167:        double t;
                    168:        register char *cp, *cp2;
                    169:        register struct hent *hp;
                    170:        register int ic;
                    171: 
                    172:        while (fgets(linebuf, BUFSIZ, acct) != NULL) {
                    173:                cp = linebuf;
                    174:                while (any(*cp, " t\t"))
                    175:                        cp++;
                    176:                t = atof(cp);
                    177:                while (any(*cp, ".0123456789"))
                    178:                        cp++;
                    179:                while (any(*cp, " \t"))
                    180:                        cp++;
                    181:                for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
                    182:                        ;
                    183:                ic = atoi(cp2);
                    184:                *cp2 = '\0';
                    185:                if (mflag && index(cp, ':'))
                    186:                    cp = index(cp, ':') + 1;
                    187:                hp = lookup(cp);
                    188:                if (hp == NIL) {
                    189:                        if (!allflag)
                    190:                                continue;
                    191:                        hp = enter(cp);
                    192:                }
                    193:                hp->h_feetpages += t;
                    194:                if (ic)
                    195:                        hp->h_count += ic;
                    196:                else
                    197:                        hp->h_count++;
                    198:        }
                    199: }
                    200: 
                    201: /*
                    202:  * Sort the hashed entries by name or footage
                    203:  * and print it all out.
                    204:  */
                    205: 
                    206: dumpit()
                    207: {
                    208:        struct hent **base;
                    209:        register struct hent *hp, **ap;
                    210:        register int hno, c, runs;
                    211:        float feet;
                    212:        int qucmp();
                    213: 
                    214:        hp = hashtab[0];
                    215:        hno = 1;
                    216:        base = (struct hent **) calloc(sizeof hp, hcount);
                    217:        for (ap = base, c = hcount; c--; ap++) {
                    218:                while (hp == NIL)
                    219:                        hp = hashtab[hno++];
                    220:                *ap = hp;
                    221:                hp = hp->h_link;
                    222:        }
                    223:        qsort(base, hcount, sizeof hp, qucmp);
                    224:        printf("  Login               pages/feet   runs    price\n");
                    225:        feet = 0.0;
                    226:        runs = 0;
                    227:        for (ap = base, c = hcount; c--; ap++) {
                    228:                hp = *ap;
                    229:                runs += hp->h_count;
                    230:                feet += hp->h_feetpages;
                    231:                printf("%-24s %7.2f %4d   $%6.2f\n", hp->h_name,
                    232:                    hp->h_feetpages, hp->h_count, hp->h_feetpages * price);
                    233:        }
                    234:        if (allflag) {
                    235:                printf("\n");
                    236:                printf("%-24s %7.2f %4d   $%6.2f\n", "total", feet, 
                    237:                    runs, feet * price);
                    238:        }
                    239: }
                    240: 
                    241: /*
                    242:  * Rewrite the summary file with the summary information we have accumulated.
                    243:  */
                    244: 
                    245: rewrite()
                    246: {
                    247:        register struct hent *hp;
                    248:        register int i;
                    249:        register FILE *acctf;
                    250: 
                    251:        if ((acctf = fopen(sumfile, "w")) == NULL) {
                    252:                perror(sumfile);
                    253:                errs++;
                    254:                return;
                    255:        }
                    256:        for (i = 0; i < HSHSIZE; i++) {
                    257:                hp = hashtab[i];
                    258:                while (hp != NULL) {
                    259:                        fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
                    260:                            hp->h_name, hp->h_count);
                    261:                        hp = hp->h_link;
                    262:                }
                    263:        }
                    264:        fflush(acctf);
                    265:        if (ferror(acctf)) {
                    266:                perror(sumfile);
                    267:                errs++;
                    268:        }
                    269:        fclose(acctf);
                    270:        if ((acctf = fopen(acctfile, "w")) == NULL)
                    271:                perror(acctfile);
                    272:        else
                    273:                fclose(acctf);
                    274: }
                    275: 
                    276: /*
                    277:  * Hashing routines.
                    278:  */
                    279: 
                    280: /*
                    281:  * Enter the name into the hash table and return the pointer allocated.
                    282:  */
                    283: 
                    284: struct hent *
                    285: enter(name)
                    286:        char name[];
                    287: {
                    288:        register struct hent *hp;
                    289:        register int h;
                    290: 
                    291:        if ((hp = lookup(name)) != NIL)
                    292:                return(hp);
                    293:        h = hash(name);
                    294:        hcount++;
                    295:        hp = (struct hent *) calloc(sizeof *hp, 1);
                    296:        hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1);
                    297:        strcpy(hp->h_name, name);
                    298:        hp->h_feetpages = 0.0;
                    299:        hp->h_count = 0;
                    300:        hp->h_link = hashtab[h];
                    301:        hashtab[h] = hp;
                    302:        return(hp);
                    303: }
                    304: 
                    305: /*
                    306:  * Lookup a name in the hash table and return a pointer
                    307:  * to it.
                    308:  */
                    309: 
                    310: struct hent *
                    311: lookup(name)
                    312:        char name[];
                    313: {
                    314:        register int h;
                    315:        register struct hent *hp;
                    316: 
                    317:        h = hash(name);
                    318:        for (hp = hashtab[h]; hp != NIL; hp = hp->h_link)
                    319:                if (strcmp(hp->h_name, name) == 0)
                    320:                        return(hp);
                    321:        return(NIL);
                    322: }
                    323: 
                    324: /*
                    325:  * Hash the passed name and return the index in
                    326:  * the hash table to begin the search.
                    327:  */
                    328: 
                    329: hash(name)
                    330:        char name[];
                    331: {
                    332:        register int h;
                    333:        register char *cp;
                    334: 
                    335:        for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
                    336:                ;
                    337:        return((h & 0x7fffffff) % HSHSIZE);
                    338: }
                    339: 
                    340: /*
                    341:  * Other stuff
                    342:  */
                    343: 
                    344: any(ch, str)
                    345:        char str[];
                    346: {
                    347:        register int c = ch;
                    348:        register char *cp = str;
                    349: 
                    350:        while (*cp)
                    351:                if (*cp++ == c)
                    352:                        return(1);
                    353:        return(0);
                    354: }
                    355: 
                    356: /*
                    357:  * The qsort comparison routine.
                    358:  * The comparison is ascii collating order
                    359:  * or by feet of typesetter film, according to sort.
                    360:  */
                    361: 
                    362: qucmp(left, right)
                    363:        struct hent **left, **right;
                    364: {
                    365:        register struct hent *h1, *h2;
                    366:        register int r;
                    367: 
                    368:        h1 = *left;
                    369:        h2 = *right;
                    370:        if (sort)
                    371:                r = h1->h_feetpages < h2->h_feetpages ? -1 : h1->h_feetpages > 
                    372: h2->h_feetpages;
                    373:        else
                    374:                r = strcmp(h1->h_name, h2->h_name);
                    375:        return(reverse ? -r : r);
                    376: }
                    377: 
                    378: /*
                    379:  * Perform lookup for printer name or abbreviation --
                    380:  */
                    381: chkprinter(s)
                    382:        register char *s;
                    383: {
                    384:        static char buf[BUFSIZ/2];
                    385:        char b[BUFSIZ];
                    386:        int stat;
                    387:        char *bp = buf;
                    388: 
                    389:        if ((stat = pgetent(b, s)) < 0) {
                    390:                printf("pac: can't open printer description file\n");
                    391:                exit(3);
                    392:        } else if (stat == 0)
                    393:                return(0);
                    394:        if ((acctfile = pgetstr("af", &bp)) == NULL) {
                    395:                printf("accounting not enabled for printer %s\n", printer);
                    396:                exit(2);
                    397:        }
                    398:        if (!pflag && (price100 = pgetnum("pc")) > 0)
                    399:                price = price100/10000.0;
                    400:        sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
                    401:        if (sumfile == NULL) {
                    402:                perror("pac");
                    403:                exit(1);
                    404:        }
                    405:        strcpy(sumfile, acctfile);
                    406:        strcat(sumfile, "_sum");
                    407:        return(1);
                    408: }

unix.superglobalmegacorp.com

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