1193242Ssam/*- 2193242Ssam * Copyright (c) 2007 Sam Leffler, Errno Consulting 3193242Ssam * All rights reserved. 4193242Ssam * 5193242Ssam * Redistribution and use in source and binary forms, with or without 6193242Ssam * modification, are permitted provided that the following conditions 7193242Ssam * are met: 8193242Ssam * 1. Redistributions of source code must retain the above copyright 9193242Ssam * notice, this list of conditions and the following disclaimer, 10193242Ssam * without modification. 11193242Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12193242Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13193242Ssam * redistribution must be conditioned upon including a substantially 14193242Ssam * similar Disclaimer requirement for further binary redistribution. 15193242Ssam * 16193242Ssam * NO WARRANTY 17193242Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18193242Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19193242Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20193242Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21193242Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22193242Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23193242Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24193242Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25193242Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26193242Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27193242Ssam * THE POSSIBILITY OF SUCH DAMAGES. 28193242Ssam * 29193242Ssam * $FreeBSD$ 30193242Ssam */ 31193242Ssam 32193242Ssam#include <stdio.h> 33193242Ssam#include <string.h> 34193242Ssam 35193242Ssam#include "statfoo.h" 36193242Ssam 37193242Ssamstatic void 38193242Ssamstatfoo_setfmt(struct statfoo *sf, const char *fmt0) 39193242Ssam{ 40193242Ssam#define N(a) (sizeof(a)/sizeof(a[0])) 41193242Ssam char fmt[4096]; 42193242Ssam char *fp, *tok; 43193242Ssam int i, j; 44193242Ssam 45193242Ssam j = 0; 46193242Ssam strlcpy(fmt, fmt0, sizeof(fmt)); 47193242Ssam for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) { 48193242Ssam for (i = 0; i < sf->nstats; i++) 49193242Ssam if (strcasecmp(tok, sf->stats[i].name) == 0) 50193242Ssam break; 51193242Ssam if (i >= sf->nstats) { 52193242Ssam fprintf(stderr, "%s: unknown statistic name \"%s\" " 53193242Ssam "skipped\n", sf->name, tok); 54193242Ssam continue; 55193242Ssam } 56193242Ssam if (j+3 > sizeof(sf->fmts)) { 57193242Ssam fprintf(stderr, "%s: not enough room for all stats; " 58193242Ssam "stopped at %s\n", sf->name, tok); 59193242Ssam break; 60193242Ssam } 61193242Ssam if (j != 0) 62193242Ssam sf->fmts[j++] = ' '; 63193242Ssam sf->fmts[j++] = 0x80 | i; 64193242Ssam } 65193242Ssam sf->fmts[j] = '\0'; 66193242Ssam#undef N 67193242Ssam} 68193242Ssam 69193242Ssamstatic void 70193242Ssamstatfoo_collect(struct statfoo *sf) 71193242Ssam{ 72193242Ssam fprintf(stderr, "%s: don't know how to collect data\n", sf->name); 73193242Ssam} 74193242Ssam 75193242Ssamstatic void 76193242Ssamstatfoo_update_tot(struct statfoo *sf) 77193242Ssam{ 78193242Ssam fprintf(stderr, "%s: don't know how to update total data\n", sf->name); 79193242Ssam} 80193242Ssam 81193242Ssamstatic int 82193242Ssamstatfoo_get(struct statfoo *sf, int s, char b[], size_t bs) 83193242Ssam{ 84193242Ssam fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s); 85193242Ssam return 0; 86193242Ssam} 87193242Ssam 88193242Ssamstatic void 89193242Ssamstatfoo_print_header(struct statfoo *sf, FILE *fd) 90193242Ssam{ 91193242Ssam const unsigned char *cp; 92193242Ssam 93193242Ssam for (cp = sf->fmts; *cp != '\0'; cp++) { 94193242Ssam if (*cp & 0x80) { 95193242Ssam const struct fmt *f = &sf->stats[*cp &~ 0x80]; 96193242Ssam fprintf(fd, "%*s", f->width, f->label); 97193242Ssam } else 98193242Ssam putc(*cp, fd); 99193242Ssam } 100193242Ssam putc('\n', fd); 101193242Ssam} 102193242Ssam 103193242Ssamstatic void 104193242Ssamstatfoo_print_current(struct statfoo *sf, FILE *fd) 105193242Ssam{ 106193242Ssam char buf[32]; 107193242Ssam const unsigned char *cp; 108193242Ssam 109193242Ssam for (cp = sf->fmts; *cp != '\0'; cp++) { 110193242Ssam if (*cp & 0x80) { 111193242Ssam const struct fmt *f = &sf->stats[*cp &~ 0x80]; 112193242Ssam if (sf->get_curstat(sf, *cp &~ 0x80, buf, sizeof(buf))) 113193242Ssam fprintf(fd, "%*s", f->width, buf); 114193242Ssam } else 115193242Ssam putc(*cp, fd); 116193242Ssam } 117193242Ssam putc('\n', fd); 118193242Ssam} 119193242Ssam 120193242Ssamstatic void 121193242Ssamstatfoo_print_total(struct statfoo *sf, FILE *fd) 122193242Ssam{ 123193242Ssam char buf[32]; 124193242Ssam const unsigned char *cp; 125193242Ssam 126193242Ssam for (cp = sf->fmts; *cp != '\0'; cp++) { 127193242Ssam if (*cp & 0x80) { 128193242Ssam const struct fmt *f = &sf->stats[*cp &~ 0x80]; 129193242Ssam if (sf->get_totstat(sf, *cp &~ 0x80, buf, sizeof(buf))) 130193242Ssam fprintf(fd, "%*s", f->width, buf); 131193242Ssam } else 132193242Ssam putc(*cp, fd); 133193242Ssam } 134193242Ssam putc('\n', fd); 135193242Ssam} 136193242Ssam 137193242Ssamstatic void 138193242Ssamstatfoo_print_verbose(struct statfoo *sf, FILE *fd) 139193242Ssam{ 140193242Ssam char s[32]; 141193242Ssam int i; 142193242Ssam 143193242Ssam for (i = 0; i < sf->nstats; i++) { 144193242Ssam if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) 145193242Ssam fprintf(fd, "%s %s\n", s, sf->stats[i].desc); 146193242Ssam } 147193242Ssam} 148193242Ssam 149193242Ssamstatic void 150193242Ssamstatfoo_print_fields(struct statfoo *sf, FILE *fd) 151193242Ssam{ 152193242Ssam int i, w, width; 153193242Ssam 154193242Ssam width = 0; 155193242Ssam for (i = 0; i < sf->nstats; i++) { 156193242Ssam w = strlen(sf->stats[i].name); 157193242Ssam if (w > width) 158193242Ssam width = w; 159193242Ssam } 160193242Ssam for (i = 0; i < sf->nstats; i++) { 161193242Ssam const struct fmt *f = &sf->stats[i]; 162193242Ssam if (f->width != 0) 163193242Ssam fprintf(fd, "%-*s %s\n", width, f->name, f->desc); 164193242Ssam } 165193242Ssam} 166193242Ssam 167193242Ssamvoid 168193242Ssamstatfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats) 169193242Ssam{ 170193242Ssam sf->name = name; 171193242Ssam sf->stats = stats; 172193242Ssam sf->nstats = nstats; 173193242Ssam sf->setfmt = statfoo_setfmt; 174193242Ssam sf->collect_cur = statfoo_collect; 175193242Ssam sf->collect_tot = statfoo_collect; 176193242Ssam sf->update_tot = statfoo_update_tot; 177193242Ssam sf->get_curstat = statfoo_get; 178193242Ssam sf->get_totstat = statfoo_get; 179193242Ssam sf->print_header = statfoo_print_header; 180193242Ssam sf->print_current = statfoo_print_current; 181193242Ssam sf->print_total = statfoo_print_total; 182193242Ssam sf->print_verbose = statfoo_print_verbose; 183193242Ssam sf->print_fields = statfoo_print_fields; 184193242Ssam} 185