main.c revision 1.22
1/* $OpenBSD: main.c,v 1.22 2002/02/16 21:27:54 millert Exp $ */ 2/* $NetBSD: main.c,v 1.8 1996/05/10 23:16:36 thorpej Exp $ */ 3 4/*- 5 * Copyright (c) 1980, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#ifndef lint 38static char copyright[] = 39"@(#) Copyright (c) 1980, 1992, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /* not lint */ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 46#endif 47static char rcsid[] = "$OpenBSD: main.c,v 1.22 2002/02/16 21:27:54 millert Exp $"; 48#endif /* not lint */ 49 50#include <sys/param.h> 51#include <sys/sysctl.h> 52 53#include <err.h> 54#include <nlist.h> 55#include <signal.h> 56#include <ctype.h> 57#include <stdio.h> 58#include <string.h> 59#include <unistd.h> 60#include <stdlib.h> 61#include <limits.h> 62 63#include "systat.h" 64#include "extern.h" 65 66double dellave; 67 68kvm_t *kd; 69char *nlistf = NULL; 70char *memf = NULL; 71sig_t sigtstpdfl; 72double avenrun[3]; 73int col; 74int naptime = 5; 75int verbose = 1; /* to report kvm read errs */ 76int hz, stathz; 77char c; 78char *namp; 79char hostname[MAXHOSTNAMELEN]; 80WINDOW *wnd; 81long CMDLINE; 82 83WINDOW *wload; /* one line window for load average */ 84 85static void usage(void); 86 87int 88main(argc, argv) 89 int argc; 90 char **argv; 91{ 92 int ch; 93 char errbuf[_POSIX2_LINE_MAX]; 94 95 while ((ch = getopt(argc, argv, "w:")) != -1) 96 switch(ch) { 97 case 'w': 98 if ((naptime = atoi(optarg)) <= 0) 99 errx(1, "interval <= 0."); 100 break; 101 default: 102 usage(); 103 } 104 argc -= optind; 105 argv += optind; 106 107 while (argc > 0) { 108 if (isdigit(argv[0][0])) { 109 naptime = atoi(argv[0]); 110 if (naptime <= 0) 111 naptime = 5; 112 } else { 113 struct cmdtab *p; 114 115 p = lookup(&argv[0][0]); 116 if (p == (struct cmdtab *)-1) 117 errx(1, "ambiguous request: %s", &argv[0][0]); 118 if (p == 0) 119 errx(1, "unknown request: %s", &argv[0][0]); 120 curcmd = p; 121 } 122 argc--; 123 argv++; 124 } 125 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 126 if (kd == NULL) { 127 error("%s", errbuf); 128 exit(1); 129 } 130 131 signal(SIGINT, sigdie); 132 siginterrupt(SIGINT, 1); 133 signal(SIGQUIT, sigdie); 134 siginterrupt(SIGQUIT, 1); 135 signal(SIGTERM, sigdie); 136 siginterrupt(SIGTERM, 1); 137 138 /* 139 * Initialize display. Load average appears in a one line 140 * window of its own. Current command's display appears in 141 * an overlapping sub-window of stdscr configured by the display 142 * routines to minimize update work by curses. 143 */ 144 if (initscr() == NULL) 145 { 146 warnx("couldn't initialize screen"); 147 exit(0); 148 } 149 150 CMDLINE = LINES - 1; 151 wnd = (*curcmd->c_open)(); 152 if (wnd == NULL) { 153 warnx("couldn't initialize display"); 154 die(); 155 } 156 wload = newwin(1, 0, 3, 20); 157 if (wload == NULL) { 158 warnx("couldn't set up load average window"); 159 die(); 160 } 161 gethostname(hostname, sizeof (hostname)); 162 gethz(); 163 (*curcmd->c_init)(); 164 curcmd->c_flags |= CF_INIT; 165 labels(); 166 167 dellave = 0.0; 168 169 signal(SIGALRM, sigdisplay); 170 siginterrupt(SIGALRM, 1); 171 signal(SIGWINCH, sigwinch); 172 siginterrupt(SIGWINCH, 1); 173 gotdisplay = 1; 174 noecho(); 175 crmode(); 176 keyboard(); 177 /*NOTREACHED*/ 178} 179 180void 181gethz() 182{ 183 struct clockinfo cinf; 184 size_t size = sizeof(cinf); 185 int mib[2]; 186 187 mib[0] = CTL_KERN; 188 mib[1] = KERN_CLOCKRATE; 189 if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) 190 return; 191 stathz = cinf.stathz; 192 hz = cinf.hz; 193} 194 195static void 196usage() 197{ 198 fprintf(stderr, "usage: systat [-M core] [-N system] [-w wait]\n"); 199 fprintf(stderr, 200 " [iostat|mbufs|netstat|pigs|swap|vmstat]\n"); 201 exit(1); 202} 203 204 205void 206labels() 207{ 208 if (curcmd->c_flags & CF_LOADAV) { 209 mvaddstr(2, 20, 210 "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10"); 211 mvaddstr(3, 5, "Load Average"); 212 } 213 (*curcmd->c_label)(); 214#ifdef notdef 215 mvprintw(21, 25, "CPU usage on %s", hostname); 216#endif 217 refresh(); 218} 219 220void 221sigdisplay(signo) 222 int signo; 223{ 224 gotdisplay = 1; 225} 226 227void 228display(void) 229{ 230 int i, j; 231 232 /* Get the load average over the last minute. */ 233 (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); 234 (*curcmd->c_fetch)(); 235 if (curcmd->c_flags & CF_LOADAV) { 236 j = 5.0*avenrun[0] + 0.5; 237 dellave -= avenrun[0]; 238 if (dellave >= 0.0) 239 c = '<'; 240 else { 241 c = '>'; 242 dellave = -dellave; 243 } 244 if (dellave < 0.05) 245 c = '|'; 246 dellave = avenrun[0]; 247 wmove(wload, 0, 0); 248 wclrtoeol(wload); 249 for (i = (j > 50) ? 50 : j; i > 0; i--) 250 waddch(wload, c); 251 if (j > 50) 252 wprintw(wload, " %4.1f", avenrun[0]); 253 } 254 (*curcmd->c_refresh)(); 255 if (curcmd->c_flags & CF_LOADAV) 256 wrefresh(wload); 257 wrefresh(wnd); 258 move(CMDLINE, col); 259 refresh(); 260 alarm(naptime); 261} 262 263void 264load() 265{ 266 267 (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); 268 mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", 269 avenrun[0], avenrun[1], avenrun[2]); 270 clrtoeol(); 271} 272 273volatile sig_atomic_t gotdie; 274volatile sig_atomic_t gotdisplay; 275volatile sig_atomic_t gotwinch; 276 277void 278sigdie(signo) 279 int signo; 280{ 281 gotdie = 1; 282} 283 284void 285die() 286{ 287 if (wnd) { 288 move(CMDLINE, 0); 289 clrtoeol(); 290 refresh(); 291 endwin(); 292 } 293 exit(0); 294} 295 296void 297sigwinch(signo) 298 int signo; 299{ 300 gotwinch = 1; 301} 302 303 304#ifdef __STDC__ 305#include <stdarg.h> 306#else 307#include <varargs.h> 308#endif 309 310#ifdef __STDC__ 311void 312error(const char *fmt, ...) 313#else 314void 315error(fmt, va_alist) 316 char *fmt; 317 va_dcl 318#endif 319{ 320 va_list ap; 321 char buf[255]; 322 int oy, ox; 323#ifdef __STDC__ 324 va_start(ap, fmt); 325#else 326 va_start(ap); 327#endif 328 329 if (wnd) { 330 getyx(stdscr, oy, ox); 331 (void) vsnprintf(buf, sizeof buf, fmt, ap); 332 clrtoeol(); 333 standout(); 334 mvaddstr(CMDLINE, 0, buf); 335 standend(); 336 move(oy, ox); 337 refresh(); 338 } else { 339 (void) vfprintf(stderr, fmt, ap); 340 fprintf(stderr, "\n"); 341 } 342 va_end(ap); 343} 344 345void 346nlisterr(namelist) 347 struct nlist namelist[]; 348{ 349 int i, n; 350 351 n = 0; 352 clear(); 353 mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 354 for (i = 0; 355 namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++) 356 if (namelist[i].n_value == 0) 357 mvprintw(2 + ++n, 10, "%s", namelist[i].n_name); 358 move(CMDLINE, 0); 359 clrtoeol(); 360 refresh(); 361 endwin(); 362 exit(1); 363} 364