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