1 /* $OpenBSD: main.c,v 1.21 2001/12/07 09:18:08 deraadt 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 38 static 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 45 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 46 #endif 47 static char rcsid[] = "$OpenBSD: main.c,v 1.21 2001/12/07 09:18:08 deraadt 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 66 double dellave; 67 68 kvm_t *kd; 69 char *nlistf = NULL; 70 char *memf = NULL; 71 sig_t sigtstpdfl; 72 double avenrun[3]; 73 int col; 74 int naptime = 5; 75 int verbose = 1; /* to report kvm read errs */ 76 int hz, stathz; 77 char c; 78 char *namp; 79 char hostname[MAXHOSTNAMELEN]; 80 WINDOW *wnd; 81 long CMDLINE; 82 83 WINDOW *wload; /* one line window for load average */ 84 85 static void usage __P((void)); 86 87 int 88 main(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 180 void 181 gethz() 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 195 static void 196 usage() 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 205 void 206 labels() 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 220 void 221 sigdisplay(signo) 222 int signo; 223 { 224 gotdisplay = 1; 225 } 226 227 void 228 display(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 263 void 264 load() 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 273 volatile sig_atomic_t gotdie; 274 volatile sig_atomic_t gotdisplay; 275 volatile sig_atomic_t gotwinch; 276 277 void 278 sigdie(signo) 279 int signo; 280 { 281 gotdie = 1; 282 } 283 284 void 285 die() 286 { 287 if (wnd) { 288 move(CMDLINE, 0); 289 clrtoeol(); 290 refresh(); 291 endwin(); 292 } 293 exit(0); 294 } 295 296 void 297 sigwinch(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__ 311 void 312 error(const char *fmt, ...) 313 #else 314 void 315 error(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 345 void 346 nlisterr(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