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