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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3087715Smarkm#include <sys/cdefs.h> 3187715Smarkm 3287715Smarkm__FBSDID("$FreeBSD$"); 3387715Smarkm 3487715Smarkm#ifdef lint 3587715Smarkmstatic const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 3687715Smarkm#endif 3787715Smarkm 381590Srgrimes#ifndef lint 3987715Smarkmstatic const char copyright[] = 401590Srgrimes"@(#) Copyright (c) 1980, 1992, 1993\n\ 411590Srgrimes The Regents of the University of California. All rights reserved.\n"; 4228149Scharnier#endif 431590Srgrimes 441590Srgrimes#include <sys/param.h> 4570118Srwatson#include <sys/time.h> 4674671Stmm#include <sys/sysctl.h> 471590Srgrimes 4828149Scharnier#include <err.h> 4977205Stmm#include <limits.h> 5014953Sache#include <locale.h> 511590Srgrimes#include <nlist.h> 52200462Sdelphij#include <paths.h> 531590Srgrimes#include <signal.h> 541590Srgrimes#include <stdio.h> 5540060Sobrien#include <stdlib.h> 5640060Sobrien#include <unistd.h> 5787715Smarkm 581590Srgrimes#include "systat.h" 591590Srgrimes#include "extern.h" 601590Srgrimes 611590Srgrimesstatic int dellave; 621590Srgrimes 631590Srgrimeskvm_t *kd; 641590Srgrimessig_t sigtstpdfl; 651590Srgrimesdouble avenrun[3]; 661590Srgrimesint col; 67240605Smelifarounsigned int delay = 5000000; /* in microseconds */ 681590Srgrimesint verbose = 1; /* to report kvm read errs */ 6970118Srwatsonstruct clockinfo clkinfo; 704930Sbdedouble hertz; 711590Srgrimeschar c; 721590Srgrimeschar *namp; 731590Srgrimeschar hostname[MAXHOSTNAMELEN]; 741590SrgrimesWINDOW *wnd; 751590Srgrimesint CMDLINE; 7674671Stmmint use_kvm = 1; 771590Srgrimes 781590Srgrimesstatic WINDOW *wload; /* one line window for load average */ 791590Srgrimes 8028789Scharnierint 81126775Sdwmalonemain(int argc, char **argv) 821590Srgrimes{ 8377205Stmm char errbuf[_POSIX2_LINE_MAX], dummy; 8469140Srwatson size_t size; 85240605Smelifaro double t; 861590Srgrimes 87199242Sume (void) setlocale(LC_ALL, ""); 8814953Sache 891590Srgrimes argc--, argv++; 901590Srgrimes while (argc > 0) { 911590Srgrimes if (argv[0][0] == '-') { 921590Srgrimes struct cmdtab *p; 931590Srgrimes 941590Srgrimes p = lookup(&argv[0][1]); 9528149Scharnier if (p == (struct cmdtab *)-1) 9628149Scharnier errx(1, "%s: ambiguous request", &argv[0][1]); 9728149Scharnier if (p == (struct cmdtab *)0) 9828149Scharnier errx(1, "%s: unknown request", &argv[0][1]); 991590Srgrimes curcmd = p; 1001590Srgrimes } else { 101240605Smelifaro t = strtod(argv[0], NULL) * 1000000.0; 102240605Smelifaro if (t > 0 && t < (double)UINT_MAX) 103240605Smelifaro delay = (unsigned int)t; 1041590Srgrimes } 1051590Srgrimes argc--, argv++; 1061590Srgrimes } 1071590Srgrimes kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 10874671Stmm if (kd != NULL) { 109158161Sbde /* 11074671Stmm * Try to actually read something, we may be in a jail, and 11174671Stmm * have /dev/null opened as /dev/mem. 11274671Stmm */ 113158161Sbde if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 || 11474671Stmm kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) != 11574671Stmm sizeof(dummy)) { 11674671Stmm kvm_close(kd); 11774671Stmm kd = NULL; 11874671Stmm } 11974671Stmm } 1201590Srgrimes if (kd == NULL) { 121158161Sbde /* 12274671Stmm * Maybe we are lacking permissions? Retry, this time with bogus 12374671Stmm * devices. We can now use sysctl only. 12474671Stmm */ 12574671Stmm use_kvm = 0; 12677205Stmm kd = kvm_openfiles("/dev/null", "/dev/null", "/dev/null", 12777205Stmm O_RDONLY, errbuf); 12874671Stmm if (kd == NULL) { 12974671Stmm error("%s", errbuf); 13074671Stmm exit(1); 13174671Stmm } 1321590Srgrimes } 133197956Sjh signal(SIGHUP, die); 1341590Srgrimes signal(SIGINT, die); 1351590Srgrimes signal(SIGQUIT, die); 1361590Srgrimes signal(SIGTERM, die); 1371590Srgrimes 1381590Srgrimes /* 1391590Srgrimes * Initialize display. Load average appears in a one line 1401590Srgrimes * window of its own. Current command's display appears in 1411590Srgrimes * an overlapping sub-window of stdscr configured by the display 1421590Srgrimes * routines to minimize update work by curses. 1431590Srgrimes */ 1441590Srgrimes initscr(); 1451590Srgrimes CMDLINE = LINES - 1; 1461590Srgrimes wnd = (*curcmd->c_open)(); 1471590Srgrimes if (wnd == NULL) { 14828149Scharnier warnx("couldn't initialize display"); 1491590Srgrimes die(0); 1501590Srgrimes } 151158160Sbde wload = newwin(1, 0, 1, 20); 1521590Srgrimes if (wload == NULL) { 15328149Scharnier warnx("couldn't set up load average window"); 1541590Srgrimes die(0); 1551590Srgrimes } 15669140Srwatson gethostname(hostname, sizeof (hostname)); 15769140Srwatson size = sizeof(clkinfo); 15887715Smarkm if (sysctlbyname("kern.clockrate", &clkinfo, &size, NULL, 0) 15987715Smarkm || size != sizeof(clkinfo)) { 16070118Srwatson error("kern.clockrate"); 16169140Srwatson die(0); 1627011Sphk } 16370118Srwatson hertz = clkinfo.stathz; 1641590Srgrimes (*curcmd->c_init)(); 1651590Srgrimes curcmd->c_flags |= CF_INIT; 1661590Srgrimes labels(); 1671590Srgrimes 1681590Srgrimes dellave = 0.0; 1691590Srgrimes 170240605Smelifaro display(); 1711590Srgrimes noecho(); 1721590Srgrimes crmode(); 1731590Srgrimes keyboard(); 1741590Srgrimes /*NOTREACHED*/ 17540060Sobrien 17640060Sobrien return EXIT_SUCCESS; 1771590Srgrimes} 1781590Srgrimes 1791590Srgrimesvoid 180175387Sdelphijlabels(void) 1811590Srgrimes{ 1821590Srgrimes if (curcmd->c_flags & CF_LOADAV) { 183158160Sbde mvaddstr(0, 20, 1841590Srgrimes "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10"); 185158160Sbde mvaddstr(1, 5, "Load Average"); 1861590Srgrimes } 1871590Srgrimes (*curcmd->c_label)(); 1881590Srgrimes#ifdef notdef 1891590Srgrimes mvprintw(21, 25, "CPU usage on %s", hostname); 1901590Srgrimes#endif 1911590Srgrimes refresh(); 1921590Srgrimes} 1931590Srgrimes 1941590Srgrimesvoid 195246987Scharnierdisplay(void) 1961590Srgrimes{ 19787715Smarkm int i, j; 1981590Srgrimes 1991590Srgrimes /* Get the load average over the last minute. */ 2001590Srgrimes (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); 2011590Srgrimes (*curcmd->c_fetch)(); 2021590Srgrimes if (curcmd->c_flags & CF_LOADAV) { 2031590Srgrimes j = 5.0*avenrun[0] + 0.5; 2041590Srgrimes dellave -= avenrun[0]; 2051590Srgrimes if (dellave >= 0.0) 2061590Srgrimes c = '<'; 2071590Srgrimes else { 2081590Srgrimes c = '>'; 2091590Srgrimes dellave = -dellave; 2101590Srgrimes } 2111590Srgrimes if (dellave < 0.1) 2121590Srgrimes c = '|'; 2131590Srgrimes dellave = avenrun[0]; 2141590Srgrimes wmove(wload, 0, 0); wclrtoeol(wload); 2151590Srgrimes for (i = (j > 50) ? 50 : j; i > 0; i--) 2161590Srgrimes waddch(wload, c); 2171590Srgrimes if (j > 50) 2181590Srgrimes wprintw(wload, " %4.1f", avenrun[0]); 2191590Srgrimes } 2201590Srgrimes (*curcmd->c_refresh)(); 2211590Srgrimes if (curcmd->c_flags & CF_LOADAV) 2221590Srgrimes wrefresh(wload); 2231590Srgrimes wrefresh(wnd); 2241590Srgrimes move(CMDLINE, col); 2251590Srgrimes refresh(); 2261590Srgrimes} 2271590Srgrimes 2281590Srgrimesvoid 229175387Sdelphijload(void) 2301590Srgrimes{ 2311590Srgrimes 2321590Srgrimes (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); 2331590Srgrimes mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", 2341590Srgrimes avenrun[0], avenrun[1], avenrun[2]); 2351590Srgrimes clrtoeol(); 2361590Srgrimes} 2371590Srgrimes 2381590Srgrimesvoid 239175387Sdelphijdie(int signo __unused) 2401590Srgrimes{ 2411590Srgrimes move(CMDLINE, 0); 2421590Srgrimes clrtoeol(); 2431590Srgrimes refresh(); 2441590Srgrimes endwin(); 2451590Srgrimes exit(0); 2461590Srgrimes} 2471590Srgrimes 2481590Srgrimes#include <stdarg.h> 2491590Srgrimes 2501590Srgrimesvoid 2511590Srgrimeserror(const char *fmt, ...) 2521590Srgrimes{ 2531590Srgrimes va_list ap; 2541590Srgrimes char buf[255]; 2551590Srgrimes int oy, ox; 25693058Simp 2571590Srgrimes va_start(ap, fmt); 2581590Srgrimes if (wnd) { 2591590Srgrimes getyx(stdscr, oy, ox); 26036789Simp (void) vsnprintf(buf, sizeof(buf), fmt, ap); 2611590Srgrimes clrtoeol(); 2621590Srgrimes standout(); 2631590Srgrimes mvaddstr(CMDLINE, 0, buf); 2641590Srgrimes standend(); 2651590Srgrimes move(oy, ox); 2661590Srgrimes refresh(); 2671590Srgrimes } else { 2681590Srgrimes (void) vfprintf(stderr, fmt, ap); 2691590Srgrimes fprintf(stderr, "\n"); 2701590Srgrimes } 2711590Srgrimes va_end(ap); 2721590Srgrimes} 2731590Srgrimes 2741590Srgrimesvoid 275175387Sdelphijnlisterr(struct nlist n_list[]) 2761590Srgrimes{ 2771590Srgrimes int i, n; 2781590Srgrimes 2791590Srgrimes n = 0; 2801590Srgrimes clear(); 2811590Srgrimes mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 2821590Srgrimes for (i = 0; 28387715Smarkm n_list[i].n_name != NULL && *n_list[i].n_name != '\0'; i++) 28487715Smarkm if (n_list[i].n_value == 0) 28587715Smarkm mvprintw(2 + ++n, 10, "%s", n_list[i].n_name); 2861590Srgrimes move(CMDLINE, 0); 2871590Srgrimes clrtoeol(); 2881590Srgrimes refresh(); 2891590Srgrimes endwin(); 2901590Srgrimes exit(1); 2911590Srgrimes} 292