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

unix.superglobalmegacorp.com

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