1262821Sadrian/*-
2262821Sadrian * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3262821Sadrian * All rights reserved.
4262821Sadrian *
5262821Sadrian * Redistribution and use in source and binary forms, with or without
6262821Sadrian * modification, are permitted provided that the following conditions
7262821Sadrian * are met:
8262821Sadrian * 1. Redistributions of source code must retain the above copyright
9262821Sadrian *    notice, this list of conditions and the following disclaimer,
10262821Sadrian *    without modification.
11262821Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12262821Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13262821Sadrian *    redistribution must be conditioned upon including a substantially
14262821Sadrian *    similar Disclaimer requirement for further binary redistribution.
15262821Sadrian *
16262821Sadrian * NO WARRANTY
17262821Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18262821Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19262821Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20262821Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21262821Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22262821Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23262821Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24262821Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25262821Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26262821Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27262821Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28262821Sadrian *
29262821Sadrian * $FreeBSD$
30262821Sadrian */
31262821Sadrian
32262821Sadrian#include <stdio.h>
33262821Sadrian#include <string.h>
34262821Sadrian
35262821Sadrian#include "bsdstat.h"
36262821Sadrian
37262821Sadrianstatic void
38262821Sadrianbsdstat_setfmt(struct bsdstat *sf, const char *fmt0)
39262821Sadrian{
40262821Sadrian#define	N(a)	(sizeof(a)/sizeof(a[0]))
41262821Sadrian	char fmt[4096];
42262821Sadrian	char *fp, *tok;
43262821Sadrian	int i, j;
44262821Sadrian
45262821Sadrian	j = 0;
46262821Sadrian	strlcpy(fmt, fmt0, sizeof(fmt));
47262821Sadrian	for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) {
48262821Sadrian		for (i = 0; i < sf->nstats; i++)
49262821Sadrian			if (strcasecmp(tok, sf->stats[i].name) == 0)
50262821Sadrian				break;
51262821Sadrian		if (i >= sf->nstats) {
52262821Sadrian			fprintf(stderr, "%s: unknown statistic name \"%s\" "
53262821Sadrian				"skipped\n", sf->name, tok);
54262821Sadrian			continue;
55262821Sadrian		}
56299950Struckman		if (j+4 > (int) sizeof(sf->fmts)) {
57262821Sadrian			fprintf(stderr, "%s: not enough room for all stats; "
58262821Sadrian				"stopped at %s\n", sf->name, tok);
59262821Sadrian			break;
60262821Sadrian		}
61262821Sadrian		if (j != 0)
62262821Sadrian			sf->fmts[j++] = ' ';
63262821Sadrian		sf->fmts[j++] = FMTS_IS_STAT;
64262821Sadrian		sf->fmts[j++] = i & 0xff;
65262821Sadrian		sf->fmts[j++] = (i >> 8) & 0xff;
66262821Sadrian	}
67262821Sadrian	sf->fmts[j] = '\0';
68262821Sadrian#undef N
69262821Sadrian}
70262821Sadrian
71262821Sadrianstatic void
72262821Sadrianbsdstat_collect(struct bsdstat *sf)
73262821Sadrian{
74262821Sadrian	fprintf(stderr, "%s: don't know how to collect data\n", sf->name);
75262821Sadrian}
76262821Sadrian
77262821Sadrianstatic void
78262821Sadrianbsdstat_update_tot(struct bsdstat *sf)
79262821Sadrian{
80262821Sadrian	fprintf(stderr, "%s: don't know how to update total data\n", sf->name);
81262821Sadrian}
82262821Sadrian
83262821Sadrianstatic int
84262992Seadlerbsdstat_get(struct bsdstat *sf, int s, char b[] __unused, size_t bs __unused)
85262821Sadrian{
86262821Sadrian	fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s);
87262821Sadrian	return 0;
88262821Sadrian}
89262821Sadrian
90262821Sadrianstatic void
91262821Sadrianbsdstat_print_header(struct bsdstat *sf, FILE *fd)
92262821Sadrian{
93262821Sadrian	const unsigned char *cp;
94262821Sadrian	int i;
95262821Sadrian	const struct fmt *f;
96262821Sadrian
97262821Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
98262821Sadrian		if (*cp == FMTS_IS_STAT) {
99262821Sadrian			i = *(++cp);
100262821Sadrian			i |= ((int) *(++cp)) << 8;
101262821Sadrian			f = &sf->stats[i];
102262821Sadrian			fprintf(fd, "%*s", f->width, f->label);
103262821Sadrian		} else
104262821Sadrian			putc(*cp, fd);
105262821Sadrian	}
106262821Sadrian	putc('\n', fd);
107262821Sadrian}
108262821Sadrian
109262821Sadrianstatic void
110262821Sadrianbsdstat_print_current(struct bsdstat *sf, FILE *fd)
111262821Sadrian{
112262821Sadrian	char buf[32];
113262821Sadrian	const unsigned char *cp;
114262821Sadrian	int i;
115262821Sadrian	const struct fmt *f;
116262821Sadrian
117262821Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
118262821Sadrian		if (*cp == FMTS_IS_STAT) {
119262821Sadrian			i = *(++cp);
120262821Sadrian			i |= ((int) *(++cp)) << 8;
121262821Sadrian			f = &sf->stats[i];
122262821Sadrian			if (sf->get_curstat(sf, i, buf, sizeof(buf)))
123262821Sadrian				fprintf(fd, "%*s", f->width, buf);
124262821Sadrian		} else
125262821Sadrian			putc(*cp, fd);
126262821Sadrian	}
127262821Sadrian	putc('\n', fd);
128262821Sadrian}
129262821Sadrian
130262821Sadrianstatic void
131262821Sadrianbsdstat_print_total(struct bsdstat *sf, FILE *fd)
132262821Sadrian{
133262821Sadrian	char buf[32];
134262821Sadrian	const unsigned char *cp;
135262821Sadrian	const struct fmt *f;
136262821Sadrian	int i;
137262821Sadrian
138262821Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
139262821Sadrian		if (*cp == FMTS_IS_STAT) {
140262821Sadrian			i = *(++cp);
141262821Sadrian			i |= ((int) *(++cp)) << 8;
142262821Sadrian			f = &sf->stats[i];
143262821Sadrian			if (sf->get_totstat(sf, i, buf, sizeof(buf)))
144262821Sadrian				fprintf(fd, "%*s", f->width, buf);
145262821Sadrian		} else
146262821Sadrian			putc(*cp, fd);
147262821Sadrian	}
148262821Sadrian	putc('\n', fd);
149262821Sadrian}
150262821Sadrian
151262821Sadrianstatic void
152262821Sadrianbsdstat_print_verbose(struct bsdstat *sf, FILE *fd)
153262821Sadrian{
154262821Sadrian	const struct fmt *f;
155262821Sadrian	char s[32];
156262821Sadrian	int i, width;
157262821Sadrian
158262821Sadrian	width = 0;
159262821Sadrian	for (i = 0; i < sf->nstats; i++) {
160262821Sadrian		f = &sf->stats[i];
161262821Sadrian		if (f->width > width)
162262821Sadrian			width = f->width;
163262821Sadrian	}
164262821Sadrian	for (i = 0; i < sf->nstats; i++) {
165262821Sadrian		f = &sf->stats[i];
166262821Sadrian		if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0"))
167262821Sadrian			fprintf(fd, "%-*s %s\n", width, s, f->desc);
168262821Sadrian	}
169262821Sadrian}
170262821Sadrian
171262821Sadrianstatic void
172262821Sadrianbsdstat_print_fields(struct bsdstat *sf, FILE *fd)
173262821Sadrian{
174262821Sadrian	int i, w, width;
175262821Sadrian
176262821Sadrian	width = 0;
177262821Sadrian	for (i = 0; i < sf->nstats; i++) {
178262821Sadrian		w = strlen(sf->stats[i].name);
179262821Sadrian		if (w > width)
180262821Sadrian			width = w;
181262821Sadrian	}
182262821Sadrian	for (i = 0; i < sf->nstats; i++) {
183262821Sadrian		const struct fmt *f = &sf->stats[i];
184262821Sadrian		if (f->width != 0)
185262821Sadrian			fprintf(fd, "%-*s %s\n", width, f->name, f->desc);
186262821Sadrian	}
187262821Sadrian}
188262821Sadrian
189262821Sadrianvoid
190262821Sadrianbsdstat_init(struct bsdstat *sf, const char *name, const struct fmt *stats, int nstats)
191262821Sadrian{
192262821Sadrian	sf->name = name;
193262821Sadrian	sf->stats = stats;
194262821Sadrian	sf->nstats = nstats;
195262821Sadrian	sf->setfmt = bsdstat_setfmt;
196262821Sadrian	sf->collect_cur = bsdstat_collect;
197262821Sadrian	sf->collect_tot = bsdstat_collect;
198262821Sadrian	sf->update_tot = bsdstat_update_tot;
199262821Sadrian	sf->get_curstat = bsdstat_get;
200262821Sadrian	sf->get_totstat = bsdstat_get;
201262821Sadrian	sf->print_header = bsdstat_print_header;
202262821Sadrian	sf->print_current = bsdstat_print_current;
203262821Sadrian	sf->print_total = bsdstat_print_total;
204262821Sadrian	sf->print_verbose = bsdstat_print_verbose;
205262821Sadrian	sf->print_fields = bsdstat_print_fields;
206262821Sadrian}
207