diff options
Diffstat (limited to 'usr.bin/systat/main.c')
-rw-r--r-- | usr.bin/systat/main.c | 672 |
1 files changed, 407 insertions, 265 deletions
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 5676b83235b..3896455ab82 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -1,65 +1,57 @@ -/* $OpenBSD: main.c,v 1.37 2007/05/21 21:15:37 cnst Exp $ */ -/* $NetBSD: main.c,v 1.8 1996/05/10 23:16:36 thorpej Exp $ */ - -/*- - * Copyright (c) 1980, 1992, 1993 - * The Regents of the University of California. All rights reserved. +/* $Id: main.c,v 1.38 2008/06/12 22:26:01 canacar Exp $ */ +/* + * Copyright (c) 2001, 2007 Can Erkin Acar + * Copyright (c) 2001 Daniel Hartmeier + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * */ -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1980, 1992, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; -#endif -static char rcsid[] = "$OpenBSD: main.c,v 1.37 2007/05/21 21:15:37 cnst Exp $"; -#endif /* not lint */ - +#include <sys/types.h> #include <sys/param.h> #include <sys/sysctl.h> + +#include <ctype.h> +#include <curses.h> #include <err.h> -#include <nlist.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <netdb.h> #include <signal.h> -#include <ctype.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <stdarg.h> #include <unistd.h> #include <utmp.h> -#include <stdlib.h> -#include <limits.h> -#include <stdarg.h> +#include "engine.h" #include "systat.h" -#include "extern.h" double dellave; @@ -69,300 +61,450 @@ char *memf = NULL; double avenrun[3]; double naptime = 5.0; int verbose = 1; /* to report kvm read errs */ -int nflag = 0; +int nflag = 1; int ut, hz, stathz; char hostname[MAXHOSTNAMELEN]; WINDOW *wnd; int CMDLINE; -WINDOW *wload; /* one line window for load average */ +#define TIMEPOS 55 + +/* command prompt */ + +void cmd_delay(void); +void cmd_count(void); +void cmd_compat(void); + +struct command cm_compat = {"Command", cmd_compat}; +struct command cm_delay = {"Seconds to delay", cmd_delay}; +struct command cm_count = {"Number of lines to display", cmd_count}; -static void usage(void); + +/* display functions */ int -main(int argc, char *argv[]) +print_header(void) { - char errbuf[_POSIX2_LINE_MAX]; - gid_t gid; - int ch; + struct tm *tp; + time_t t; + order_type *ordering; - ut = open(_PATH_UTMP, O_RDONLY); - if (ut < 0) { - error("No utmp"); - exit(1); - } + int start = dispstart + 1; + int end = dispstart + maxprint; - kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); - if (kd == NULL) { - error("%s", errbuf); - exit(1); + if (end > num_disp) + end = num_disp; + + tb_start(); + +#if 0 + if (curr_mgr && curr_mgr->sort_fn != NULL) { + ordering = curr_mgr->order_curr; + if (ordering != NULL) { + tbprintf(", Order: %s", ordering->name); + if (sortdir < 0 && ordering->func != NULL) + tbprintf(" (rev)"); + } } +#endif - gid = getgid(); - if (setresgid(gid, gid, gid) == -1) - err(1, "setresgid"); + getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); + extern int ucount(); + char tbuf[26]; + time_t now; - while ((ch = getopt(argc, argv, "nw:")) != -1) - switch (ch) { - case 'n': - nflag = 1; - break; - case 'w': + time(&now); + strlcpy(tbuf, ctime(&now), sizeof tbuf); + tbprintf(" %d users", ucount()); + tbprintf(" Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]); + if (num_disp && (start > 1 || end != num_disp)) + tbprintf(" (%u-%u of %u)", start, end, num_disp); - naptime = strtod(optarg, NULL); - if (naptime < 0.09 || naptime > 1000.0) - errx(1, "invalid interval: %s", optarg); - break; - default: - usage(); - } - argc -= optind; - argv += optind; + if (paused) + tbprintf(" PAUSED"); - while (argc > 0) { - if (isdigit(argv[0][0])) { - naptime = strtod(argv[0], NULL); - if (naptime < 0.09 || naptime > 1000.0) - naptime = 5.0; - } else { - struct cmdtab *p; - - p = lookup(&argv[0][0]); - if (p == (struct cmdtab *)-1) - errx(1, "ambiguous request: %s", &argv[0][0]); - if (p == 0) - errx(1, "unknown request: %s", &argv[0][0]); - curcmd = p; - } - argc--; - argv++; - } + if (rawmode) + printf("\n\n%s\n", tmp_buf); + else + mvprintw(0, 0, "%s", tmp_buf); - signal(SIGINT, sigdie); - siginterrupt(SIGINT, 1); - signal(SIGQUIT, sigdie); - siginterrupt(SIGQUIT, 1); - signal(SIGTERM, sigdie); - siginterrupt(SIGTERM, 1); - signal(SIGTSTP, sigtstp); - siginterrupt(SIGTSTP, 1); - - /* - * Initialize display. Load average appears in a one line - * window of its own. Current command's display appears in - * an overlapping sub-window of stdscr configured by the display - * routines to minimize update work by curses. - */ - if (initscr() == NULL) { - warnx("couldn't initialize screen"); - exit(0); - } + mvprintw(0, TIMEPOS, "%s", tbuf); - CMDLINE = LINES - 1; - wnd = (*curcmd->c_open)(); - if (wnd == NULL) { - warnx("couldn't initialize display"); - die(); - } - wload = newwin(1, 0, 1, 20); - if (wload == NULL) { - warnx("couldn't set up load average window"); - die(); - } - gethostname(hostname, sizeof (hostname)); - gethz(); - (*curcmd->c_init)(); - curcmd->c_flags |= CF_INIT; - labels(); - - dellave = 0.0; - - signal(SIGALRM, sigdisplay); - siginterrupt(SIGALRM, 1); - signal(SIGWINCH, sigwinch); - siginterrupt(SIGWINCH, 1); - gotdisplay = 1; - noecho(); - crmode(); - keyboard(); - /*NOTREACHED*/ + + return (1); } +/* compatibility functions, rearrange later */ void -gethz(void) +error(const char *fmt, ...) { - struct clockinfo cinf; - size_t size = sizeof(cinf); - int mib[2]; + va_list ap; + char buf[MAX_LINE_BUF]; - mib[0] = CTL_KERN; - mib[1] = KERN_CLOCKRATE; - if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) - return; - stathz = cinf.stathz; - hz = cinf.hz; -} + va_start(ap, fmt); + vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); -static void -usage(void) -{ - fprintf(stderr, "usage: systat [-n] [-w wait] [display] [refresh-interval]\n"); - exit(1); + message_set(buf); } - void -labels(void) +nlisterr(struct nlist namelist[]) { - if (curcmd->c_flags & CF_LOADAV) - mvprintw(0, 2 + 4, "users Load"); - (*curcmd->c_label)(); -#ifdef notdef - mvprintw(21, 25, "CPU usage on %s", hostname); -#endif + int i, n; + + n = 0; + clear(); + mvprintw(2, 10, "systat: nlist: can't find following symbols:"); + for (i = 0; + namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++) + if (namelist[i].n_value == 0) + mvprintw(2 + ++n, 10, "%s", namelist[i].n_name); + move(CMDLINE, 0); + clrtoeol(); refresh(); + endwin(); + exit(1); } -/*ARGSUSED*/ void -sigdisplay(int signo) +die(void) { - gotdisplay = 1; + if (!rawmode) + endwin(); + exit(0); } -void -display(void) + +int +prefix(char *s1, char *s2) { - /* Get the load average over the last minute. */ - (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); - (*curcmd->c_fetch)(); - if (curcmd->c_flags & CF_LOADAV) { - extern int ucount(); - char tbuf[26]; - time_t now; - - time(&now); - strlcpy(tbuf, ctime(&now), sizeof tbuf); - - putint(ucount(), 0, 2, 3); - putfloat(avenrun[0], 0, 2 + 17, 6, 2, 0); - putfloat(avenrun[1], 0, 2 + 23, 6, 2, 0); - putfloat(avenrun[2], 0, 2 + 29, 6, 2, 0); - mvaddstr(0, 2 + 53, tbuf); + + while (*s1 == *s2) { + if (*s1 == '\0') + return (1); + s1++, s2++; } - (*curcmd->c_refresh)(); - if (curcmd->c_flags & CF_LOADAV) - wrefresh(wload); - wrefresh(wnd); - move(CMDLINE, 0); - refresh(); - ualarm(naptime * 1000000, 0); + return (*s1 == '\0'); } -void -load(void) +/* calculate number of users on the system */ +int +ucount(void) { + int nusers = 0; + struct utmp utmp; - (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); - mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", - avenrun[0], avenrun[1], avenrun[2]); - clrtoeol(); + if (ut < 0) + return (0); + lseek(ut, (off_t)0, SEEK_SET); + while (read(ut, &utmp, sizeof(utmp))) + if (utmp.ut_name[0] != '\0') + nusers++; + + return (nusers); } -volatile sig_atomic_t gotdie; -volatile sig_atomic_t gotdisplay; -volatile sig_atomic_t gotwinch; -volatile sig_atomic_t gottstp; +/* main program functions */ -/*ARGSUSED*/ void -sigdie(int signo) +usage() { - gotdie = 1; + extern char *__progname; + fprintf(stderr, "usage: %s [-abhir] [-c cache] [-d cnt]", __progname); + fprintf(stderr, " [-o field] [-s time] [-w width] [view] [num]\n"); + exit(1); } -/*ARGSUSED*/ + void -sigtstp(int signo) +add_view_tb(field_view *v) { - gottstp = 1; + if (curr_view == v) + tbprintf("[%s] ", v->name); + else + tbprintf("%s ", v->name); } void -die(void) +show_help(void) { - if (wnd) { - move(CMDLINE, 0); - clrtoeol(); - refresh(); - endwin(); + int line = 0; + + if (rawmode) + return; + + tb_start(); + foreach_view(add_view_tb); + tb_end(); + message_set(tmp_buf); + +#if 0 + erase(); + mvprintw(line, 2, "Systat Help"); + line += 2; + mvprintw(line, 5, " h - Help (this page)"); + mvprintw(line++, 40, " l - set number of Lines"); + mvprintw(line, 5, " p - Pause display"); + mvprintw(line++, 40, " s - Set update interval"); + mvprintw(line, 5, " v - next View"); + mvprintw(line++, 40, " q - Quit"); + line++; + mvprintw(line++, 5, "0-7 - select view directly"); + mvprintw(line++, 5, "SPC - update immediately"); + mvprintw(line++, 5, "^L - refresh display"); + line++; + mvprintw(line++, 5, "cursor keys - scroll display"); + line++; + mvprintw(line++, 3, "Netstat specific keys::"); + mvprintw(line, 5, " t - toggle TCP display"); + mvprintw(line++, 40, " u - toggle UDP display"); + mvprintw(line++, 5, " n - toggle Name resolution"); + line++; + mvprintw(line++, 3, "Ifstat specific keys::"); + mvprintw(line, 5, " r - initialize RUN mode"); + mvprintw(line++, 40, " b - set BOOT mode"); + mvprintw(line, 5, " t - set TIME mode (default)"); + line++; + line++; + mvprintw(line++, 3, "VMstat specific keys::"); + mvprintw(line, 5, " r - initialize RUN mode"); + mvprintw(line++, 40, " b - set BOOT mode"); + mvprintw(line, 5, " t - set TIME mode (default)"); + mvprintw(line++, 40, " z - zero in RUN mode"); + line++; + mvprintw(line++, 6, "press any key to continue ..."); + + while (getch() == ERR) { + if (gotsig_close) + break; } - exit(0); +#endif } -/*ARGSUSED*/ void -sigwinch(int signo) +cmd_compat(void) { - gotwinch = 1; + char *s; + + if (strcasecmp(cmdbuf, "help") == 0) { + show_help(); + need_update = 1; + return; + } + if (strcasecmp(cmdbuf, "quit") == 0) { + gotsig_close = 1; + return; + } + + for (s = cmdbuf; *s && strchr("0123456789+-.eE", *s) != NULL; s++) + ; + if (*s) { + if (set_view(cmdbuf)) + error("Invalid/ambigious view: %s", cmdbuf); + } else + cmd_delay(); } void -error(const char *fmt, ...) +cmd_delay(void) { - va_list ap; - char buf[255]; - int oy, ox; - - va_start(ap, fmt); - if (wnd) { - getyx(stdscr, oy, ox); - (void) vsnprintf(buf, sizeof buf, fmt, ap); - clrtoeol(); - standout(); - mvaddstr(CMDLINE, 0, buf); - standend(); - move(oy, ox); - refresh(); - } else { - (void) vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + double del; + del = atof(cmdbuf); + error("delay: %g", del); + if (del > 0) { + udelay = (useconds_t)(del * 1000000); + gotsig_alarm = 1; } - va_end(ap); } void -nlisterr(struct nlist namelist[]) +cmd_count(void) { - int i, n; + int ms; + ms = atoi(cmdbuf); - n = 0; - clear(); - mvprintw(2, 10, "systat: nlist: can't find following symbols:"); - for (i = 0; - namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++) - if (namelist[i].n_value == 0) - mvprintw(2 + ++n, 10, "%s", namelist[i].n_name); - move(CMDLINE, 0); - clrtoeol(); - refresh(); - endwin(); - exit(1); + if (ms <= 0 || ms > lines - HEADER_LINES) + maxprint = lines - HEADER_LINES; + else + maxprint = ms; } -/* calculate number of users on the system */ + int -ucount(void) +keyboard_callback(int ch) { - int nusers = 0; - struct utmp utmp; + switch (ch) { + case '?': + /* FALLTHROUGH */ + case 'h': + show_help(); + need_update = 1; + break; + case 'l': + command_set(&cm_count, NULL); + break; + case 's': + command_set(&cm_delay, NULL); + break; + case ':': + command_set(&cm_compat, NULL); + break; + default: + return 0; + }; + + return 1; +} - if (ut < 0) - return (0); - lseek(ut, (off_t)0, SEEK_SET); - while (read(ut, &utmp, sizeof(utmp))) - if (utmp.ut_name[0] != '\0') - nusers++; +void +initialize(void) +{ + engine_initialize(); + + initvmstat(); + initpigs(); + initifstat(); + initiostat(); + initsensors(); + initmembufs(); + initnetstat(); + initswap(); + initpftop(); + initpf(); +} - return (nusers); +void +gethz(void) +{ + struct clockinfo cinf; + size_t size = sizeof(cinf); + int mib[2]; + + mib[0] = CTL_KERN; + mib[1] = KERN_CLOCKRATE; + if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) + return; + stathz = cinf.stathz; + hz = cinf.hz; +} + +int +main(int argc, char *argv[]) +{ + char errbuf[_POSIX2_LINE_MAX]; + extern char *optarg; + extern int optind; + double delay = 5; + + char *viewstr = NULL; + + gid_t gid; + int countmax = 0; + int maxlines = 0; + + int ch; + + ut = open(_PATH_UTMP, O_RDONLY); + if (ut < 0) { + warn("No utmp"); + } + + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); + if (kd == NULL) + warnx("kvm_openfiles: %s", errbuf); + + gid = getgid(); + if (setresgid(gid, gid, gid) == -1) + err(1, "setresgid"); + + while ((ch = getopt(argc, argv, "abd:hins:S:w:")) != -1) { + switch (ch) { + case 'a': + maxlines = -1; + break; + case 'b': + rawmode = 1; + interactive = 0; + break; + case 'd': + countmax = atoi(optarg); + if (countmax < 0) + countmax = 0; + break; + case 'i': + interactive = 1; + break; + case 'n': + nflag = 1; + break; + case 's': + delay = atof(optarg); + if (delay < 0) + delay = 5; + break; + case 'S': + dispstart = atoi(optarg); + if (dispstart < 0) + dispstart = 0; + break; + case 'w': + rawwidth = atoi(optarg); + if (rawwidth < 1) + rawwidth = DEFAULT_WIDTH; + if (rawwidth >= MAX_LINE_BUF) + rawwidth = MAX_LINE_BUF - 1; + break; + case 'h': + /* FALLTHROUGH */ + default: + usage(); + /* NOTREACHED */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) { + double del = atof(argv[0]); + if (del == 0) + viewstr = argv[0]; + else + delay = del; + } else if (argc == 2) { + viewstr = argv[0]; + delay = atof(argv[1]); + } + + udelay = (useconds_t)(delay * 1000000.0); + if (udelay < 1) + udelay = 1; + + gethostname(hostname, sizeof (hostname)); + gethz(); + + initialize(); + + set_order(NULL); + if (viewstr && set_view(viewstr)) { + fprintf(stderr, "Unknown/ambigious view name: %s\n", viewstr); + return 1; + } + + if (!isatty(STDOUT_FILENO)) { + rawmode = 1; + interactive = 0; + } + + setup_term(maxlines); + + if (rawmode && countmax == 0) + countmax = 1; + + gotsig_alarm = 1; + + engine_loop(countmax); + + return 0; } |