1 /*-
2 * Copyright (c) 1980, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1992, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17
18 #include <sys/param.h>
19
20 #include <nlist.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include "systat.h"
24 #include "extern.h"
25
26 static struct nlist namelist[] = {
27 #define X_FIRST 0
28 #define X_HZ 0
29 { "_hz" },
30 #define X_STATHZ 1
31 { "_stathz" },
32 { "" }
33 };
34 static int dellave;
35
36 kvm_t *kd;
37 sig_t sigtstpdfl;
38 double avenrun[3];
39 int col;
40 int naptime = 5;
41 int verbose = 1; /* to report kvm read errs */
42 int hz, stathz;
43 char c;
44 char *namp;
45 char hostname[MAXHOSTNAMELEN];
46 WINDOW *wnd;
47 int CMDLINE;
48
49 static WINDOW *wload; /* one line window for load average */
50
51 void
main(argc,argv)52 main(argc, argv)
53 int argc;
54 char **argv;
55 {
56 char errbuf[80];
57
58 argc--, argv++;
59 while (argc > 0) {
60 if (argv[0][0] == '-') {
61 struct cmdtab *p;
62
63 p = lookup(&argv[0][1]);
64 if (p == (struct cmdtab *)-1) {
65 fprintf(stderr, "%s: unknown request\n",
66 &argv[0][1]);
67 exit(1);
68 }
69 curcmd = p;
70 } else {
71 naptime = atoi(argv[0]);
72 if (naptime <= 0)
73 naptime = 5;
74 }
75 argc--, argv++;
76 }
77 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
78 if (kd == NULL) {
79 error("%s", errbuf);
80 exit(1);
81 }
82 if (kvm_nlist(kd, namelist)) {
83 nlisterr(namelist);
84 exit(1);
85 }
86 if (namelist[X_FIRST].n_type == 0) {
87 fprintf(stderr, "couldn't read namelist.\n");
88 exit(1);
89 }
90 signal(SIGINT, die);
91 signal(SIGQUIT, die);
92 signal(SIGTERM, die);
93
94 /*
95 * Initialize display. Load average appears in a one line
96 * window of its own. Current command's display appears in
97 * an overlapping sub-window of stdscr configured by the display
98 * routines to minimize update work by curses.
99 */
100 initscr();
101 CMDLINE = LINES - 1;
102 wnd = (*curcmd->c_open)();
103 if (wnd == NULL) {
104 fprintf(stderr, "Couldn't initialize display.\n");
105 die(0);
106 }
107 wload = newwin(1, 0, 3, 20);
108 if (wload == NULL) {
109 fprintf(stderr, "Couldn't set up load average window.\n");
110 die(0);
111 }
112 gethostname(hostname, sizeof (hostname));
113 NREAD(X_HZ, &hz, LONG);
114 NREAD(X_STATHZ, &stathz, LONG);
115 (*curcmd->c_init)();
116 curcmd->c_flags |= CF_INIT;
117 labels();
118
119 dellave = 0.0;
120
121 signal(SIGALRM, display);
122 display(0);
123 noecho();
124 crmode();
125 keyboard();
126 /*NOTREACHED*/
127 }
128
129 void
labels()130 labels()
131 {
132 if (curcmd->c_flags & CF_LOADAV) {
133 mvaddstr(2, 20,
134 "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10");
135 mvaddstr(3, 5, "Load Average");
136 }
137 (*curcmd->c_label)();
138 #ifdef notdef
139 mvprintw(21, 25, "CPU usage on %s", hostname);
140 #endif
141 refresh();
142 }
143
144 void
display(signo)145 display(signo)
146 int signo;
147 {
148 register int i, j;
149
150 /* Get the load average over the last minute. */
151 (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
152 (*curcmd->c_fetch)();
153 if (curcmd->c_flags & CF_LOADAV) {
154 j = 5.0*avenrun[0] + 0.5;
155 dellave -= avenrun[0];
156 if (dellave >= 0.0)
157 c = '<';
158 else {
159 c = '>';
160 dellave = -dellave;
161 }
162 if (dellave < 0.1)
163 c = '|';
164 dellave = avenrun[0];
165 wmove(wload, 0, 0); wclrtoeol(wload);
166 for (i = (j > 50) ? 50 : j; i > 0; i--)
167 waddch(wload, c);
168 if (j > 50)
169 wprintw(wload, " %4.1f", avenrun[0]);
170 }
171 (*curcmd->c_refresh)();
172 if (curcmd->c_flags & CF_LOADAV)
173 wrefresh(wload);
174 wrefresh(wnd);
175 move(CMDLINE, col);
176 refresh();
177 alarm(naptime);
178 }
179
180 void
load()181 load()
182 {
183
184 (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0]));
185 mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f",
186 avenrun[0], avenrun[1], avenrun[2]);
187 clrtoeol();
188 }
189
190 void
die(signo)191 die(signo)
192 int signo;
193 {
194 move(CMDLINE, 0);
195 clrtoeol();
196 refresh();
197 endwin();
198 exit(0);
199 }
200
201 #if __STDC__
202 #include <stdarg.h>
203 #else
204 #include <varargs.h>
205 #endif
206
207 #if __STDC__
208 void
error(const char * fmt,...)209 error(const char *fmt, ...)
210 #else
211 void
212 error(fmt, va_alist)
213 char *fmt;
214 va_dcl
215 #endif
216 {
217 va_list ap;
218 char buf[255];
219 int oy, ox;
220 #if __STDC__
221 va_start(ap, fmt);
222 #else
223 va_start(ap);
224 #endif
225
226 if (wnd) {
227 getyx(stdscr, oy, ox);
228 (void) vsprintf(buf, fmt, ap);
229 clrtoeol();
230 standout();
231 mvaddstr(CMDLINE, 0, buf);
232 standend();
233 move(oy, ox);
234 refresh();
235 } else {
236 (void) vfprintf(stderr, fmt, ap);
237 fprintf(stderr, "\n");
238 }
239 va_end(ap);
240 }
241
242 void
nlisterr(namelist)243 nlisterr(namelist)
244 struct nlist namelist[];
245 {
246 int i, n;
247
248 n = 0;
249 clear();
250 mvprintw(2, 10, "systat: nlist: can't find following symbols:");
251 for (i = 0;
252 namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
253 if (namelist[i].n_value == 0)
254 mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
255 move(CMDLINE, 0);
256 clrtoeol();
257 refresh();
258 endwin();
259 exit(1);
260 }
261