Annotation of src/usr.bin/systat/main.c, Revision 1.30
1.30 ! itojun 1: /* $OpenBSD: main.c,v 1.29 2004/04/14 19:53:04 deraadt 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.30 ! itojun 43: static char rcsid[] = "$OpenBSD: main.c,v 1.29 2004/04/14 19:53:04 deraadt 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.1 deraadt 68: sig_t sigtstpdfl;
1.21 deraadt 69: double avenrun[3];
70: int col;
1.1 deraadt 71: int naptime = 5;
1.21 deraadt 72: int verbose = 1; /* to report kvm read errs */
1.30 ! itojun 73: int nflag = 0;
1.21 deraadt 74: int hz, stathz;
1.1 deraadt 75: char c;
76: char *namp;
77: char hostname[MAXHOSTNAMELEN];
78: WINDOW *wnd;
1.11 millert 79: long CMDLINE;
1.1 deraadt 80:
1.21 deraadt 81: WINDOW *wload; /* one line window for load average */
1.1 deraadt 82:
1.22 millert 83: static void usage(void);
1.3 deraadt 84:
1.2 deraadt 85: int
1.24 deraadt 86: main(int argc, char *argv[])
1.1 deraadt 87: {
1.21 deraadt 88: int ch;
1.6 deraadt 89: char errbuf[_POSIX2_LINE_MAX];
1.1 deraadt 90:
1.25 deraadt 91: kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
92: if (kd == NULL) {
93: error("%s", errbuf);
94: exit(1);
95: }
96:
97: setegid(getgid());
98: setgid(getgid());
99:
1.30 ! itojun 100: while ((ch = getopt(argc, argv, "nw:")) != -1)
1.24 deraadt 101: switch (ch) {
1.30 ! itojun 102: case 'n':
! 103: nflag = 1;
! 104: break;
1.21 deraadt 105: case 'w':
106: if ((naptime = atoi(optarg)) <= 0)
107: errx(1, "interval <= 0.");
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])) {
117: naptime = atoi(argv[0]);
118: if (naptime <= 0)
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:
222: void
1.21 deraadt 223: sigdisplay(signo)
1.1 deraadt 224: int signo;
225: {
1.21 deraadt 226: gotdisplay = 1;
227: }
228:
229: void
230: display(void)
231: {
1.17 mpech 232: int i, j;
1.1 deraadt 233:
234: /* Get the load average over the last minute. */
235: (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
236: (*curcmd->c_fetch)();
237: if (curcmd->c_flags & CF_LOADAV) {
238: j = 5.0*avenrun[0] + 0.5;
239: dellave -= avenrun[0];
240: if (dellave >= 0.0)
241: c = '<';
242: else {
243: c = '>';
244: dellave = -dellave;
245: }
1.10 kstailey 246: if (dellave < 0.05)
1.1 deraadt 247: c = '|';
248: dellave = avenrun[0];
1.21 deraadt 249: wmove(wload, 0, 0);
250: wclrtoeol(wload);
1.1 deraadt 251: for (i = (j > 50) ? 50 : j; i > 0; i--)
252: waddch(wload, c);
253: if (j > 50)
254: wprintw(wload, " %4.1f", avenrun[0]);
255: }
256: (*curcmd->c_refresh)();
257: if (curcmd->c_flags & CF_LOADAV)
258: wrefresh(wload);
259: wrefresh(wnd);
260: move(CMDLINE, col);
261: refresh();
262: alarm(naptime);
263: }
264:
265: void
1.24 deraadt 266: load(void)
1.1 deraadt 267: {
268:
269: (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
270: mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f",
271: avenrun[0], avenrun[1], avenrun[2]);
272: clrtoeol();
273: }
274:
1.21 deraadt 275: volatile sig_atomic_t gotdie;
276: volatile sig_atomic_t gotdisplay;
277: volatile sig_atomic_t gotwinch;
1.29 deraadt 278: volatile sig_atomic_t gottstp;
1.21 deraadt 279:
1.1 deraadt 280: void
1.29 deraadt 281: sigdie(int signo)
1.1 deraadt 282: {
1.21 deraadt 283: gotdie = 1;
1.29 deraadt 284: }
285:
286: void
287: sigtstp(int signo)
288: {
289: gottstp = 1;
1.21 deraadt 290: }
291:
292: void
1.24 deraadt 293: die(void)
1.21 deraadt 294: {
1.13 deraadt 295: if (wnd) {
296: move(CMDLINE, 0);
297: clrtoeol();
298: refresh();
299: endwin();
300: }
1.1 deraadt 301: exit(0);
302: }
1.14 kstailey 303:
304: void
1.24 deraadt 305: sigwinch(int signo)
1.14 kstailey 306: {
1.21 deraadt 307: gotwinch = 1;
1.14 kstailey 308: }
309:
1.1 deraadt 310: void
311: error(const char *fmt, ...)
312: {
313: va_list ap;
314: char buf[255];
315: int oy, ox;
1.23 millert 316:
1.1 deraadt 317: va_start(ap, fmt);
318: if (wnd) {
319: getyx(stdscr, oy, ox);
1.5 deraadt 320: (void) vsnprintf(buf, sizeof buf, fmt, ap);
1.1 deraadt 321: clrtoeol();
322: standout();
323: mvaddstr(CMDLINE, 0, buf);
324: standend();
325: move(oy, ox);
326: refresh();
327: } else {
328: (void) vfprintf(stderr, fmt, ap);
329: fprintf(stderr, "\n");
330: }
331: va_end(ap);
332: }
333:
334: void
1.24 deraadt 335: nlisterr(struct nlist namelist[])
1.1 deraadt 336: {
337: int i, n;
338:
339: n = 0;
340: clear();
341: mvprintw(2, 10, "systat: nlist: can't find following symbols:");
342: for (i = 0;
343: namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
344: if (namelist[i].n_value == 0)
345: mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
346: move(CMDLINE, 0);
347: clrtoeol();
348: refresh();
349: endwin();
350: exit(1);
351: }