main.c revision 126775
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 3487715Smarkm#include <sys/cdefs.h> 3587715Smarkm 3687715Smarkm__FBSDID("$FreeBSD: head/usr.bin/systat/main.c 126775 2004-03-09 11:57:28Z dwmalone $"); 3787715Smarkm 3887715Smarkm#ifdef lint 3987715Smarkmstatic const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 4087715Smarkm#endif 4187715Smarkm 421590Srgrimes#ifndef lint 4387715Smarkmstatic const char copyright[] = 441590Srgrimes"@(#) Copyright (c) 1980, 1992, 1993\n\ 451590Srgrimes The Regents of the University of California. All rights reserved.\n"; 4628149Scharnier#endif 471590Srgrimes 481590Srgrimes#include <sys/param.h> 4970118Srwatson#include <sys/time.h> 5074671Stmm#include <sys/sysctl.h> 511590Srgrimes 5228149Scharnier#include <err.h> 5377205Stmm#include <limits.h> 5414953Sache#include <locale.h> 551590Srgrimes#include <nlist.h> 5669140Srwatson#include <paths.h> 571590Srgrimes#include <signal.h> 581590Srgrimes#include <stdio.h> 5940060Sobrien#include <stdlib.h> 6040060Sobrien#include <unistd.h> 6187715Smarkm 621590Srgrimes#include "systat.h" 631590Srgrimes#include "extern.h" 641590Srgrimes 651590Srgrimesstatic int dellave; 661590Srgrimes 671590Srgrimeskvm_t *kd; 681590Srgrimessig_t sigtstpdfl; 691590Srgrimesdouble avenrun[3]; 701590Srgrimesint col; 711590Srgrimesint naptime = 5; 721590Srgrimesint verbose = 1; /* to report kvm read errs */ 7370118Srwatsonstruct clockinfo clkinfo; 744930Sbdedouble hertz; 751590Srgrimeschar c; 761590Srgrimeschar *namp; 771590Srgrimeschar hostname[MAXHOSTNAMELEN]; 781590SrgrimesWINDOW *wnd; 791590Srgrimesint CMDLINE; 8074671Stmmint use_kvm = 1; 811590Srgrimes 821590Srgrimesstatic WINDOW *wload; /* one line window for load average */ 831590Srgrimes 8428789Scharnierint 85126775Sdwmalonemain(int argc, char **argv) 861590Srgrimes{ 8777205Stmm char errbuf[_POSIX2_LINE_MAX], dummy; 8869140Srwatson size_t size; 891590Srgrimes 9014953Sache (void) setlocale(LC_TIME, ""); 9114953Sache 921590Srgrimes argc--, argv++; 931590Srgrimes while (argc > 0) { 941590Srgrimes if (argv[0][0] == '-') { 951590Srgrimes struct cmdtab *p; 961590Srgrimes 971590Srgrimes p = lookup(&argv[0][1]); 9828149Scharnier if (p == (struct cmdtab *)-1) 9928149Scharnier errx(1, "%s: ambiguous request", &argv[0][1]); 10028149Scharnier if (p == (struct cmdtab *)0) 10128149Scharnier errx(1, "%s: unknown request", &argv[0][1]); 1021590Srgrimes curcmd = p; 1031590Srgrimes } else { 1041590Srgrimes naptime = atoi(argv[0]); 1051590Srgrimes if (naptime <= 0) 1061590Srgrimes naptime = 5; 1071590Srgrimes } 1081590Srgrimes argc--, argv++; 1091590Srgrimes } 1101590Srgrimes kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 11174671Stmm if (kd != NULL) { 11274671Stmm /* 11374671Stmm * Try to actually read something, we may be in a jail, and 11474671Stmm * have /dev/null opened as /dev/mem. 11574671Stmm */ 11674671Stmm if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 || 11774671Stmm kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) != 11874671Stmm sizeof(dummy)) { 11974671Stmm kvm_close(kd); 12074671Stmm kd = NULL; 12174671Stmm } 12274671Stmm } 1231590Srgrimes if (kd == NULL) { 12474671Stmm /* 12574671Stmm * Maybe we are lacking permissions? Retry, this time with bogus 12674671Stmm * devices. We can now use sysctl only. 12774671Stmm */ 12874671Stmm use_kvm = 0; 12977205Stmm kd = kvm_openfiles("/dev/null", "/dev/null", "/dev/null", 13077205Stmm O_RDONLY, errbuf); 13174671Stmm if (kd == NULL) { 13274671Stmm error("%s", errbuf); 13374671Stmm exit(1); 13474671Stmm } 1351590Srgrimes } 1361590Srgrimes signal(SIGINT, die); 1371590Srgrimes signal(SIGQUIT, die); 1381590Srgrimes signal(SIGTERM, die); 1391590Srgrimes 1401590Srgrimes /* 1411590Srgrimes * Initialize display. Load average appears in a one line 1421590Srgrimes * window of its own. Current command's display appears in 1431590Srgrimes * an overlapping sub-window of stdscr configured by the display 1441590Srgrimes * routines to minimize update work by curses. 1451590Srgrimes */ 1461590Srgrimes initscr(); 1471590Srgrimes CMDLINE = LINES - 1; 1481590Srgrimes wnd = (*curcmd->c_open)(); 1491590Srgrimes if (wnd == NULL) { 15028149Scharnier warnx("couldn't initialize display"); 1511590Srgrimes die(0); 1521590Srgrimes } 1531590Srgrimes wload = newwin(1, 0, 3, 20); 1541590Srgrimes if (wload == NULL) { 15528149Scharnier warnx("couldn't set up load average window"); 1561590Srgrimes die(0); 1571590Srgrimes } 15869140Srwatson gethostname(hostname, sizeof (hostname)); 15969140Srwatson size = sizeof(clkinfo); 16087715Smarkm if (sysctlbyname("kern.clockrate", &clkinfo, &size, NULL, 0) 16187715Smarkm || size != sizeof(clkinfo)) { 16270118Srwatson error("kern.clockrate"); 16369140Srwatson die(0); 1647011Sphk } 16570118Srwatson hertz = clkinfo.stathz; 1661590Srgrimes (*curcmd->c_init)(); 1671590Srgrimes curcmd->c_flags |= CF_INIT; 1681590Srgrimes labels(); 1691590Srgrimes 1701590Srgrimes dellave = 0.0; 1711590Srgrimes 1721590Srgrimes signal(SIGALRM, display); 1731590Srgrimes display(0); 1741590Srgrimes noecho(); 1751590Srgrimes crmode(); 1761590Srgrimes keyboard(); 1771590Srgrimes /*NOTREACHED*/ 17840060Sobrien 17940060Sobrien return EXIT_SUCCESS; 1801590Srgrimes} 1811590Srgrimes 1821590Srgrimesvoid 1831590Srgrimeslabels() 1841590Srgrimes{ 1851590Srgrimes if (curcmd->c_flags & CF_LOADAV) { 1861590Srgrimes mvaddstr(2, 20, 1871590Srgrimes "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10"); 1881590Srgrimes mvaddstr(3, 5, "Load Average"); 1891590Srgrimes } 1901590Srgrimes (*curcmd->c_label)(); 1911590Srgrimes#ifdef notdef 1921590Srgrimes mvprintw(21, 25, "CPU usage on %s", hostname); 1931590Srgrimes#endif 1941590Srgrimes refresh(); 1951590Srgrimes} 1961590Srgrimes 1971590Srgrimesvoid 1981590Srgrimesdisplay(signo) 19987715Smarkm int signo __unused; 2001590Srgrimes{ 20187715Smarkm int i, j; 2021590Srgrimes 2031590Srgrimes /* Get the load average over the last minute. */ 2041590Srgrimes (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); 2051590Srgrimes (*curcmd->c_fetch)(); 2061590Srgrimes if (curcmd->c_flags & CF_LOADAV) { 2071590Srgrimes j = 5.0*avenrun[0] + 0.5; 2081590Srgrimes dellave -= avenrun[0]; 2091590Srgrimes if (dellave >= 0.0) 2101590Srgrimes c = '<'; 2111590Srgrimes else { 2121590Srgrimes c = '>'; 2131590Srgrimes dellave = -dellave; 2141590Srgrimes } 2151590Srgrimes if (dellave < 0.1) 2161590Srgrimes c = '|'; 2171590Srgrimes dellave = avenrun[0]; 2181590Srgrimes wmove(wload, 0, 0); wclrtoeol(wload); 2191590Srgrimes for (i = (j > 50) ? 50 : j; i > 0; i--) 2201590Srgrimes waddch(wload, c); 2211590Srgrimes if (j > 50) 2221590Srgrimes wprintw(wload, " %4.1f", avenrun[0]); 2231590Srgrimes } 2241590Srgrimes (*curcmd->c_refresh)(); 2251590Srgrimes if (curcmd->c_flags & CF_LOADAV) 2261590Srgrimes wrefresh(wload); 2271590Srgrimes wrefresh(wnd); 2281590Srgrimes move(CMDLINE, col); 2291590Srgrimes refresh(); 2301590Srgrimes alarm(naptime); 2311590Srgrimes} 2321590Srgrimes 2331590Srgrimesvoid 2341590Srgrimesload() 2351590Srgrimes{ 2361590Srgrimes 2371590Srgrimes (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); 2381590Srgrimes mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", 2391590Srgrimes avenrun[0], avenrun[1], avenrun[2]); 2401590Srgrimes clrtoeol(); 2411590Srgrimes} 2421590Srgrimes 2431590Srgrimesvoid 2441590Srgrimesdie(signo) 24587715Smarkm int signo __unused; 2461590Srgrimes{ 2471590Srgrimes move(CMDLINE, 0); 2481590Srgrimes clrtoeol(); 2491590Srgrimes refresh(); 2501590Srgrimes endwin(); 2511590Srgrimes exit(0); 2521590Srgrimes} 2531590Srgrimes 2541590Srgrimes#include <stdarg.h> 2551590Srgrimes 2561590Srgrimesvoid 2571590Srgrimeserror(const char *fmt, ...) 2581590Srgrimes{ 2591590Srgrimes va_list ap; 2601590Srgrimes char buf[255]; 2611590Srgrimes int oy, ox; 26293058Simp 2631590Srgrimes va_start(ap, fmt); 2641590Srgrimes if (wnd) { 2651590Srgrimes getyx(stdscr, oy, ox); 26636789Simp (void) vsnprintf(buf, sizeof(buf), fmt, ap); 2671590Srgrimes clrtoeol(); 2681590Srgrimes standout(); 2691590Srgrimes mvaddstr(CMDLINE, 0, buf); 2701590Srgrimes standend(); 2711590Srgrimes move(oy, ox); 2721590Srgrimes refresh(); 2731590Srgrimes } else { 2741590Srgrimes (void) vfprintf(stderr, fmt, ap); 2751590Srgrimes fprintf(stderr, "\n"); 2761590Srgrimes } 2771590Srgrimes va_end(ap); 2781590Srgrimes} 2791590Srgrimes 2801590Srgrimesvoid 28187715Smarkmnlisterr(n_list) 28287715Smarkm struct nlist n_list[]; 2831590Srgrimes{ 2841590Srgrimes int i, n; 2851590Srgrimes 2861590Srgrimes n = 0; 2871590Srgrimes clear(); 2881590Srgrimes mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 2891590Srgrimes for (i = 0; 29087715Smarkm n_list[i].n_name != NULL && *n_list[i].n_name != '\0'; i++) 29187715Smarkm if (n_list[i].n_value == 0) 29287715Smarkm mvprintw(2 + ++n, 10, "%s", n_list[i].n_name); 2931590Srgrimes move(CMDLINE, 0); 2941590Srgrimes clrtoeol(); 2951590Srgrimes refresh(); 2961590Srgrimes endwin(); 2971590Srgrimes exit(1); 2981590Srgrimes} 299