181bd3d89SAdrian Chadd /*- 2*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*5e53a4f9SPedro F. Giffuni * 481bd3d89SAdrian Chadd * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting 581bd3d89SAdrian Chadd * All rights reserved. 681bd3d89SAdrian Chadd * 781bd3d89SAdrian Chadd * Redistribution and use in source and binary forms, with or without 881bd3d89SAdrian Chadd * modification, are permitted provided that the following conditions 981bd3d89SAdrian Chadd * are met: 1081bd3d89SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 1181bd3d89SAdrian Chadd * notice, this list of conditions and the following disclaimer, 1281bd3d89SAdrian Chadd * without modification. 1381bd3d89SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1481bd3d89SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1581bd3d89SAdrian Chadd * redistribution must be conditioned upon including a substantially 1681bd3d89SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 1781bd3d89SAdrian Chadd * 1881bd3d89SAdrian Chadd * NO WARRANTY 1981bd3d89SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2081bd3d89SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2181bd3d89SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2281bd3d89SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2381bd3d89SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2481bd3d89SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2581bd3d89SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2681bd3d89SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2781bd3d89SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2881bd3d89SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2981bd3d89SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 3081bd3d89SAdrian Chadd * 3181bd3d89SAdrian Chadd * $FreeBSD$ 3281bd3d89SAdrian Chadd */ 3381bd3d89SAdrian Chadd 3481bd3d89SAdrian Chadd #include <stdio.h> 3581bd3d89SAdrian Chadd #include <string.h> 3681bd3d89SAdrian Chadd 3781bd3d89SAdrian Chadd #include "bsdstat.h" 3881bd3d89SAdrian Chadd 3981bd3d89SAdrian Chadd static void 4081bd3d89SAdrian Chadd bsdstat_setfmt(struct bsdstat *sf, const char *fmt0) 4181bd3d89SAdrian Chadd { 4281bd3d89SAdrian Chadd #define N(a) (sizeof(a)/sizeof(a[0])) 4381bd3d89SAdrian Chadd char fmt[4096]; 4481bd3d89SAdrian Chadd char *fp, *tok; 4581bd3d89SAdrian Chadd int i, j; 4681bd3d89SAdrian Chadd 4781bd3d89SAdrian Chadd j = 0; 4881bd3d89SAdrian Chadd strlcpy(fmt, fmt0, sizeof(fmt)); 4981bd3d89SAdrian Chadd for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) { 5081bd3d89SAdrian Chadd for (i = 0; i < sf->nstats; i++) 5181bd3d89SAdrian Chadd if (strcasecmp(tok, sf->stats[i].name) == 0) 5281bd3d89SAdrian Chadd break; 5381bd3d89SAdrian Chadd if (i >= sf->nstats) { 5481bd3d89SAdrian Chadd fprintf(stderr, "%s: unknown statistic name \"%s\" " 5581bd3d89SAdrian Chadd "skipped\n", sf->name, tok); 5681bd3d89SAdrian Chadd continue; 5781bd3d89SAdrian Chadd } 5841cee4e4SDon Lewis if (j+4 > (int) sizeof(sf->fmts)) { 5981bd3d89SAdrian Chadd fprintf(stderr, "%s: not enough room for all stats; " 6081bd3d89SAdrian Chadd "stopped at %s\n", sf->name, tok); 6181bd3d89SAdrian Chadd break; 6281bd3d89SAdrian Chadd } 6381bd3d89SAdrian Chadd if (j != 0) 6481bd3d89SAdrian Chadd sf->fmts[j++] = ' '; 6581bd3d89SAdrian Chadd sf->fmts[j++] = FMTS_IS_STAT; 6681bd3d89SAdrian Chadd sf->fmts[j++] = i & 0xff; 6781bd3d89SAdrian Chadd sf->fmts[j++] = (i >> 8) & 0xff; 6881bd3d89SAdrian Chadd } 6981bd3d89SAdrian Chadd sf->fmts[j] = '\0'; 7081bd3d89SAdrian Chadd #undef N 7181bd3d89SAdrian Chadd } 7281bd3d89SAdrian Chadd 7381bd3d89SAdrian Chadd static void 7481bd3d89SAdrian Chadd bsdstat_collect(struct bsdstat *sf) 7581bd3d89SAdrian Chadd { 7681bd3d89SAdrian Chadd fprintf(stderr, "%s: don't know how to collect data\n", sf->name); 7781bd3d89SAdrian Chadd } 7881bd3d89SAdrian Chadd 7981bd3d89SAdrian Chadd static void 8081bd3d89SAdrian Chadd bsdstat_update_tot(struct bsdstat *sf) 8181bd3d89SAdrian Chadd { 8281bd3d89SAdrian Chadd fprintf(stderr, "%s: don't know how to update total data\n", sf->name); 8381bd3d89SAdrian Chadd } 8481bd3d89SAdrian Chadd 8581bd3d89SAdrian Chadd static int 86801a8f94SEitan Adler bsdstat_get(struct bsdstat *sf, int s, char b[] __unused, size_t bs __unused) 8781bd3d89SAdrian Chadd { 8881bd3d89SAdrian Chadd fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s); 8981bd3d89SAdrian Chadd return 0; 9081bd3d89SAdrian Chadd } 9181bd3d89SAdrian Chadd 9281bd3d89SAdrian Chadd static void 9381bd3d89SAdrian Chadd bsdstat_print_header(struct bsdstat *sf, FILE *fd) 9481bd3d89SAdrian Chadd { 9581bd3d89SAdrian Chadd const unsigned char *cp; 9681bd3d89SAdrian Chadd int i; 9781bd3d89SAdrian Chadd const struct fmt *f; 9881bd3d89SAdrian Chadd 9981bd3d89SAdrian Chadd for (cp = sf->fmts; *cp != '\0'; cp++) { 10081bd3d89SAdrian Chadd if (*cp == FMTS_IS_STAT) { 10181bd3d89SAdrian Chadd i = *(++cp); 10281bd3d89SAdrian Chadd i |= ((int) *(++cp)) << 8; 10381bd3d89SAdrian Chadd f = &sf->stats[i]; 10481bd3d89SAdrian Chadd fprintf(fd, "%*s", f->width, f->label); 10581bd3d89SAdrian Chadd } else 10681bd3d89SAdrian Chadd putc(*cp, fd); 10781bd3d89SAdrian Chadd } 10881bd3d89SAdrian Chadd putc('\n', fd); 10981bd3d89SAdrian Chadd } 11081bd3d89SAdrian Chadd 11181bd3d89SAdrian Chadd static void 11281bd3d89SAdrian Chadd bsdstat_print_current(struct bsdstat *sf, FILE *fd) 11381bd3d89SAdrian Chadd { 11481bd3d89SAdrian Chadd char buf[32]; 11581bd3d89SAdrian Chadd const unsigned char *cp; 11681bd3d89SAdrian Chadd int i; 11781bd3d89SAdrian Chadd const struct fmt *f; 11881bd3d89SAdrian Chadd 11981bd3d89SAdrian Chadd for (cp = sf->fmts; *cp != '\0'; cp++) { 12081bd3d89SAdrian Chadd if (*cp == FMTS_IS_STAT) { 12181bd3d89SAdrian Chadd i = *(++cp); 12281bd3d89SAdrian Chadd i |= ((int) *(++cp)) << 8; 12381bd3d89SAdrian Chadd f = &sf->stats[i]; 12481bd3d89SAdrian Chadd if (sf->get_curstat(sf, i, buf, sizeof(buf))) 12581bd3d89SAdrian Chadd fprintf(fd, "%*s", f->width, buf); 12681bd3d89SAdrian Chadd } else 12781bd3d89SAdrian Chadd putc(*cp, fd); 12881bd3d89SAdrian Chadd } 12981bd3d89SAdrian Chadd putc('\n', fd); 13081bd3d89SAdrian Chadd } 13181bd3d89SAdrian Chadd 13281bd3d89SAdrian Chadd static void 13381bd3d89SAdrian Chadd bsdstat_print_total(struct bsdstat *sf, FILE *fd) 13481bd3d89SAdrian Chadd { 13581bd3d89SAdrian Chadd char buf[32]; 13681bd3d89SAdrian Chadd const unsigned char *cp; 13781bd3d89SAdrian Chadd const struct fmt *f; 13881bd3d89SAdrian Chadd int i; 13981bd3d89SAdrian Chadd 14081bd3d89SAdrian Chadd for (cp = sf->fmts; *cp != '\0'; cp++) { 14181bd3d89SAdrian Chadd if (*cp == FMTS_IS_STAT) { 14281bd3d89SAdrian Chadd i = *(++cp); 14381bd3d89SAdrian Chadd i |= ((int) *(++cp)) << 8; 14481bd3d89SAdrian Chadd f = &sf->stats[i]; 14581bd3d89SAdrian Chadd if (sf->get_totstat(sf, i, buf, sizeof(buf))) 14681bd3d89SAdrian Chadd fprintf(fd, "%*s", f->width, buf); 14781bd3d89SAdrian Chadd } else 14881bd3d89SAdrian Chadd putc(*cp, fd); 14981bd3d89SAdrian Chadd } 15081bd3d89SAdrian Chadd putc('\n', fd); 15181bd3d89SAdrian Chadd } 15281bd3d89SAdrian Chadd 15381bd3d89SAdrian Chadd static void 15481bd3d89SAdrian Chadd bsdstat_print_verbose(struct bsdstat *sf, FILE *fd) 15581bd3d89SAdrian Chadd { 15681bd3d89SAdrian Chadd const struct fmt *f; 15781bd3d89SAdrian Chadd char s[32]; 15881bd3d89SAdrian Chadd int i, width; 15981bd3d89SAdrian Chadd 16081bd3d89SAdrian Chadd width = 0; 16181bd3d89SAdrian Chadd for (i = 0; i < sf->nstats; i++) { 16281bd3d89SAdrian Chadd f = &sf->stats[i]; 16381bd3d89SAdrian Chadd if (f->width > width) 16481bd3d89SAdrian Chadd width = f->width; 16581bd3d89SAdrian Chadd } 16681bd3d89SAdrian Chadd for (i = 0; i < sf->nstats; i++) { 16781bd3d89SAdrian Chadd f = &sf->stats[i]; 16881bd3d89SAdrian Chadd if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) 16981bd3d89SAdrian Chadd fprintf(fd, "%-*s %s\n", width, s, f->desc); 17081bd3d89SAdrian Chadd } 17181bd3d89SAdrian Chadd } 17281bd3d89SAdrian Chadd 17381bd3d89SAdrian Chadd static void 17481bd3d89SAdrian Chadd bsdstat_print_fields(struct bsdstat *sf, FILE *fd) 17581bd3d89SAdrian Chadd { 17681bd3d89SAdrian Chadd int i, w, width; 17781bd3d89SAdrian Chadd 17881bd3d89SAdrian Chadd width = 0; 17981bd3d89SAdrian Chadd for (i = 0; i < sf->nstats; i++) { 18081bd3d89SAdrian Chadd w = strlen(sf->stats[i].name); 18181bd3d89SAdrian Chadd if (w > width) 18281bd3d89SAdrian Chadd width = w; 18381bd3d89SAdrian Chadd } 18481bd3d89SAdrian Chadd for (i = 0; i < sf->nstats; i++) { 18581bd3d89SAdrian Chadd const struct fmt *f = &sf->stats[i]; 18681bd3d89SAdrian Chadd if (f->width != 0) 18781bd3d89SAdrian Chadd fprintf(fd, "%-*s %s\n", width, f->name, f->desc); 18881bd3d89SAdrian Chadd } 18981bd3d89SAdrian Chadd } 19081bd3d89SAdrian Chadd 19181bd3d89SAdrian Chadd void 19281bd3d89SAdrian Chadd bsdstat_init(struct bsdstat *sf, const char *name, const struct fmt *stats, int nstats) 19381bd3d89SAdrian Chadd { 19481bd3d89SAdrian Chadd sf->name = name; 19581bd3d89SAdrian Chadd sf->stats = stats; 19681bd3d89SAdrian Chadd sf->nstats = nstats; 19781bd3d89SAdrian Chadd sf->setfmt = bsdstat_setfmt; 19881bd3d89SAdrian Chadd sf->collect_cur = bsdstat_collect; 19981bd3d89SAdrian Chadd sf->collect_tot = bsdstat_collect; 20081bd3d89SAdrian Chadd sf->update_tot = bsdstat_update_tot; 20181bd3d89SAdrian Chadd sf->get_curstat = bsdstat_get; 20281bd3d89SAdrian Chadd sf->get_totstat = bsdstat_get; 20381bd3d89SAdrian Chadd sf->print_header = bsdstat_print_header; 20481bd3d89SAdrian Chadd sf->print_current = bsdstat_print_current; 20581bd3d89SAdrian Chadd sf->print_total = bsdstat_print_total; 20681bd3d89SAdrian Chadd sf->print_verbose = bsdstat_print_verbose; 20781bd3d89SAdrian Chadd sf->print_fields = bsdstat_print_fields; 20881bd3d89SAdrian Chadd } 209