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