xref: /csrg-svn/old/vpr/vpac.c (revision 7691)
1*7691Smckusick static char sccsid[] = "@(#)vpac.c	1.2	(Berkeley)	08/08/82";
21848Sroot 
31848Sroot #include <stdio.h>
41848Sroot 
51848Sroot /*
61848Sroot  * Do Versatec and Varian accounting summary.
71848Sroot  * Currently, usage is
81848Sroot  *	vpac [-srW] [user] ...
91848Sroot  * to print the usage information for the named people.
101848Sroot  */
111848Sroot 
121848Sroot int	errs;
131848Sroot 
141848Sroot #define VAACCT		"/usr/adm/vaacct"
151848Sroot #define VASUM		"/usr/adm/va_sum"
161848Sroot #define VPACCT		"/usr/adm/vpacct"
171848Sroot #define VPSUM		"/usr/adm/vp_sum"
181848Sroot char	*acctfile;
191848Sroot char	*sumfile;
201848Sroot 
211848Sroot #define	VAPRICE	0.02			/* Dollars per page */
221848Sroot #define	VPPRICE	0.08			/* Dollars per foot of paper */
231848Sroot float price;
241848Sroot 
251848Sroot /*
261848Sroot  * Grossness follows:
271848Sroot  *  Names to be accumulated are hashed into the following
281848Sroot  *  table.
291848Sroot  */
301848Sroot 
311848Sroot #define	HSHSIZE	97			/* Number of hash buckets */
321848Sroot 
331848Sroot struct hent {
341848Sroot 	struct	hent *h_link;		/* Forward hash link */
351848Sroot 	char	h_name[9];		/* Name of this user */
361848Sroot 	float	h_feetpages;		/* Feet or pages of paper */
371848Sroot 	int	h_count;		/* Number of runs */
381848Sroot };
391848Sroot 
401848Sroot struct	hent	*hashtab[HSHSIZE];	/* Hash table proper */
411848Sroot struct	hent	*enter();
421848Sroot struct	hent	*lookup();
431848Sroot 
441848Sroot #define	NIL	((struct hent *) 0)	/* The big zero */
451848Sroot 
461848Sroot int	allflag;			/* Get stats on everybody */
471848Sroot int	sort;				/* Sort by cost */
481848Sroot int	summarize;			/* Compress accounting file */
491848Sroot int	reverse;			/* Reverse sort order */
501848Sroot int	wide;				/* wide paper (Versatec) accounting. */
511848Sroot 
521848Sroot int	hcount;				/* Count of hash entries */
531848Sroot 
main(argc,argv)541848Sroot main(argc, argv)
551848Sroot 	char **argv;
561848Sroot {
571848Sroot 	register FILE *acct;
581848Sroot 	register char *cp;
591848Sroot 	register int gotcha = 0;
601848Sroot 
611848Sroot 	acctfile = VAACCT;
621848Sroot 	sumfile = VASUM;
631848Sroot 	price = VAPRICE;
641848Sroot 	if (argc >= 2)
651848Sroot 		while (--argc) {
661848Sroot 			cp = *++argv;
671848Sroot 			if (*cp++ == '-') {
681848Sroot 				while (*cp) switch(*cp++) {
691848Sroot 				case 's':
701848Sroot 					/*
711848Sroot 					 * Summarize and compress
721848Sroot 					 * accounting file.
731848Sroot 					 */
741848Sroot 					summarize++;
751848Sroot 					break;
761848Sroot 
771848Sroot 				case 't':
781848Sroot 					/*
791848Sroot 					 * Sort by feet of typesetter film.
801848Sroot 					 */
811848Sroot 					sort++;
821848Sroot 					break;
831848Sroot 
841848Sroot 				case 'r':
851848Sroot 					/*
861848Sroot 					 * Reverse sorting order.
871848Sroot 					 */
881848Sroot 					reverse++;
891848Sroot 					break;
901848Sroot 
911848Sroot 				case 'W':
921848Sroot 					/*
931848Sroot 					 * Versatec, not Varian accounting.
941848Sroot 					 */
951848Sroot 					wide++;
961848Sroot 					acctfile = VPACCT;
971848Sroot 					sumfile = VPSUM;
981848Sroot 					price = VPPRICE;
991848Sroot 					break;
1001848Sroot 				default:
1011848Sroot 					fprintf(stderr, "%s?\n", *argv);
1021848Sroot 					exit(1);
1031848Sroot 				}
1041848Sroot 				continue;
1051848Sroot 			}
1061848Sroot 			ignore(enter(--cp));
1071848Sroot 			gotcha++;
1081848Sroot 		}
1091848Sroot 	allflag = gotcha == 0;
1101848Sroot 
1111848Sroot 	if ((acct = fopen(acctfile, "r")) == NULL) {
1121848Sroot 		perror(acctfile);
1131848Sroot 		exit(1);
1141848Sroot 	}
1151848Sroot 	account(acct);
1161848Sroot 	fclose(acct);
1171848Sroot 	if ((acct = fopen(sumfile, "r")) != NULL) {
1181848Sroot 		account(acct);
1191848Sroot 		fclose(acct);
1201848Sroot 	}
1211848Sroot 	if (summarize)
1221848Sroot 		rewrite();
1231848Sroot 	else
1241848Sroot 		dumpit();
1251848Sroot 	exit(errs);
1261848Sroot }
1271848Sroot 
1281848Sroot /*
1291848Sroot  * Read the entire accounting file, accumulating statistics
1301848Sroot  * for the users that we have in the hash table.  If allflag
1311848Sroot  * is set, then just gather the facts on everyone.
1321848Sroot  * Note that we must accomodate both the active and summary file
1331848Sroot  * formats here.
1341848Sroot  */
1351848Sroot 
account(acct)1361848Sroot account(acct)
1371848Sroot 	register FILE *acct;
1381848Sroot {
1391848Sroot 	char linebuf[BUFSIZ];
1401848Sroot 	float t, atof();
1411848Sroot 	register char *cp, *cp2;
1421848Sroot 	register struct hent *hp;
1431848Sroot 	register int ic;
1441848Sroot 
1451848Sroot 	while (fgets(linebuf, BUFSIZ, acct) != NULL) {
1461848Sroot 		cp = linebuf;
1471848Sroot 		while (any(*cp, " t\t"))
1481848Sroot 			cp++;
1491848Sroot 		t = atof(cp);
1501848Sroot 		while (any(*cp, ".0123456789"))
1511848Sroot 			cp++;
1521848Sroot 		while (any(*cp, " \t"))
1531848Sroot 			cp++;
1541848Sroot 		for (cp2 = cp; !any(*cp2, " \t\n"); cp2++)
1551848Sroot 			;
1561848Sroot 		ic = atoi(cp2);
1571848Sroot 		*cp2 = '\0';
1581848Sroot 		hp = lookup(cp);
1591848Sroot 		if (hp == NIL && !allflag)
1601848Sroot 			continue;
1611848Sroot 		if (hp == NIL)
1621848Sroot 			hp = enter(cp);
1631848Sroot 		hp->h_feetpages += t;
1641848Sroot 		if (ic)
1651848Sroot 			hp->h_count += ic;
1661848Sroot 		else
1671848Sroot 			hp->h_count++;
1681848Sroot 	}
1691848Sroot }
1701848Sroot 
1711848Sroot /*
1721848Sroot  * Sort the hashed entries by name or footage
1731848Sroot  * and print it all out.
1741848Sroot  */
1751848Sroot 
dumpit()1761848Sroot dumpit()
1771848Sroot {
1781848Sroot 	struct hent **base;
1791848Sroot 	register struct hent *hp, **ap;
1801848Sroot 	register int hno, c, runs;
1811848Sroot 	float feet;
1821848Sroot 	int qucmp();
1831848Sroot 
1841848Sroot 	hp = hashtab[0];
1851848Sroot 	hno = 1;
1861848Sroot 	base = (struct hent **) calloc(sizeof hp, hcount+4);
1871848Sroot 	for (ap = base, c = hcount; c--; ap++) {
1881848Sroot 		while (hp == NIL)
1891848Sroot 			hp = hashtab[hno++];
1901848Sroot 		*ap = hp;
1911848Sroot 		hp = hp->h_link;
1921848Sroot 	}
1931848Sroot 	qsort(base, hcount, sizeof hp, qucmp);
1941848Sroot 	printf(wide ? " Login    feet   runs    price\n"
1951848Sroot 		    : " Login   pages   runs    price\n");
1961848Sroot 	feet = 0.0;
1971848Sroot 	runs = 0;
1981848Sroot 	for (ap = base, c = hcount; c--; ap++) {
1991848Sroot 		hp = *ap;
2001848Sroot 		runs += hp->h_count;
2011848Sroot 		feet += hp->h_feetpages;
2021848Sroot 		printf("%-8s %7.2f %4d   $%6.2f\n", hp->h_name, hp->h_feetpages,
2031848Sroot 		    hp->h_count, hp->h_feetpages * price);
2041848Sroot 	}
2051848Sroot 	if (allflag) {
2061848Sroot 		printf("\n");
2071848Sroot 		printf("%-8s %7.2f %4d   $%6.2f\n", "total", feet,
2081848Sroot 		    runs, feet * price);
2091848Sroot 	}
2101848Sroot }
2111848Sroot 
2121848Sroot /*
2131848Sroot  * Rewrite the summary file with the summary information we have accumulated.
2141848Sroot  */
2151848Sroot 
rewrite()2161848Sroot rewrite()
2171848Sroot {
2181848Sroot 	register struct hent *hp;
2191848Sroot 	register int i;
2201848Sroot 	register FILE *acctf;
2211848Sroot 
2221848Sroot 	if ((acctf = fopen(sumfile, "w")) == NULL) {
2231848Sroot 		perror(sumfile);
2241848Sroot 		errs++;
2251848Sroot 		return;
2261848Sroot 	}
2271848Sroot 	for (i = 0; i < HSHSIZE; i++) {
2281848Sroot 		hp = hashtab[i];
2291848Sroot 		while (hp != NULL) {
2301848Sroot 			fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages,
2311848Sroot 			    hp->h_name, hp->h_count);
2321848Sroot 			hp = hp->h_link;
2331848Sroot 		}
2341848Sroot 	}
2351848Sroot 	fflush(acctf);
2361848Sroot 	if (ferror(acctf)) {
2371848Sroot 		perror(sumfile);
2381848Sroot 		errs++;
2391848Sroot 	}
2401848Sroot 	fclose(acctf);
2411848Sroot 	if ((acctf = fopen(acctfile, "w")) == NULL)
2421848Sroot 		perror(acctfile);
2431848Sroot 	else
2441848Sroot 		fclose(acctf);
2451848Sroot }
2461848Sroot 
2471848Sroot /*
2481848Sroot  * Hashing routines.
2491848Sroot  */
2501848Sroot 
2511848Sroot /*
2521848Sroot  * Enter the passed name into the hash table
2531848Sroot  * and returns the pointer allocated.
2541848Sroot  */
2551848Sroot 
2561848Sroot struct hent *
enter(name)2571848Sroot enter(name)
2581848Sroot 	char name[];
2591848Sroot {
2601848Sroot 	register struct hent *hp;
2611848Sroot 	register int h;
2621848Sroot 
2631848Sroot 	if ((hp = lookup(name)) != NIL)
2641848Sroot 		return(hp);
2651848Sroot 	h = hash(name);
2661848Sroot 	hcount++;
2671848Sroot 	hp = (struct hent *) calloc(sizeof *hp, 1);
2681848Sroot 	strcpy(hp->h_name, name);
2691848Sroot 	hp->h_feetpages = 0.0;
2701848Sroot 	hp->h_count = 0;
2711848Sroot 	hp->h_link = hashtab[h];
2721848Sroot 	hashtab[h] = hp;
2731848Sroot 	return(hp);
2741848Sroot }
2751848Sroot 
2761848Sroot /*
2771848Sroot  * Lookup a name in the hash table and return a pointer
2781848Sroot  * to it.
2791848Sroot  */
2801848Sroot 
2811848Sroot struct hent *
lookup(name)2821848Sroot lookup(name)
2831848Sroot 	char name[];
2841848Sroot {
2851848Sroot 	register int h;
2861848Sroot 	register struct hent *hp;
2871848Sroot 
2881848Sroot 	h = hash(name);
2891848Sroot 	for (hp = hashtab[h]; hp != NIL; hp = hp->h_link)
2901848Sroot 		if (strcmp(hp->h_name, name) == 0)
2911848Sroot 			return(hp);
2921848Sroot 	return(NIL);
2931848Sroot }
2941848Sroot 
2951848Sroot /*
2961848Sroot  * Hash the passed name and return the index in
2971848Sroot  * the hash table to begin the search.
2981848Sroot  */
2991848Sroot 
hash(name)3001848Sroot hash(name)
3011848Sroot 	char name[];
3021848Sroot {
3031848Sroot 	register int h;
3041848Sroot 	register char *cp;
3051848Sroot 
3061848Sroot 	for (cp = name, h = 0; *cp; h = (h << 2) + *cp++)
3071848Sroot 		;
3081848Sroot 	if (h < 0)
3091848Sroot 		h = -h;
3101848Sroot 	if (h < 0)
3111848Sroot 		h = 0;
3121848Sroot 	return(h % HSHSIZE);
3131848Sroot }
3141848Sroot 
3151848Sroot /*
3161848Sroot  * Other stuff
3171848Sroot  */
3181848Sroot 
any(ch,str)3191848Sroot any(ch, str)
3201848Sroot 	char str[];
3211848Sroot {
3221848Sroot 	register int c = ch;
3231848Sroot 	register char *cp = str;
3241848Sroot 
3251848Sroot 	while (*cp)
3261848Sroot 		if (*cp++ == c)
3271848Sroot 			return(1);
3281848Sroot 	return(0);
3291848Sroot }
3301848Sroot 
3311848Sroot /*
3321848Sroot  * Throw away a hash pointer.
3331848Sroot  */
3341848Sroot 
3351848Sroot ignore(p)
3361848Sroot 	struct hent *p;
3371848Sroot {;}
3381848Sroot 
3391848Sroot /*
3401848Sroot  * The qsort comparison routine.
3411848Sroot  * The comparison is ascii collating order
3421848Sroot  * or by feet of typesetter film, according to sort.
3431848Sroot  */
3441848Sroot 
3451848Sroot qucmp(left, right)
3461848Sroot 	struct hent **left, **right;
3471848Sroot {
3481848Sroot 	register struct hent *h1, *h2;
3491848Sroot 	register int r;
3501848Sroot 
3511848Sroot 	h1 = *left;
3521848Sroot 	h2 = *right;
3531848Sroot 	if (sort)
3541848Sroot 		r = h1->h_feetpages < h2->h_feetpages ? -1 : h1->h_feetpages > h2->h_feetpages;
3551848Sroot 	else
3561848Sroot 		r = strcmp(h1->h_name, h2->h_name);
3571848Sroot 	return(reverse ? -r : r);
3581848Sroot }
359