Annotation of src/usr.bin/systat/main.c, Revision 1.59
1.59 ! mpf 1: /* $Id: main.c,v 1.58 2011/03/31 06:12:34 lum 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.1 deraadt 34: #include <sys/param.h>
1.21 deraadt 35: #include <sys/sysctl.h>
1.1 deraadt 36:
1.38 canacar 37:
38: #include <ctype.h>
39: #include <curses.h>
1.1 deraadt 40: #include <err.h>
1.38 canacar 41: #include <errno.h>
42: #include <fcntl.h>
43: #include <limits.h>
44: #include <netdb.h>
1.1 deraadt 45: #include <signal.h>
46: #include <stdio.h>
1.38 canacar 47: #include <stdlib.h>
1.1 deraadt 48: #include <string.h>
1.38 canacar 49: #include <stdarg.h>
1.3 deraadt 50: #include <unistd.h>
1.35 deraadt 51: #include <utmp.h>
1.1 deraadt 52:
1.38 canacar 53: #include "engine.h"
1.1 deraadt 54: #include "systat.h"
55:
1.58 lum 56: #define TIMEPOS 55
57:
1.21 deraadt 58: double dellave;
1.1 deraadt 59:
1.21 deraadt 60: kvm_t *kd;
61: char *nlistf = NULL;
1.20 pvalchev 62: char *memf = NULL;
1.21 deraadt 63: double avenrun[3];
1.36 tedu 64: double naptime = 5.0;
1.21 deraadt 65: int verbose = 1; /* to report kvm read errs */
1.38 canacar 66: int nflag = 1;
1.35 deraadt 67: int ut, hz, stathz;
1.1 deraadt 68: char hostname[MAXHOSTNAMELEN];
69: WINDOW *wnd;
1.32 deraadt 70: int CMDLINE;
1.58 lum 71: char timebuf[26];
72: char uloadbuf[TIMEPOS];
1.1 deraadt 73:
1.38 canacar 74:
1.50 canacar 75: int ucount(void);
76: void usage(void);
77:
1.38 canacar 78: /* command prompt */
79:
1.46 canacar 80: void cmd_delay(const char *);
81: void cmd_count(const char *);
82: void cmd_compat(const char *);
1.38 canacar 83:
84: struct command cm_compat = {"Command", cmd_compat};
85: struct command cm_delay = {"Seconds to delay", cmd_delay};
86: struct command cm_count = {"Number of lines to display", cmd_count};
1.1 deraadt 87:
1.38 canacar 88:
89: /* display functions */
1.3 deraadt 90:
1.2 deraadt 91: int
1.38 canacar 92: print_header(void)
1.1 deraadt 93: {
1.50 canacar 94: time_t now;
1.40 deraadt 95: int start = dispstart + 1, end = dispstart + maxprint;
1.58 lum 96: char tmpbuf[TIMEPOS];
97: char header[MAX_LINE_BUF];
1.38 canacar 98:
99: if (end > num_disp)
100: end = num_disp;
101:
102: tb_start();
1.35 deraadt 103:
1.58 lum 104: if (!paused) {
105: getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0]));
1.38 canacar 106:
1.58 lum 107: snprintf(uloadbuf, sizeof(uloadbuf),
108: "%5d users Load %.2f %.2f %.2f",
109: ucount(), avenrun[0], avenrun[1], avenrun[2]);
1.25 deraadt 110:
1.58 lum 111: time(&now);
112: strlcpy(timebuf, ctime(&now), sizeof(timebuf));
113: }
1.25 deraadt 114:
1.58 lum 115: if (num_disp && (start > 1 || end != num_disp))
116: snprintf(tmpbuf, sizeof(tmpbuf),
117: "%s (%u-%u of %u) %s", uloadbuf, start, end, num_disp,
118: paused ? "PAUSED" : "");
119: else
120: snprintf(tmpbuf, sizeof(tmpbuf),
121: "%s %s", uloadbuf,
122: paused ? "PAUSED" : "");
123:
124: snprintf(header, sizeof(header), "%-55s%s", tmpbuf, timebuf);
125:
126: if (rawmode)
127: printf("\n\n%s\n", header);
128: else
129: mvprintw(0, 0, "%s", header);
1.24 deraadt 130:
1.38 canacar 131: return (1);
1.1 deraadt 132: }
1.3 deraadt 133:
1.38 canacar 134: /* compatibility functions, rearrange later */
1.21 deraadt 135: void
1.38 canacar 136: error(const char *fmt, ...)
1.21 deraadt 137: {
1.38 canacar 138: va_list ap;
139: char buf[MAX_LINE_BUF];
140:
141: va_start(ap, fmt);
142: vsnprintf(buf, sizeof buf, fmt, ap);
143: va_end(ap);
1.21 deraadt 144:
1.38 canacar 145: message_set(buf);
1.21 deraadt 146: }
147:
1.38 canacar 148: void
149: nlisterr(struct nlist namelist[])
1.3 deraadt 150: {
1.38 canacar 151: int i, n;
152:
153: n = 0;
154: clear();
155: mvprintw(2, 10, "systat: nlist: can't find following symbols:");
156: for (i = 0;
157: namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++)
158: if (namelist[i].n_value == 0)
159: mvprintw(2 + ++n, 10, "%s", namelist[i].n_name);
160: move(CMDLINE, 0);
161: clrtoeol();
162: refresh();
163: endwin();
1.3 deraadt 164: exit(1);
165: }
166:
1.1 deraadt 167: void
1.38 canacar 168: die(void)
1.1 deraadt 169: {
1.38 canacar 170: if (!rawmode)
171: endwin();
172: exit(0);
1.1 deraadt 173: }
174:
1.38 canacar 175:
176: int
177: prefix(char *s1, char *s2)
1.1 deraadt 178: {
1.38 canacar 179:
180: while (*s1 == *s2) {
181: if (*s1 == '\0')
182: return (1);
183: s1++, s2++;
184: }
185: return (*s1 == '\0');
1.21 deraadt 186: }
187:
1.38 canacar 188: /* calculate number of users on the system */
189: int
190: ucount(void)
1.21 deraadt 191: {
1.38 canacar 192: int nusers = 0;
193: struct utmp utmp;
1.35 deraadt 194:
1.38 canacar 195: if (ut < 0)
196: return (0);
197: lseek(ut, (off_t)0, SEEK_SET);
198: while (read(ut, &utmp, sizeof(utmp)))
199: if (utmp.ut_name[0] != '\0')
200: nusers++;
1.35 deraadt 201:
1.38 canacar 202: return (nusers);
1.1 deraadt 203: }
204:
1.38 canacar 205: /* main program functions */
206:
1.1 deraadt 207: void
1.50 canacar 208: usage(void)
1.1 deraadt 209: {
1.38 canacar 210: extern char *__progname;
1.55 sthen 211: fprintf(stderr, "usage: %s [-abiNn] [-d count] "
1.43 matthieu 212: "[-s delay] [-w width] [view] [delay]\n", __progname);
1.38 canacar 213: exit(1);
1.1 deraadt 214: }
215:
1.45 canacar 216: void
217: show_view(void)
218: {
219: if (rawmode)
220: return;
221:
222: tb_start();
223: tbprintf("%s %g", curr_view->name, naptime);
224: tb_end();
225: message_set(tmp_buf);
226: }
1.21 deraadt 227:
1.1 deraadt 228: void
1.38 canacar 229: add_view_tb(field_view *v)
1.1 deraadt 230: {
1.38 canacar 231: if (curr_view == v)
232: tbprintf("[%s] ", v->name);
233: else
234: tbprintf("%s ", v->name);
1.29 deraadt 235: }
236:
237: void
1.38 canacar 238: show_help(void)
1.29 deraadt 239: {
1.38 canacar 240: if (rawmode)
241: return;
242:
243: tb_start();
244: foreach_view(add_view_tb);
245: tb_end();
246: message_set(tmp_buf);
1.21 deraadt 247: }
248:
249: void
1.46 canacar 250: cmd_compat(const char *buf)
1.21 deraadt 251: {
1.46 canacar 252: const char *s;
1.38 canacar 253:
1.46 canacar 254: if (strcasecmp(buf, "help") == 0) {
1.38 canacar 255: show_help();
256: need_update = 1;
257: return;
258: }
1.46 canacar 259: if (strcasecmp(buf, "quit") == 0 || strcasecmp(buf, "q") == 0) {
1.38 canacar 260: gotsig_close = 1;
261: return;
262: }
1.46 canacar 263: if (strcasecmp(buf, "stop") == 0) {
264: paused = 1;
265: gotsig_alarm = 1;
266: return;
267: }
268: if (strncasecmp(buf, "start", 5) == 0) {
269: paused = 0;
270: gotsig_alarm = 1;
1.47 canacar 271: cmd_delay(buf + 5);
1.46 canacar 272: return;
273: }
1.38 canacar 274:
1.46 canacar 275: for (s = buf; *s && strchr("0123456789+-.eE", *s) != NULL; s++)
1.38 canacar 276: ;
277: if (*s) {
1.46 canacar 278: if (set_view(buf))
1.49 espie 279: error("Invalid/ambiguous view: %s", buf);
1.38 canacar 280: } else
1.46 canacar 281: cmd_delay(buf);
1.38 canacar 282: }
283:
284: void
1.46 canacar 285: cmd_delay(const char *buf)
1.38 canacar 286: {
287: double del;
1.46 canacar 288: del = atof(buf);
1.39 canacar 289:
1.38 canacar 290: if (del > 0) {
291: udelay = (useconds_t)(del * 1000000);
292: gotsig_alarm = 1;
1.39 canacar 293: naptime = del;
1.13 deraadt 294: }
1.1 deraadt 295: }
1.14 kstailey 296:
297: void
1.46 canacar 298: cmd_count(const char *buf)
1.14 kstailey 299: {
1.38 canacar 300: int ms;
1.46 canacar 301: ms = atoi(buf);
1.38 canacar 302:
303: if (ms <= 0 || ms > lines - HEADER_LINES)
304: maxprint = lines - HEADER_LINES;
305: else
306: maxprint = ms;
1.14 kstailey 307: }
308:
1.38 canacar 309:
310: int
311: keyboard_callback(int ch)
1.1 deraadt 312: {
1.38 canacar 313: switch (ch) {
314: case '?':
315: /* FALLTHROUGH */
316: case 'h':
317: show_help();
1.45 canacar 318: need_update = 1;
319: break;
320: case CTRL_G:
321: show_view();
1.38 canacar 322: need_update = 1;
323: break;
324: case 'l':
325: command_set(&cm_count, NULL);
326: break;
327: case 's':
328: command_set(&cm_delay, NULL);
1.59 ! mpf 329: break;
! 330: case ',':
! 331: separate_thousands = !separate_thousands;
! 332: gotsig_alarm = 1;
1.38 canacar 333: break;
334: case ':':
335: command_set(&cm_compat, NULL);
336: break;
337: default:
338: return 0;
339: };
340:
341: return 1;
342: }
1.23 millert 343:
1.38 canacar 344: void
345: initialize(void)
346: {
347: engine_initialize();
348:
349: initvmstat();
350: initpigs();
351: initifstat();
352: initiostat();
353: initsensors();
354: initmembufs();
355: initnetstat();
356: initswap();
357: initpftop();
358: initpf();
1.48 canacar 359: initpool();
1.51 canacar 360: initmalloc();
1.52 jasper 361: initnfs();
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.55 sthen 406: while ((ch = getopt(argc, argv, "Nabd:ins:w:")) != -1) {
1.38 canacar 407: switch (ch) {
408: case 'a':
409: maxlines = -1;
410: break;
411: case 'b':
412: rawmode = 1;
413: interactive = 0;
414: break;
415: case 'd':
416: countmax = atoi(optarg);
417: if (countmax < 0)
418: countmax = 0;
419: break;
420: case 'i':
421: interactive = 1;
422: break;
1.55 sthen 423: case 'N':
424: nflag = 0;
425: break;
1.38 canacar 426: case 'n':
1.55 sthen 427: /* this is a noop, -n is the default */
1.38 canacar 428: nflag = 1;
429: break;
430: case 's':
431: delay = atof(optarg);
1.39 canacar 432: if (delay <= 0)
1.38 canacar 433: delay = 5;
434: break;
435: case 'w':
436: rawwidth = atoi(optarg);
437: if (rawwidth < 1)
438: rawwidth = DEFAULT_WIDTH;
439: if (rawwidth >= MAX_LINE_BUF)
440: rawwidth = MAX_LINE_BUF - 1;
441: break;
442: default:
443: usage();
444: /* NOTREACHED */
445: }
446: }
1.43 matthieu 447:
448: if (kd == NULL)
449: warnx("kvm_openfiles: %s", errbuf);
1.38 canacar 450:
451: argc -= optind;
452: argv += optind;
453:
454: if (argc == 1) {
455: double del = atof(argv[0]);
456: if (del == 0)
457: viewstr = argv[0];
458: else
459: delay = del;
460: } else if (argc == 2) {
461: viewstr = argv[0];
462: delay = atof(argv[1]);
1.42 canacar 463: if (delay <= 0)
464: delay = 5;
1.38 canacar 465: }
466:
467: udelay = (useconds_t)(delay * 1000000.0);
468: if (udelay < 1)
469: udelay = 1;
1.39 canacar 470:
471: naptime = (double)udelay / 1000000.0;
1.38 canacar 472:
473: gethostname(hostname, sizeof (hostname));
474: gethz();
475:
476: initialize();
477:
478: set_order(NULL);
479: if (viewstr && set_view(viewstr)) {
1.49 espie 480: fprintf(stderr, "Unknown/ambiguous view name: %s\n", viewstr);
1.38 canacar 481: return 1;
482: }
483:
1.57 lum 484: if (check_termcap()) {
1.38 canacar 485: rawmode = 1;
486: interactive = 0;
487: }
488:
489: setup_term(maxlines);
490:
491: if (rawmode && countmax == 0)
492: countmax = 1;
493:
494: gotsig_alarm = 1;
1.35 deraadt 495:
1.38 canacar 496: engine_loop(countmax);
1.35 deraadt 497:
1.38 canacar 498: return 0;
1.1 deraadt 499: }