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