Annotation of src/usr.bin/systat/main.c, Revision 1.61
1.61 ! deraadt 1: /* $Id: main.c,v 1.60 2013/09/07 11:43:50 reyk Exp $ */
1.38 canacar 2: /*
3: * Copyright (c) 2001, 2007 Can Erkin Acar
4: * Copyright (c) 2001 Daniel Hartmeier
5: * All rights reserved.
1.1 deraadt 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.38 canacar 11: * - Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * - Redistributions in binary form must reproduce the above
14: * copyright notice, this list of conditions and the following
15: * disclaimer in the documentation and/or other materials provided
16: * with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22: * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: *
1.1 deraadt 31: */
32:
1.38 canacar 33: #include <sys/types.h>
1.21 deraadt 34: #include <sys/sysctl.h>
1.1 deraadt 35:
1.38 canacar 36:
37: #include <ctype.h>
38: #include <curses.h>
1.1 deraadt 39: #include <err.h>
1.38 canacar 40: #include <errno.h>
41: #include <fcntl.h>
42: #include <limits.h>
43: #include <netdb.h>
1.1 deraadt 44: #include <signal.h>
45: #include <stdio.h>
1.38 canacar 46: #include <stdlib.h>
1.1 deraadt 47: #include <string.h>
1.38 canacar 48: #include <stdarg.h>
1.3 deraadt 49: #include <unistd.h>
1.35 deraadt 50: #include <utmp.h>
1.1 deraadt 51:
1.38 canacar 52: #include "engine.h"
1.1 deraadt 53: #include "systat.h"
54:
1.58 lum 55: #define TIMEPOS 55
56:
1.21 deraadt 57: double dellave;
1.1 deraadt 58:
1.21 deraadt 59: kvm_t *kd;
60: char *nlistf = NULL;
1.20 pvalchev 61: char *memf = NULL;
1.21 deraadt 62: double avenrun[3];
1.36 tedu 63: double naptime = 5.0;
1.21 deraadt 64: int verbose = 1; /* to report kvm read errs */
1.38 canacar 65: int nflag = 1;
1.35 deraadt 66: int ut, hz, stathz;
1.61 ! deraadt 67: char hostname[HOST_NAME_MAX+1];
1.1 deraadt 68: WINDOW *wnd;
1.32 deraadt 69: int CMDLINE;
1.58 lum 70: char timebuf[26];
71: char uloadbuf[TIMEPOS];
1.1 deraadt 72:
1.38 canacar 73:
1.50 canacar 74: int ucount(void);
75: void usage(void);
76:
1.38 canacar 77: /* command prompt */
78:
1.46 canacar 79: void cmd_delay(const char *);
80: void cmd_count(const char *);
81: void cmd_compat(const char *);
1.38 canacar 82:
83: struct command cm_compat = {"Command", cmd_compat};
84: struct command cm_delay = {"Seconds to delay", cmd_delay};
85: struct command cm_count = {"Number of lines to display", cmd_count};
1.1 deraadt 86:
1.38 canacar 87:
88: /* display functions */
1.3 deraadt 89:
1.2 deraadt 90: int
1.38 canacar 91: print_header(void)
1.1 deraadt 92: {
1.50 canacar 93: time_t now;
1.40 deraadt 94: int start = dispstart + 1, end = dispstart + maxprint;
1.58 lum 95: char tmpbuf[TIMEPOS];
96: char header[MAX_LINE_BUF];
1.38 canacar 97:
98: if (end > num_disp)
99: end = num_disp;
100:
101: tb_start();
1.35 deraadt 102:
1.58 lum 103: if (!paused) {
104: getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
1.38 canacar 105:
1.58 lum 106: snprintf(uloadbuf, sizeof(uloadbuf),
107: "%5d users Load %.2f %.2f %.2f",
108: ucount(), avenrun[0], avenrun[1], avenrun[2]);
1.25 deraadt 109:
1.58 lum 110: time(&now);
111: strlcpy(timebuf, ctime(&now), sizeof(timebuf));
112: }
1.25 deraadt 113:
1.58 lum 114: if (num_disp && (start > 1 || end != num_disp))
115: snprintf(tmpbuf, sizeof(tmpbuf),
116: "%s (%u-%u of %u) %s", uloadbuf, start, end, num_disp,
117: paused ? "PAUSED" : "");
118: else
119: snprintf(tmpbuf, sizeof(tmpbuf),
120: "%s %s", uloadbuf,
121: paused ? "PAUSED" : "");
122:
123: snprintf(header, sizeof(header), "%-55s%s", tmpbuf, timebuf);
124:
125: if (rawmode)
126: printf("\n\n%s\n", header);
127: else
128: mvprintw(0, 0, "%s", header);
1.24 deraadt 129:
1.38 canacar 130: return (1);
1.1 deraadt 131: }
1.3 deraadt 132:
1.38 canacar 133: /* compatibility functions, rearrange later */
1.21 deraadt 134: void
1.38 canacar 135: error(const char *fmt, ...)
1.21 deraadt 136: {
1.38 canacar 137: va_list ap;
138: char buf[MAX_LINE_BUF];
139:
140: va_start(ap, fmt);
141: vsnprintf(buf, sizeof buf, fmt, ap);
142: va_end(ap);
1.21 deraadt 143:
1.38 canacar 144: message_set(buf);
1.21 deraadt 145: }
146:
1.38 canacar 147: void
148: nlisterr(struct nlist namelist[])
1.3 deraadt 149: {
1.38 canacar 150: int i, n;
151:
152: n = 0;
153: clear();
154: mvprintw(2, 10, "systat: nlist: can't find following symbols:");
155: for (i = 0;
156: namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
157: if (namelist[i].n_value == 0)
158: mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
159: move(CMDLINE, 0);
160: clrtoeol();
161: refresh();
162: endwin();
1.3 deraadt 163: exit(1);
164: }
165:
1.1 deraadt 166: void
1.38 canacar 167: die(void)
1.1 deraadt 168: {
1.38 canacar 169: if (!rawmode)
170: endwin();
171: exit(0);
1.1 deraadt 172: }
173:
1.38 canacar 174:
175: int
176: prefix(char *s1, char *s2)
1.1 deraadt 177: {
1.38 canacar 178:
179: while (*s1 == *s2) {
180: if (*s1 == '\0')
181: return (1);
182: s1++, s2++;
183: }
184: return (*s1 == '\0');
1.21 deraadt 185: }
186:
1.38 canacar 187: /* calculate number of users on the system */
188: int
189: ucount(void)
1.21 deraadt 190: {
1.38 canacar 191: int nusers = 0;
192: struct utmp utmp;
1.35 deraadt 193:
1.38 canacar 194: if (ut < 0)
195: return (0);
196: lseek(ut, (off_t)0, SEEK_SET);
197: while (read(ut, &utmp, sizeof(utmp)))
198: if (utmp.ut_name[0] != '\0')
199: nusers++;
1.35 deraadt 200:
1.38 canacar 201: return (nusers);
1.1 deraadt 202: }
203:
1.38 canacar 204: /* main program functions */
205:
1.1 deraadt 206: void
1.50 canacar 207: usage(void)
1.1 deraadt 208: {
1.38 canacar 209: extern char *__progname;
1.60 reyk 210: fprintf(stderr, "usage: %s [-aBbiNn] [-d count] "
1.43 matthieu 211: "[-s delay] [-w width] [view] [delay]\n", __progname);
1.38 canacar 212: exit(1);
1.1 deraadt 213: }
214:
1.45 canacar 215: void
216: show_view(void)
217: {
218: if (rawmode)
219: return;
220:
221: tb_start();
222: tbprintf("%s %g", curr_view->name, naptime);
223: tb_end();
224: message_set(tmp_buf);
225: }
1.21 deraadt 226:
1.1 deraadt 227: void
1.38 canacar 228: add_view_tb(field_view *v)
1.1 deraadt 229: {
1.38 canacar 230: if (curr_view == v)
231: tbprintf("[%s] ", v->name);
232: else
233: tbprintf("%s ", v->name);
1.29 deraadt 234: }
235:
236: void
1.38 canacar 237: show_help(void)
1.29 deraadt 238: {
1.38 canacar 239: if (rawmode)
240: return;
241:
242: tb_start();
243: foreach_view(add_view_tb);
244: tb_end();
245: message_set(tmp_buf);
1.21 deraadt 246: }
247:
248: void
1.46 canacar 249: cmd_compat(const char *buf)
1.21 deraadt 250: {
1.46 canacar 251: const char *s;
1.38 canacar 252:
1.46 canacar 253: if (strcasecmp(buf, "help") == 0) {
1.38 canacar 254: show_help();
255: need_update = 1;
256: return;
257: }
1.46 canacar 258: if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
1.38 canacar 259: gotsig_close = 1;
260: return;
261: }
1.46 canacar 262: if (strcasecmp(buf, "stop") == 0) {
263: paused = 1;
264: gotsig_alarm = 1;
265: return;
266: }
267: if (strncasecmp(buf, "start", 5) == 0) {
268: paused = 0;
269: gotsig_alarm = 1;
1.47 canacar 270: cmd_delay(buf + 5);
1.46 canacar 271: return;
272: }
1.38 canacar 273:
1.46 canacar 274: for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
1.38 canacar 275: ;
276: if (*s) {
1.46 canacar 277: if (set_view(buf))
1.49 espie 278: error("Invalid/ambiguous view: %s", buf);
1.38 canacar 279: } else
1.46 canacar 280: cmd_delay(buf);
1.38 canacar 281: }
282:
283: void
1.46 canacar 284: cmd_delay(const char *buf)
1.38 canacar 285: {
286: double del;
1.46 canacar 287: del = atof(buf);
1.39 canacar 288:
1.38 canacar 289: if (del > 0) {
290: udelay = (useconds_t)(del * 1000000);
291: gotsig_alarm = 1;
1.39 canacar 292: naptime = del;
1.13 deraadt 293: }
1.1 deraadt 294: }
1.14 kstailey 295:
296: void
1.46 canacar 297: cmd_count(const char *buf)
1.14 kstailey 298: {
1.38 canacar 299: int ms;
1.46 canacar 300: ms = atoi(buf);
1.38 canacar 301:
302: if (ms <= 0 || ms > lines - HEADER_LINES)
303: maxprint = lines - HEADER_LINES;
304: else
305: maxprint = ms;
1.14 kstailey 306: }
307:
1.38 canacar 308:
309: int
310: keyboard_callback(int ch)
1.1 deraadt 311: {
1.38 canacar 312: switch (ch) {
313: case '?':
314: /* FALLTHROUGH */
315: case 'h':
316: show_help();
1.45 canacar 317: need_update = 1;
318: break;
319: case CTRL_G:
320: show_view();
1.38 canacar 321: need_update = 1;
322: break;
323: case 'l':
324: command_set(&cm_count, NULL);
325: break;
326: case 's':
327: command_set(&cm_delay, NULL);
1.59 mpf 328: break;
329: case ',':
330: separate_thousands = !separate_thousands;
331: gotsig_alarm = 1;
1.38 canacar 332: break;
333: case ':':
334: command_set(&cm_compat, NULL);
335: break;
336: default:
337: return 0;
338: };
339:
340: return 1;
341: }
1.23 millert 342:
1.38 canacar 343: void
344: initialize(void)
345: {
346: engine_initialize();
347:
348: initvmstat();
349: initpigs();
350: initifstat();
351: initiostat();
352: initsensors();
353: initmembufs();
354: initnetstat();
355: initswap();
356: initpftop();
357: initpf();
1.48 canacar 358: initpool();
1.51 canacar 359: initmalloc();
1.52 jasper 360: initnfs();
1.60 reyk 361: initcpu();
1.1 deraadt 362: }
363:
364: void
1.38 canacar 365: gethz(void)
1.1 deraadt 366: {
1.38 canacar 367: struct clockinfo cinf;
368: size_t size = sizeof(cinf);
369: int mib[2];
1.1 deraadt 370:
1.38 canacar 371: mib[0] = CTL_KERN;
372: mib[1] = KERN_CLOCKRATE;
373: if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
374: return;
375: stathz = cinf.stathz;
376: hz = cinf.hz;
1.35 deraadt 377: }
378:
379: int
1.38 canacar 380: main(int argc, char *argv[])
1.35 deraadt 381: {
1.38 canacar 382: char errbuf[_POSIX2_LINE_MAX];
383: extern char *optarg;
384: extern int optind;
385: double delay = 5;
386:
387: char *viewstr = NULL;
388:
389: gid_t gid;
390: int countmax = 0;
391: int maxlines = 0;
392:
393: int ch;
394:
395: ut = open(_PATH_UTMP, O_RDONLY);
396: if (ut < 0) {
397: warn("No utmp");
398: }
399:
400: kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
401:
402: gid = getgid();
403: if (setresgid(gid, gid, gid) == -1)
404: err(1, "setresgid");
405:
1.60 reyk 406: while ((ch = getopt(argc, argv, "BNabd:ins:w:")) != -1) {
1.38 canacar 407: switch (ch) {
408: case 'a':
409: maxlines = -1;
410: break;
1.60 reyk 411: case 'B':
412: averageonly = 1;
413: if (countmax < 2)
414: countmax = 2;
415: /* FALLTHROUGH */
1.38 canacar 416: case 'b':
417: rawmode = 1;
418: interactive = 0;
419: break;
420: case 'd':
421: countmax = atoi(optarg);
422: if (countmax < 0)
423: countmax = 0;
424: break;
425: case 'i':
426: interactive = 1;
427: break;
1.55 sthen 428: case 'N':
429: nflag = 0;
430: break;
1.38 canacar 431: case 'n':
1.55 sthen 432: /* this is a noop, -n is the default */
1.38 canacar 433: nflag = 1;
434: break;
435: case 's':
436: delay = atof(optarg);
1.39 canacar 437: if (delay <= 0)
1.38 canacar 438: delay = 5;
439: break;
440: case 'w':
441: rawwidth = atoi(optarg);
442: if (rawwidth < 1)
443: rawwidth = DEFAULT_WIDTH;
444: if (rawwidth >= MAX_LINE_BUF)
445: rawwidth = MAX_LINE_BUF - 1;
446: break;
447: default:
448: usage();
449: /* NOTREACHED */
450: }
451: }
1.43 matthieu 452:
453: if (kd == NULL)
454: warnx("kvm_openfiles: %s", errbuf);
1.38 canacar 455:
456: argc -= optind;
457: argv += optind;
458:
459: if (argc == 1) {
460: double del = atof(argv[0]);
461: if (del == 0)
462: viewstr = argv[0];
463: else
464: delay = del;
465: } else if (argc == 2) {
466: viewstr = argv[0];
467: delay = atof(argv[1]);
1.42 canacar 468: if (delay <= 0)
469: delay = 5;
1.38 canacar 470: }
471:
472: udelay = (useconds_t)(delay * 1000000.0);
473: if (udelay < 1)
474: udelay = 1;
1.39 canacar 475:
476: naptime = (double)udelay / 1000000.0;
1.38 canacar 477:
478: gethostname(hostname, sizeof (hostname));
479: gethz();
480:
481: initialize();
482:
483: set_order(NULL);
484: if (viewstr && set_view(viewstr)) {
1.49 espie 485: fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
1.38 canacar 486: return 1;
487: }
488:
1.57 lum 489: if (check_termcap()) {
1.38 canacar 490: rawmode = 1;
491: interactive = 0;
492: }
493:
494: setup_term(maxlines);
495:
496: if (rawmode && countmax == 0)
497: countmax = 1;
498:
499: gotsig_alarm = 1;
1.35 deraadt 500:
1.38 canacar 501: engine_loop(countmax);
1.35 deraadt 502:
1.38 canacar 503: return 0;
1.1 deraadt 504: }