xref: /freebsd/lib/libbsdstat/bsdstat.c (revision 81bd3d89e8676d6ebf38382a842c696e60696a20)
1*81bd3d89SAdrian Chadd /*-
2*81bd3d89SAdrian Chadd  * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3*81bd3d89SAdrian Chadd  * All rights reserved.
4*81bd3d89SAdrian Chadd  *
5*81bd3d89SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
6*81bd3d89SAdrian Chadd  * modification, are permitted provided that the following conditions
7*81bd3d89SAdrian Chadd  * are met:
8*81bd3d89SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
9*81bd3d89SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
10*81bd3d89SAdrian Chadd  *    without modification.
11*81bd3d89SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12*81bd3d89SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13*81bd3d89SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
14*81bd3d89SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
15*81bd3d89SAdrian Chadd  *
16*81bd3d89SAdrian Chadd  * NO WARRANTY
17*81bd3d89SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*81bd3d89SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*81bd3d89SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20*81bd3d89SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21*81bd3d89SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22*81bd3d89SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*81bd3d89SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*81bd3d89SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*81bd3d89SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*81bd3d89SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27*81bd3d89SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
28*81bd3d89SAdrian Chadd  *
29*81bd3d89SAdrian Chadd  * $FreeBSD$
30*81bd3d89SAdrian Chadd  */
31*81bd3d89SAdrian Chadd 
32*81bd3d89SAdrian Chadd #include <stdio.h>
33*81bd3d89SAdrian Chadd #include <string.h>
34*81bd3d89SAdrian Chadd 
35*81bd3d89SAdrian Chadd #include "bsdstat.h"
36*81bd3d89SAdrian Chadd 
37*81bd3d89SAdrian Chadd static void
38*81bd3d89SAdrian Chadd bsdstat_setfmt(struct bsdstat *sf, const char *fmt0)
39*81bd3d89SAdrian Chadd {
40*81bd3d89SAdrian Chadd #define	N(a)	(sizeof(a)/sizeof(a[0]))
41*81bd3d89SAdrian Chadd 	char fmt[4096];
42*81bd3d89SAdrian Chadd 	char *fp, *tok;
43*81bd3d89SAdrian Chadd 	int i, j;
44*81bd3d89SAdrian Chadd 
45*81bd3d89SAdrian Chadd 	j = 0;
46*81bd3d89SAdrian Chadd 	strlcpy(fmt, fmt0, sizeof(fmt));
47*81bd3d89SAdrian Chadd 	for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) {
48*81bd3d89SAdrian Chadd 		for (i = 0; i < sf->nstats; i++)
49*81bd3d89SAdrian Chadd 			if (strcasecmp(tok, sf->stats[i].name) == 0)
50*81bd3d89SAdrian Chadd 				break;
51*81bd3d89SAdrian Chadd 		if (i >= sf->nstats) {
52*81bd3d89SAdrian Chadd 			fprintf(stderr, "%s: unknown statistic name \"%s\" "
53*81bd3d89SAdrian Chadd 				"skipped\n", sf->name, tok);
54*81bd3d89SAdrian Chadd 			continue;
55*81bd3d89SAdrian Chadd 		}
56*81bd3d89SAdrian Chadd 		if (j+3 > (int) sizeof(sf->fmts)) {
57*81bd3d89SAdrian Chadd 			fprintf(stderr, "%s: not enough room for all stats; "
58*81bd3d89SAdrian Chadd 				"stopped at %s\n", sf->name, tok);
59*81bd3d89SAdrian Chadd 			break;
60*81bd3d89SAdrian Chadd 		}
61*81bd3d89SAdrian Chadd 		if (j != 0)
62*81bd3d89SAdrian Chadd 			sf->fmts[j++] = ' ';
63*81bd3d89SAdrian Chadd 		sf->fmts[j++] = FMTS_IS_STAT;
64*81bd3d89SAdrian Chadd 		sf->fmts[j++] = i & 0xff;
65*81bd3d89SAdrian Chadd 		sf->fmts[j++] = (i >> 8) & 0xff;
66*81bd3d89SAdrian Chadd 	}
67*81bd3d89SAdrian Chadd 	sf->fmts[j] = '\0';
68*81bd3d89SAdrian Chadd #undef N
69*81bd3d89SAdrian Chadd }
70*81bd3d89SAdrian Chadd 
71*81bd3d89SAdrian Chadd static void
72*81bd3d89SAdrian Chadd bsdstat_collect(struct bsdstat *sf)
73*81bd3d89SAdrian Chadd {
74*81bd3d89SAdrian Chadd 	fprintf(stderr, "%s: don't know how to collect data\n", sf->name);
75*81bd3d89SAdrian Chadd }
76*81bd3d89SAdrian Chadd 
77*81bd3d89SAdrian Chadd static void
78*81bd3d89SAdrian Chadd bsdstat_update_tot(struct bsdstat *sf)
79*81bd3d89SAdrian Chadd {
80*81bd3d89SAdrian Chadd 	fprintf(stderr, "%s: don't know how to update total data\n", sf->name);
81*81bd3d89SAdrian Chadd }
82*81bd3d89SAdrian Chadd 
83*81bd3d89SAdrian Chadd static int
84*81bd3d89SAdrian Chadd bsdstat_get(struct bsdstat *sf, int s, char b[], size_t bs)
85*81bd3d89SAdrian Chadd {
86*81bd3d89SAdrian Chadd 	fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s);
87*81bd3d89SAdrian Chadd 	return 0;
88*81bd3d89SAdrian Chadd }
89*81bd3d89SAdrian Chadd 
90*81bd3d89SAdrian Chadd static void
91*81bd3d89SAdrian Chadd bsdstat_print_header(struct bsdstat *sf, FILE *fd)
92*81bd3d89SAdrian Chadd {
93*81bd3d89SAdrian Chadd 	const unsigned char *cp;
94*81bd3d89SAdrian Chadd 	int i;
95*81bd3d89SAdrian Chadd 	const struct fmt *f;
96*81bd3d89SAdrian Chadd 
97*81bd3d89SAdrian Chadd 	for (cp = sf->fmts; *cp != '\0'; cp++) {
98*81bd3d89SAdrian Chadd 		if (*cp == FMTS_IS_STAT) {
99*81bd3d89SAdrian Chadd 			i = *(++cp);
100*81bd3d89SAdrian Chadd 			i |= ((int) *(++cp)) << 8;
101*81bd3d89SAdrian Chadd 			f = &sf->stats[i];
102*81bd3d89SAdrian Chadd 			fprintf(fd, "%*s", f->width, f->label);
103*81bd3d89SAdrian Chadd 		} else
104*81bd3d89SAdrian Chadd 			putc(*cp, fd);
105*81bd3d89SAdrian Chadd 	}
106*81bd3d89SAdrian Chadd 	putc('\n', fd);
107*81bd3d89SAdrian Chadd }
108*81bd3d89SAdrian Chadd 
109*81bd3d89SAdrian Chadd static void
110*81bd3d89SAdrian Chadd bsdstat_print_current(struct bsdstat *sf, FILE *fd)
111*81bd3d89SAdrian Chadd {
112*81bd3d89SAdrian Chadd 	char buf[32];
113*81bd3d89SAdrian Chadd 	const unsigned char *cp;
114*81bd3d89SAdrian Chadd 	int i;
115*81bd3d89SAdrian Chadd 	const struct fmt *f;
116*81bd3d89SAdrian Chadd 
117*81bd3d89SAdrian Chadd 	for (cp = sf->fmts; *cp != '\0'; cp++) {
118*81bd3d89SAdrian Chadd 		if (*cp == FMTS_IS_STAT) {
119*81bd3d89SAdrian Chadd 			i = *(++cp);
120*81bd3d89SAdrian Chadd 			i |= ((int) *(++cp)) << 8;
121*81bd3d89SAdrian Chadd 			f = &sf->stats[i];
122*81bd3d89SAdrian Chadd 			if (sf->get_curstat(sf, i, buf, sizeof(buf)))
123*81bd3d89SAdrian Chadd 				fprintf(fd, "%*s", f->width, buf);
124*81bd3d89SAdrian Chadd 		} else
125*81bd3d89SAdrian Chadd 			putc(*cp, fd);
126*81bd3d89SAdrian Chadd 	}
127*81bd3d89SAdrian Chadd 	putc('\n', fd);
128*81bd3d89SAdrian Chadd }
129*81bd3d89SAdrian Chadd 
130*81bd3d89SAdrian Chadd static void
131*81bd3d89SAdrian Chadd bsdstat_print_total(struct bsdstat *sf, FILE *fd)
132*81bd3d89SAdrian Chadd {
133*81bd3d89SAdrian Chadd 	char buf[32];
134*81bd3d89SAdrian Chadd 	const unsigned char *cp;
135*81bd3d89SAdrian Chadd 	const struct fmt *f;
136*81bd3d89SAdrian Chadd 	int i;
137*81bd3d89SAdrian Chadd 
138*81bd3d89SAdrian Chadd 	for (cp = sf->fmts; *cp != '\0'; cp++) {
139*81bd3d89SAdrian Chadd 		if (*cp == FMTS_IS_STAT) {
140*81bd3d89SAdrian Chadd 			i = *(++cp);
141*81bd3d89SAdrian Chadd 			i |= ((int) *(++cp)) << 8;
142*81bd3d89SAdrian Chadd 			f = &sf->stats[i];
143*81bd3d89SAdrian Chadd 			if (sf->get_totstat(sf, i, buf, sizeof(buf)))
144*81bd3d89SAdrian Chadd 				fprintf(fd, "%*s", f->width, buf);
145*81bd3d89SAdrian Chadd 		} else
146*81bd3d89SAdrian Chadd 			putc(*cp, fd);
147*81bd3d89SAdrian Chadd 	}
148*81bd3d89SAdrian Chadd 	putc('\n', fd);
149*81bd3d89SAdrian Chadd }
150*81bd3d89SAdrian Chadd 
151*81bd3d89SAdrian Chadd static void
152*81bd3d89SAdrian Chadd bsdstat_print_verbose(struct bsdstat *sf, FILE *fd)
153*81bd3d89SAdrian Chadd {
154*81bd3d89SAdrian Chadd 	const struct fmt *f;
155*81bd3d89SAdrian Chadd 	char s[32];
156*81bd3d89SAdrian Chadd 	int i, width;
157*81bd3d89SAdrian Chadd 
158*81bd3d89SAdrian Chadd 	width = 0;
159*81bd3d89SAdrian Chadd 	for (i = 0; i < sf->nstats; i++) {
160*81bd3d89SAdrian Chadd 		f = &sf->stats[i];
161*81bd3d89SAdrian Chadd 		if (f->width > width)
162*81bd3d89SAdrian Chadd 			width = f->width;
163*81bd3d89SAdrian Chadd 	}
164*81bd3d89SAdrian Chadd 	for (i = 0; i < sf->nstats; i++) {
165*81bd3d89SAdrian Chadd 		f = &sf->stats[i];
166*81bd3d89SAdrian Chadd 		if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0"))
167*81bd3d89SAdrian Chadd 			fprintf(fd, "%-*s %s\n", width, s, f->desc);
168*81bd3d89SAdrian Chadd 	}
169*81bd3d89SAdrian Chadd }
170*81bd3d89SAdrian Chadd 
171*81bd3d89SAdrian Chadd static void
172*81bd3d89SAdrian Chadd bsdstat_print_fields(struct bsdstat *sf, FILE *fd)
173*81bd3d89SAdrian Chadd {
174*81bd3d89SAdrian Chadd 	int i, w, width;
175*81bd3d89SAdrian Chadd 
176*81bd3d89SAdrian Chadd 	width = 0;
177*81bd3d89SAdrian Chadd 	for (i = 0; i < sf->nstats; i++) {
178*81bd3d89SAdrian Chadd 		w = strlen(sf->stats[i].name);
179*81bd3d89SAdrian Chadd 		if (w > width)
180*81bd3d89SAdrian Chadd 			width = w;
181*81bd3d89SAdrian Chadd 	}
182*81bd3d89SAdrian Chadd 	for (i = 0; i < sf->nstats; i++) {
183*81bd3d89SAdrian Chadd 		const struct fmt *f = &sf->stats[i];
184*81bd3d89SAdrian Chadd 		if (f->width != 0)
185*81bd3d89SAdrian Chadd 			fprintf(fd, "%-*s %s\n", width, f->name, f->desc);
186*81bd3d89SAdrian Chadd 	}
187*81bd3d89SAdrian Chadd }
188*81bd3d89SAdrian Chadd 
189*81bd3d89SAdrian Chadd void
190*81bd3d89SAdrian Chadd bsdstat_init(struct bsdstat *sf, const char *name, const struct fmt *stats, int nstats)
191*81bd3d89SAdrian Chadd {
192*81bd3d89SAdrian Chadd 	sf->name = name;
193*81bd3d89SAdrian Chadd 	sf->stats = stats;
194*81bd3d89SAdrian Chadd 	sf->nstats = nstats;
195*81bd3d89SAdrian Chadd 	sf->setfmt = bsdstat_setfmt;
196*81bd3d89SAdrian Chadd 	sf->collect_cur = bsdstat_collect;
197*81bd3d89SAdrian Chadd 	sf->collect_tot = bsdstat_collect;
198*81bd3d89SAdrian Chadd 	sf->update_tot = bsdstat_update_tot;
199*81bd3d89SAdrian Chadd 	sf->get_curstat = bsdstat_get;
200*81bd3d89SAdrian Chadd 	sf->get_totstat = bsdstat_get;
201*81bd3d89SAdrian Chadd 	sf->print_header = bsdstat_print_header;
202*81bd3d89SAdrian Chadd 	sf->print_current = bsdstat_print_current;
203*81bd3d89SAdrian Chadd 	sf->print_total = bsdstat_print_total;
204*81bd3d89SAdrian Chadd 	sf->print_verbose = bsdstat_print_verbose;
205*81bd3d89SAdrian Chadd 	sf->print_fields = bsdstat_print_fields;
206*81bd3d89SAdrian Chadd }
207