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

unix.superglobalmegacorp.com

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