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 87262643Sbrooks#ifdef USE_WIDECHAR 88199242Sume (void) setlocale(LC_ALL, ""); 89262643Sbrooks#else 90262643Sbrooks (void) setlocale(LC_TIME, ""); 91262643Sbrooks#endif 9214953Sache 931590Srgrimes argc--, argv++; 941590Srgrimes while (argc > 0) { 951590Srgrimes if (argv[0][0] == '-') { 961590Srgrimes struct cmdtab *p; 971590Srgrimes 981590Srgrimes p = lookup(&argv[0][1]); 9928149Scharnier if (p == (struct cmdtab *)-1) 10028149Scharnier errx(1, "%s: ambiguous request", &argv[0][1]); 10128149Scharnier if (p == (struct cmdtab *)0) 10228149Scharnier errx(1, "%s: unknown request", &argv[0][1]); 1031590Srgrimes curcmd = p; 1041590Srgrimes } else { 105240605Smelifaro t = strtod(argv[0], NULL) * 1000000.0; 106240605Smelifaro if (t > 0 && t < (double)UINT_MAX) 107240605Smelifaro delay = (unsigned int)t; 1081590Srgrimes } 1091590Srgrimes argc--, argv++; 1101590Srgrimes } 1111590Srgrimes kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 11274671Stmm if (kd != NULL) { 113158161Sbde /* 11474671Stmm * Try to actually read something, we may be in a jail, and 11574671Stmm * have /dev/null opened as /dev/mem. 11674671Stmm */ 117158161Sbde if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 || 11874671Stmm kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) != 11974671Stmm sizeof(dummy)) { 12074671Stmm kvm_close(kd); 12174671Stmm kd = NULL; 12274671Stmm } 12374671Stmm } 1241590Srgrimes if (kd == NULL) { 125158161Sbde /* 12674671Stmm * Maybe we are lacking permissions? Retry, this time with bogus 12774671Stmm * devices. We can now use sysctl only. 12874671Stmm */ 12974671Stmm use_kvm = 0; 13077205Stmm kd = kvm_openfiles("/dev/null", "/dev/null", "/dev/null", 13177205Stmm O_RDONLY, errbuf); 13274671Stmm if (kd == NULL) { 13374671Stmm error("%s", errbuf); 13474671Stmm exit(1); 13574671Stmm } 1361590Srgrimes } 137197956Sjh signal(SIGHUP, die); 1381590Srgrimes signal(SIGINT, die); 1391590Srgrimes signal(SIGQUIT, die); 1401590Srgrimes signal(SIGTERM, die); 1411590Srgrimes 1421590Srgrimes /* 1431590Srgrimes * Initialize display. Load average appears in a one line 1441590Srgrimes * window of its own. Current command's display appears in 1451590Srgrimes * an overlapping sub-window of stdscr configured by the display 1461590Srgrimes * routines to minimize update work by curses. 1471590Srgrimes */ 1481590Srgrimes initscr(); 1491590Srgrimes CMDLINE = LINES - 1; 1501590Srgrimes wnd = (*curcmd->c_open)(); 1511590Srgrimes if (wnd == NULL) { 15228149Scharnier warnx("couldn't initialize display"); 1531590Srgrimes die(0); 1541590Srgrimes } 155158160Sbde wload = newwin(1, 0, 1, 20); 1561590Srgrimes if (wload == NULL) { 15728149Scharnier warnx("couldn't set up load average window"); 1581590Srgrimes die(0); 1591590Srgrimes } 16069140Srwatson gethostname(hostname, sizeof (hostname)); 16169140Srwatson size = sizeof(clkinfo); 16287715Smarkm if (sysctlbyname("kern.clockrate", &clkinfo, &size, NULL, 0) 16387715Smarkm || size != sizeof(clkinfo)) { 16470118Srwatson error("kern.clockrate"); 16569140Srwatson die(0); 1667011Sphk } 16770118Srwatson hertz = clkinfo.stathz; 1681590Srgrimes (*curcmd->c_init)(); 1691590Srgrimes curcmd->c_flags |= CF_INIT; 1701590Srgrimes labels(); 1711590Srgrimes 1721590Srgrimes dellave = 0.0; 1731590Srgrimes 174240605Smelifaro display(); 1751590Srgrimes noecho(); 1761590Srgrimes crmode(); 1771590Srgrimes keyboard(); 1781590Srgrimes /*NOTREACHED*/ 17940060Sobrien 18040060Sobrien return EXIT_SUCCESS; 1811590Srgrimes} 1821590Srgrimes 1831590Srgrimesvoid 184175387Sdelphijlabels(void) 1851590Srgrimes{ 1861590Srgrimes if (curcmd->c_flags & CF_LOADAV) { 187158160Sbde mvaddstr(0, 20, 1881590Srgrimes "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10"); 189158160Sbde mvaddstr(1, 5, "Load Average"); 1901590Srgrimes } 1911590Srgrimes (*curcmd->c_label)(); 1921590Srgrimes#ifdef notdef 1931590Srgrimes mvprintw(21, 25, "CPU usage on %s", hostname); 1941590Srgrimes#endif 1951590Srgrimes refresh(); 1961590Srgrimes} 1971590Srgrimes 1981590Srgrimesvoid 199246987Scharnierdisplay(void) 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} 2311590Srgrimes 2321590Srgrimesvoid 233175387Sdelphijload(void) 2341590Srgrimes{ 2351590Srgrimes 2361590Srgrimes (void) getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); 2371590Srgrimes mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", 2381590Srgrimes avenrun[0], avenrun[1], avenrun[2]); 2391590Srgrimes clrtoeol(); 2401590Srgrimes} 2411590Srgrimes 2421590Srgrimesvoid 243175387Sdelphijdie(int signo __unused) 2441590Srgrimes{ 2451590Srgrimes move(CMDLINE, 0); 2461590Srgrimes clrtoeol(); 2471590Srgrimes refresh(); 2481590Srgrimes endwin(); 2491590Srgrimes exit(0); 2501590Srgrimes} 2511590Srgrimes 2521590Srgrimes#include <stdarg.h> 2531590Srgrimes 2541590Srgrimesvoid 2551590Srgrimeserror(const char *fmt, ...) 2561590Srgrimes{ 2571590Srgrimes va_list ap; 2581590Srgrimes char buf[255]; 2591590Srgrimes int oy, ox; 26093058Simp 2611590Srgrimes va_start(ap, fmt); 2621590Srgrimes if (wnd) { 2631590Srgrimes getyx(stdscr, oy, ox); 26436789Simp (void) vsnprintf(buf, sizeof(buf), fmt, ap); 2651590Srgrimes clrtoeol(); 2661590Srgrimes standout(); 2671590Srgrimes mvaddstr(CMDLINE, 0, buf); 2681590Srgrimes standend(); 2691590Srgrimes move(oy, ox); 2701590Srgrimes refresh(); 2711590Srgrimes } else { 2721590Srgrimes (void) vfprintf(stderr, fmt, ap); 2731590Srgrimes fprintf(stderr, "\n"); 2741590Srgrimes } 2751590Srgrimes va_end(ap); 2761590Srgrimes} 2771590Srgrimes 2781590Srgrimesvoid 279175387Sdelphijnlisterr(struct nlist n_list[]) 2801590Srgrimes{ 2811590Srgrimes int i, n; 2821590Srgrimes 2831590Srgrimes n = 0; 2841590Srgrimes clear(); 2851590Srgrimes mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 2861590Srgrimes for (i = 0; 28787715Smarkm n_list[i].n_name != NULL && *n_list[i].n_name != '\0'; i++) 28887715Smarkm if (n_list[i].n_value == 0) 28987715Smarkm mvprintw(2 + ++n, 10, "%s", n_list[i].n_name); 2901590Srgrimes move(CMDLINE, 0); 2911590Srgrimes clrtoeol(); 2921590Srgrimes refresh(); 2931590Srgrimes endwin(); 2941590Srgrimes exit(1); 2951590Srgrimes} 296