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