vmstat.c revision 12805
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1983, 1989, 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
341590Srgrimes#ifndef lint
351590Srgrimesstatic char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 1/12/94";
361590Srgrimes#endif /* not lint */
371590Srgrimes
381590Srgrimes/*
391590Srgrimes * Cursed vmstat -- from Robert Elz.
401590Srgrimes */
411590Srgrimes
421590Srgrimes#include <sys/param.h>
431590Srgrimes#include <sys/dkstat.h>
441590Srgrimes#include <sys/buf.h>
451590Srgrimes#include <sys/stat.h>
461590Srgrimes#include <sys/time.h>
471590Srgrimes#include <sys/user.h>
481590Srgrimes#include <sys/proc.h>
491590Srgrimes#include <sys/namei.h>
501590Srgrimes#include <sys/sysctl.h>
5112805Speter#include <sys/vmmeter.h>
521590Srgrimes#include <vm/vm.h>
531590Srgrimes
541590Srgrimes#include <signal.h>
551590Srgrimes#include <nlist.h>
561590Srgrimes#include <ctype.h>
571590Srgrimes#include <utmp.h>
581590Srgrimes#include <paths.h>
591590Srgrimes#include <string.h>
601590Srgrimes#include <stdlib.h>
611590Srgrimes#include <unistd.h>
621590Srgrimes#include "systat.h"
631590Srgrimes#include "extern.h"
641590Srgrimes
651590Srgrimesstatic struct Info {
661590Srgrimes	long	time[CPUSTATES];
671590Srgrimes	struct	vmmeter Cnt;
681590Srgrimes	struct	vmtotal Total;
691590Srgrimes	long	*dk_time;
701590Srgrimes	long	*dk_wds;
711590Srgrimes	long	*dk_seek;
721590Srgrimes	long	*dk_xfer;
731590Srgrimes	int	dk_busy;
741590Srgrimes	struct	nchstats nchstats;
751590Srgrimes	long	nchcount;
761590Srgrimes	long	*intrcnt;
776988Sdg	int		bufspace;
781590Srgrimes} s, s1, s2, z;
791590Srgrimes
801590Srgrimes#define	cnt s.Cnt
811590Srgrimes#define oldcnt s1.Cnt
821590Srgrimes#define	total s.Total
831590Srgrimes#define	nchtotal s.nchstats
841590Srgrimes#define	oldnchtotal s1.nchstats
851590Srgrimes
861590Srgrimesstatic	enum state { BOOT, TIME, RUN } state = TIME;
871590Srgrimes
881590Srgrimesstatic void allocinfo __P((struct Info *));
891590Srgrimesstatic void copyinfo __P((struct Info *, struct Info *));
901590Srgrimesstatic float cputime __P((int));
911590Srgrimesstatic void dinfo __P((int, int));
921590Srgrimesstatic void getinfo __P((struct Info *, enum state));
931590Srgrimesstatic void putint __P((int, int, int, int));
941590Srgrimesstatic void putfloat __P((double, int, int, int, int, int));
951590Srgrimesstatic int ucount __P((void));
961590Srgrimes
971590Srgrimesstatic	int ut;
981590Srgrimesstatic	char buf[26];
991590Srgrimesstatic	time_t t;
1001590Srgrimesstatic	double etime;
1011590Srgrimesstatic	int nintr;
1021590Srgrimesstatic	long *intrloc;
1031590Srgrimesstatic	char **intrname;
1041590Srgrimesstatic	int nextintsrow;
1051590Srgrimes
1061590Srgrimesstruct	utmp utmp;
1071590Srgrimes
1081590Srgrimes
1091590SrgrimesWINDOW *
1101590Srgrimesopenkre()
1111590Srgrimes{
1121590Srgrimes
1131590Srgrimes	ut = open(_PATH_UTMP, O_RDONLY);
1141590Srgrimes	if (ut < 0)
1151590Srgrimes		error("No utmp");
1161590Srgrimes	return (stdscr);
1171590Srgrimes}
1181590Srgrimes
1191590Srgrimesvoid
1201590Srgrimesclosekre(w)
1211590Srgrimes	WINDOW *w;
1221590Srgrimes{
1231590Srgrimes
1241590Srgrimes	(void) close(ut);
1251590Srgrimes	if (w == NULL)
1261590Srgrimes		return;
1271590Srgrimes	wclear(w);
1281590Srgrimes	wrefresh(w);
1291590Srgrimes}
1301590Srgrimes
1311590Srgrimes
1321590Srgrimesstatic struct nlist namelist[] = {
1331590Srgrimes#define X_CPTIME	0
1341590Srgrimes	{ "_cp_time" },
1351590Srgrimes#define X_CNT		1
1361590Srgrimes	{ "_cnt" },
1379501Sbde#define	X_BUFFERSPACE	2
1389501Sbde	{ "_bufspace" },
1391590Srgrimes#define	X_DK_BUSY	3
1401590Srgrimes	{ "_dk_busy" },
1411590Srgrimes#define	X_DK_TIME	4
1421590Srgrimes	{ "_dk_time" },
1431590Srgrimes#define	X_DK_XFER	5
1441590Srgrimes	{ "_dk_xfer" },
1451590Srgrimes#define	X_DK_WDS	6
1461590Srgrimes	{ "_dk_wds" },
1471590Srgrimes#define	X_DK_SEEK	7
1481590Srgrimes	{ "_dk_seek" },
1491590Srgrimes#define	X_NCHSTATS	8
1501590Srgrimes	{ "_nchstats" },
1511590Srgrimes#define	X_INTRNAMES	9
1521590Srgrimes	{ "_intrnames" },
1531590Srgrimes#define	X_EINTRNAMES	10
1541590Srgrimes	{ "_eintrnames" },
1551590Srgrimes#define	X_INTRCNT	11
1561590Srgrimes	{ "_intrcnt" },
1571590Srgrimes#define	X_EINTRCNT	12
1581590Srgrimes	{ "_eintrcnt" },
1591590Srgrimes	{ "" },
1601590Srgrimes};
1611590Srgrimes
1621590Srgrimes/*
1631590Srgrimes * These constants define where the major pieces are laid out
1641590Srgrimes */
1651590Srgrimes#define STATROW		 0	/* uses 1 row and 68 cols */
1661590Srgrimes#define STATCOL		 2
1671590Srgrimes#define MEMROW		 2	/* uses 4 rows and 31 cols */
1681590Srgrimes#define MEMCOL		 0
1691590Srgrimes#define PAGEROW		 2	/* uses 4 rows and 26 cols */
1701590Srgrimes#define PAGECOL		36
1711590Srgrimes#define INTSROW		 2	/* uses all rows to bottom and 17 cols */
1727455Sdg#define INTSCOL		61
1731590Srgrimes#define PROCSROW	 7	/* uses 2 rows and 20 cols */
1741590Srgrimes#define PROCSCOL	 0
1751590Srgrimes#define GENSTATROW	 7	/* uses 2 rows and 30 cols */
1761590Srgrimes#define GENSTATCOL	20
1774808Sdg#define VMSTATROW	 6	/* uses 17 rows and 12 cols */
1781590Srgrimes#define VMSTATCOL	48
1791590Srgrimes#define GRAPHROW	10	/* uses 3 rows and 51 cols */
1801590Srgrimes#define GRAPHCOL	 0
1811590Srgrimes#define NAMEIROW	14	/* uses 3 rows and 38 cols */
1821590Srgrimes#define NAMEICOL	 0
1831590Srgrimes#define DISKROW		18	/* uses 5 rows and 50 cols (for 9 drives) */
1841590Srgrimes#define DISKCOL		 0
1851590Srgrimes
1861590Srgrimes#define	DRIVESPACE	 9	/* max # for space */
1871590Srgrimes
1881590Srgrimes#if DK_NDRIVE > DRIVESPACE
1891590Srgrimes#define	MAXDRIVES	DRIVESPACE	 /* max # to display */
1901590Srgrimes#else
1911590Srgrimes#define	MAXDRIVES	DK_NDRIVE	 /* max # to display */
1921590Srgrimes#endif
1931590Srgrimes
1941590Srgrimesint
1951590Srgrimesinitkre()
1961590Srgrimes{
1971590Srgrimes	char *intrnamebuf, *cp;
1981590Srgrimes	int i;
1991590Srgrimes	static int once = 0;
2001590Srgrimes
2011590Srgrimes	if (namelist[0].n_type == 0) {
2021590Srgrimes		if (kvm_nlist(kd, namelist)) {
2031590Srgrimes			nlisterr(namelist);
2041590Srgrimes			return(0);
2051590Srgrimes		}
2061590Srgrimes		if (namelist[0].n_type == 0) {
2071590Srgrimes			error("No namelist");
2081590Srgrimes			return(0);
2091590Srgrimes		}
2101590Srgrimes	}
2111590Srgrimes	if (! dkinit())
2121590Srgrimes		return(0);
2131590Srgrimes	if (dk_ndrive && !once) {
2141590Srgrimes#define	allocate(e, t) \
2151590Srgrimes    s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
2161590Srgrimes    s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
2171590Srgrimes    s2./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
2181590Srgrimes    z./**/e = (t *)calloc(dk_ndrive, sizeof (t));
2191590Srgrimes		allocate(dk_time, long);
2201590Srgrimes		allocate(dk_wds, long);
2211590Srgrimes		allocate(dk_seek, long);
2221590Srgrimes		allocate(dk_xfer, long);
2231590Srgrimes		once = 1;
2241590Srgrimes#undef allocate
2251590Srgrimes	}
2261590Srgrimes	if (nintr == 0) {
2271590Srgrimes		nintr = (namelist[X_EINTRCNT].n_value -
2281590Srgrimes			namelist[X_INTRCNT].n_value) / sizeof (long);
2291590Srgrimes		intrloc = calloc(nintr, sizeof (long));
2301590Srgrimes		intrname = calloc(nintr, sizeof (long));
2311590Srgrimes		intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
2321590Srgrimes			namelist[X_INTRNAMES].n_value);
2331590Srgrimes		if (intrnamebuf == 0 || intrname == 0 || intrloc == 0) {
2341590Srgrimes			error("Out of memory\n");
2351590Srgrimes			if (intrnamebuf)
2361590Srgrimes				free(intrnamebuf);
2371590Srgrimes			if (intrname)
2381590Srgrimes				free(intrname);
2391590Srgrimes			if (intrloc)
2401590Srgrimes				free(intrloc);
2411590Srgrimes			nintr = 0;
2421590Srgrimes			return(0);
2431590Srgrimes		}
2441590Srgrimes		NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
2451590Srgrimes			NVAL(X_INTRNAMES));
2461590Srgrimes		for (cp = intrnamebuf, i = 0; i < nintr; i++) {
2471590Srgrimes			intrname[i] = cp;
2481590Srgrimes			cp += strlen(cp) + 1;
2491590Srgrimes		}
2501590Srgrimes		nextintsrow = INTSROW + 2;
2511590Srgrimes		allocinfo(&s);
2521590Srgrimes		allocinfo(&s1);
2531590Srgrimes		allocinfo(&s2);
2541590Srgrimes		allocinfo(&z);
2551590Srgrimes	}
2561590Srgrimes	getinfo(&s2, RUN);
2571590Srgrimes	copyinfo(&s2, &s1);
2581590Srgrimes	return(1);
2591590Srgrimes}
2601590Srgrimes
2611590Srgrimesvoid
2621590Srgrimesfetchkre()
2631590Srgrimes{
2641590Srgrimes	time_t now;
2651590Srgrimes
2661590Srgrimes	time(&now);
2671590Srgrimes	strcpy(buf, ctime(&now));
2681590Srgrimes	buf[16] = '\0';
2691590Srgrimes	getinfo(&s, state);
2701590Srgrimes}
2711590Srgrimes
2721590Srgrimesvoid
2731590Srgrimeslabelkre()
2741590Srgrimes{
2751590Srgrimes	register int i, j;
2761590Srgrimes
2771590Srgrimes	clear();
2781590Srgrimes	mvprintw(STATROW, STATCOL + 4, "users    Load");
2791590Srgrimes	mvprintw(MEMROW, MEMCOL, "Mem:KB  REAL        VIRTUAL");
2801590Srgrimes	mvprintw(MEMROW + 1, MEMCOL, "      Tot Share    Tot  Share");
2811590Srgrimes	mvprintw(MEMROW + 2, MEMCOL, "Act");
2821590Srgrimes	mvprintw(MEMROW + 3, MEMCOL, "All");
2831590Srgrimes
2841590Srgrimes	mvprintw(MEMROW + 1, MEMCOL + 31, "Free");
2851590Srgrimes
2863614Sdg	mvprintw(PAGEROW, PAGECOL,     "        VN PAGER  SWAP PAGER ");
2873614Sdg	mvprintw(PAGEROW + 1, PAGECOL, "        in  out     in  out ");
2881590Srgrimes	mvprintw(PAGEROW + 2, PAGECOL, "count");
2891590Srgrimes	mvprintw(PAGEROW + 3, PAGECOL, "pages");
2901590Srgrimes
2911590Srgrimes	mvprintw(INTSROW, INTSCOL + 3, " Interrupts");
2921590Srgrimes	mvprintw(INTSROW + 1, INTSCOL + 9, "total");
2931590Srgrimes
2941590Srgrimes	mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "cow");
2957348Sdg	mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "zfod");
2967351Sdg	mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "wire");
2977351Sdg	mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "act");
2987351Sdg	mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "inact");
2997351Sdg	mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "cache");
3007351Sdg	mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "free");
3017351Sdg	mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "daefr");
3027351Sdg	mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "prcfr");
3037351Sdg	mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "react");
3047351Sdg	mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "pdwake");
3057351Sdg	mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "pdpgs");
3067351Sdg	mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "intrn");
3077351Sdg	mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "buf");
3081590Srgrimes
3091590Srgrimes	mvprintw(GENSTATROW, GENSTATCOL, "  Csw  Trp  Sys  Int  Sof  Flt");
3101590Srgrimes
3111590Srgrimes	mvprintw(GRAPHROW, GRAPHCOL,
3124930Sbde		"  . %%Sys    . %%Intr   . %%User   . %%Nice   . %%Idle");
3131590Srgrimes	mvprintw(PROCSROW, PROCSCOL, "Proc:r  p  d  s  w");
3141590Srgrimes	mvprintw(GRAPHROW + 1, GRAPHCOL,
3151590Srgrimes		"|    |    |    |    |    |    |    |    |    |    |");
3161590Srgrimes
3177012Sphk	mvprintw(NAMEIROW, NAMEICOL, "Namei         Name-cache    Proc-cache");
3181590Srgrimes	mvprintw(NAMEIROW + 1, NAMEICOL,
3191590Srgrimes		"    Calls     hits    %%     hits     %%");
3201590Srgrimes	mvprintw(DISKROW, DISKCOL, "Discs");
3211590Srgrimes	mvprintw(DISKROW + 1, DISKCOL, "seeks");
3221590Srgrimes	mvprintw(DISKROW + 2, DISKCOL, "xfers");
3231590Srgrimes	mvprintw(DISKROW + 3, DISKCOL, " blks");
3241590Srgrimes	mvprintw(DISKROW + 4, DISKCOL, " msps");
3251590Srgrimes	j = 0;
3261590Srgrimes	for (i = 0; i < dk_ndrive && j < MAXDRIVES; i++)
3271590Srgrimes		if (dk_select[i]) {
3281590Srgrimes			mvprintw(DISKROW, DISKCOL + 5 + 5 * j,
3291590Srgrimes				"  %3.3s", dr_name[j]);
3301590Srgrimes			j++;
3311590Srgrimes		}
3321590Srgrimes	for (i = 0; i < nintr; i++) {
3331590Srgrimes		if (intrloc[i] == 0)
3341590Srgrimes			continue;
3357455Sdg		mvprintw(intrloc[i], INTSCOL + 9, "%-10.10s", intrname[i]);
3361590Srgrimes	}
3371590Srgrimes}
3381590Srgrimes
3391590Srgrimes#define X(fld)	{t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;}
3401590Srgrimes#define Y(fld)	{t = s.fld; s.fld -= s1.fld; if(state == TIME) s1.fld = t;}
3411590Srgrimes#define Z(fld)	{t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \
3421590Srgrimes	if(state == TIME) s1.nchstats.fld = t;}
3431590Srgrimes#define PUTRATE(fld, l, c, w) \
3441590Srgrimes	Y(fld); \
3451590Srgrimes	putint((int)((float)s.fld/etime + 0.5), l, c, w)
3461590Srgrimes#define MAXFAIL 5
3471590Srgrimes
3484930Sbdestatic	char cpuchar[CPUSTATES] = { '=' , '+', '>', '-', ' ' };
3494930Sbdestatic	char cpuorder[CPUSTATES] = { CP_SYS, CP_INTR, CP_USER, CP_NICE,
3504930Sbde				     CP_IDLE };
3511590Srgrimes
3521590Srgrimesvoid
3531590Srgrimesshowkre()
3541590Srgrimes{
3551590Srgrimes	float f1, f2;
3561590Srgrimes	int psiz, inttotal;
3571590Srgrimes	int i, l, c;
3581590Srgrimes	static int failcnt = 0;
3591590Srgrimes
3601590Srgrimes	for (i = 0; i < dk_ndrive; i++) {
3611590Srgrimes		X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
3621590Srgrimes	}
3631590Srgrimes	etime = 0;
3641590Srgrimes	for(i = 0; i < CPUSTATES; i++) {
3651590Srgrimes		X(time);
3661590Srgrimes		etime += s.time[i];
3671590Srgrimes	}
3681590Srgrimes	if (etime < 5.0) {	/* < 5 ticks - ignore this trash */
3691590Srgrimes		if (failcnt++ >= MAXFAIL) {
3701590Srgrimes			clear();
3711590Srgrimes			mvprintw(2, 10, "The alternate system clock has died!");
3721590Srgrimes			mvprintw(3, 10, "Reverting to ``pigs'' display.");
3731590Srgrimes			move(CMDLINE, 0);
3741590Srgrimes			refresh();
3751590Srgrimes			failcnt = 0;
3761590Srgrimes			sleep(5);
3771590Srgrimes			command("pigs");
3781590Srgrimes		}
3791590Srgrimes		return;
3801590Srgrimes	}
3811590Srgrimes	failcnt = 0;
3821590Srgrimes	etime /= hertz;
3831590Srgrimes	inttotal = 0;
3841590Srgrimes	for (i = 0; i < nintr; i++) {
3851590Srgrimes		if (s.intrcnt[i] == 0)
3861590Srgrimes			continue;
3871590Srgrimes		if (intrloc[i] == 0) {
3881590Srgrimes			if (nextintsrow == LINES)
3891590Srgrimes				continue;
3901590Srgrimes			intrloc[i] = nextintsrow++;
3917455Sdg			mvprintw(intrloc[i], INTSCOL + 9, "%-10.10s",
3921590Srgrimes				intrname[i]);
3931590Srgrimes		}
3941590Srgrimes		X(intrcnt);
3951590Srgrimes		l = (int)((float)s.intrcnt[i]/etime + 0.5);
3961590Srgrimes		inttotal += l;
3977455Sdg		putint(l, intrloc[i], INTSCOL + 2, 6);
3981590Srgrimes	}
3997455Sdg	putint(inttotal, INTSROW + 1, INTSCOL + 2, 6);
4001590Srgrimes	Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss);
4017138Sphk	Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); Z(ncs_neghits);
4021590Srgrimes	s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits +
4037012Sphk	    nchtotal.ncs_miss + nchtotal.ncs_long + nchtotal.ncs_neghits;
4041590Srgrimes	if (state == TIME)
4051590Srgrimes		s1.nchcount = s.nchcount;
4061590Srgrimes
4071590Srgrimes	psiz = 0;
4081590Srgrimes	f2 = 0.0;
4094930Sbde	for (c = 0; c < CPUSTATES; c++) {
4101590Srgrimes		i = cpuorder[c];
4111590Srgrimes		f1 = cputime(i);
4121590Srgrimes		f2 += f1;
4131590Srgrimes		l = (int) ((f2 + 1.0) / 2.0) - psiz;
4144930Sbde		if (f1 > 99.9)
4154930Sbde			f1 = 99.9;	/* no room to display 100.0 */
4164930Sbde		putfloat(f1, GRAPHROW, GRAPHCOL + 10 * c, 4, 1, 0);
4171590Srgrimes		move(GRAPHROW + 2, psiz);
4181590Srgrimes		psiz += l;
4191590Srgrimes		while (l-- > 0)
4201590Srgrimes			addch(cpuchar[c]);
4211590Srgrimes	}
4221590Srgrimes
4231590Srgrimes	putint(ucount(), STATROW, STATCOL, 3);
4241590Srgrimes	putfloat(avenrun[0], STATROW, STATCOL + 17, 6, 2, 0);
4251590Srgrimes	putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0);
4261590Srgrimes	putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0);
4271590Srgrimes	mvaddstr(STATROW, STATCOL + 53, buf);
4281590Srgrimes#define pgtokb(pg)	((pg) * cnt.v_page_size / 1024)
4291590Srgrimes	putint(pgtokb(total.t_arm), MEMROW + 2, MEMCOL + 3, 6);
4301590Srgrimes	putint(pgtokb(total.t_armshr), MEMROW + 2, MEMCOL + 9, 6);
4311590Srgrimes	putint(pgtokb(total.t_avm), MEMROW + 2, MEMCOL + 15, 7);
4321590Srgrimes	putint(pgtokb(total.t_avmshr), MEMROW + 2, MEMCOL + 22, 7);
4331590Srgrimes	putint(pgtokb(total.t_rm), MEMROW + 3, MEMCOL + 3, 6);
4341590Srgrimes	putint(pgtokb(total.t_rmshr), MEMROW + 3, MEMCOL + 9, 6);
4351590Srgrimes	putint(pgtokb(total.t_vm), MEMROW + 3, MEMCOL + 15, 7);
4361590Srgrimes	putint(pgtokb(total.t_vmshr), MEMROW + 3, MEMCOL + 22, 7);
4371590Srgrimes	putint(pgtokb(total.t_free), MEMROW + 2, MEMCOL + 29, 6);
4381590Srgrimes	putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3);
4391590Srgrimes	putint(total.t_pw, PROCSROW + 1, PROCSCOL + 6, 3);
4401590Srgrimes	putint(total.t_dw, PROCSROW + 1, PROCSCOL + 9, 3);
4411590Srgrimes	putint(total.t_sl, PROCSROW + 1, PROCSCOL + 12, 3);
4421590Srgrimes	putint(total.t_sw, PROCSROW + 1, PROCSCOL + 15, 3);
4431590Srgrimes	PUTRATE(Cnt.v_cow_faults, VMSTATROW + 0, VMSTATCOL + 3, 6);
4447348Sdg	PUTRATE(Cnt.v_zfod, VMSTATROW + 1, VMSTATCOL + 4, 5);
4457351Sdg	putint(pgtokb(cnt.v_wire_count), VMSTATROW + 2, VMSTATCOL, 9);
4467351Sdg	putint(pgtokb(cnt.v_active_count), VMSTATROW + 3, VMSTATCOL, 9);
4477351Sdg	putint(pgtokb(cnt.v_inactive_count), VMSTATROW + 4, VMSTATCOL, 9);
4487351Sdg	putint(pgtokb(cnt.v_cache_count), VMSTATROW + 5, VMSTATCOL, 9);
4497351Sdg	putint(pgtokb(cnt.v_free_count), VMSTATROW + 6, VMSTATCOL, 9);
4507351Sdg	PUTRATE(Cnt.v_dfree, VMSTATROW + 7, VMSTATCOL, 9);
4517351Sdg	PUTRATE(Cnt.v_pfree, VMSTATROW + 8, VMSTATCOL, 9);
4527351Sdg	PUTRATE(Cnt.v_reactivated, VMSTATROW + 9, VMSTATCOL, 9);
4537351Sdg	PUTRATE(Cnt.v_pdwakeups, VMSTATROW + 10, VMSTATCOL, 9);
4547351Sdg	PUTRATE(Cnt.v_pdpages, VMSTATROW + 11, VMSTATCOL, 9);
4557351Sdg	PUTRATE(Cnt.v_intrans, VMSTATROW + 12, VMSTATCOL, 9);
4567351Sdg	putint(s.bufspace/1024, VMSTATROW + 13, VMSTATCOL, 9);
4573614Sdg	PUTRATE(Cnt.v_vnodein, PAGEROW + 2, PAGECOL + 5, 5);
4583614Sdg	PUTRATE(Cnt.v_vnodeout, PAGEROW + 2, PAGECOL + 10, 5);
4593614Sdg	PUTRATE(Cnt.v_swapin, PAGEROW + 2, PAGECOL + 17, 5);
4603614Sdg	PUTRATE(Cnt.v_swapout, PAGEROW + 2, PAGECOL + 22, 5);
4613614Sdg	PUTRATE(Cnt.v_vnodepgsin, PAGEROW + 3, PAGECOL + 5, 5);
4623614Sdg	PUTRATE(Cnt.v_vnodepgsout, PAGEROW + 3, PAGECOL + 10, 5);
4633614Sdg	PUTRATE(Cnt.v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5);
4643614Sdg	PUTRATE(Cnt.v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5);
4651590Srgrimes	PUTRATE(Cnt.v_swtch, GENSTATROW + 1, GENSTATCOL, 5);
4661590Srgrimes	PUTRATE(Cnt.v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5);
4671590Srgrimes	PUTRATE(Cnt.v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5);
4681590Srgrimes	PUTRATE(Cnt.v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5);
4691590Srgrimes	PUTRATE(Cnt.v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5);
4703614Sdg	PUTRATE(Cnt.v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5);
4711590Srgrimes	mvprintw(DISKROW, DISKCOL + 5, "                              ");
4721590Srgrimes	for (i = 0, c = 0; i < dk_ndrive && c < MAXDRIVES; i++)
4731590Srgrimes		if (dk_select[i]) {
4741590Srgrimes			mvprintw(DISKROW, DISKCOL + 5 + 5 * c,
4751590Srgrimes				"  %3.3s", dr_name[i]);
4761590Srgrimes			dinfo(i, ++c);
4771590Srgrimes		}
4781590Srgrimes	putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9);
4797012Sphk	putint((nchtotal.ncs_goodhits + nchtotal.ncs_neghits),
4807012Sphk	   NAMEIROW + 2, NAMEICOL + 9, 9);
4811590Srgrimes#define nz(x)	((x) ? (x) : 1)
4828874Srgrimes	putfloat((nchtotal.ncs_goodhits+nchtotal.ncs_neghits) *
4837012Sphk	   100.0 / nz(s.nchcount),
4841590Srgrimes	   NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1);
4851590Srgrimes	putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 23, 9);
4861590Srgrimes	putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount),
4871590Srgrimes	   NAMEIROW + 2, NAMEICOL + 34, 4, 0, 1);
4881590Srgrimes#undef nz
4891590Srgrimes}
4901590Srgrimes
4911590Srgrimesint
4921590Srgrimescmdkre(cmd, args)
4931590Srgrimes	char *cmd, *args;
4941590Srgrimes{
4951590Srgrimes
4961590Srgrimes	if (prefix(cmd, "run")) {
4971590Srgrimes		copyinfo(&s2, &s1);
4981590Srgrimes		state = RUN;
4991590Srgrimes		return (1);
5001590Srgrimes	}
5011590Srgrimes	if (prefix(cmd, "boot")) {
5021590Srgrimes		state = BOOT;
5031590Srgrimes		copyinfo(&z, &s1);
5041590Srgrimes		return (1);
5051590Srgrimes	}
5061590Srgrimes	if (prefix(cmd, "time")) {
5071590Srgrimes		state = TIME;
5081590Srgrimes		return (1);
5091590Srgrimes	}
5101590Srgrimes	if (prefix(cmd, "zero")) {
5111590Srgrimes		if (state == RUN)
5121590Srgrimes			getinfo(&s1, RUN);
5131590Srgrimes		return (1);
5141590Srgrimes	}
5151590Srgrimes	return (dkcmd(cmd, args));
5161590Srgrimes}
5171590Srgrimes
5181590Srgrimes/* calculate number of users on the system */
5191590Srgrimesstatic int
5201590Srgrimesucount()
5211590Srgrimes{
5221590Srgrimes	register int nusers = 0;
5231590Srgrimes
5241590Srgrimes	if (ut < 0)
5251590Srgrimes		return (0);
5261590Srgrimes	while (read(ut, &utmp, sizeof(utmp)))
5271590Srgrimes		if (utmp.ut_name[0] != '\0')
5281590Srgrimes			nusers++;
5291590Srgrimes
5301590Srgrimes	lseek(ut, 0L, L_SET);
5311590Srgrimes	return (nusers);
5321590Srgrimes}
5331590Srgrimes
5341590Srgrimesstatic float
5351590Srgrimescputime(indx)
5361590Srgrimes	int indx;
5371590Srgrimes{
5381590Srgrimes	double t;
5391590Srgrimes	register int i;
5401590Srgrimes
5411590Srgrimes	t = 0;
5421590Srgrimes	for (i = 0; i < CPUSTATES; i++)
5431590Srgrimes		t += s.time[i];
5441590Srgrimes	if (t == 0.0)
5451590Srgrimes		t = 1.0;
5461590Srgrimes	return (s.time[indx] * 100.0 / t);
5471590Srgrimes}
5481590Srgrimes
5491590Srgrimesstatic void
5501590Srgrimesputint(n, l, c, w)
5511590Srgrimes	int n, l, c, w;
5521590Srgrimes{
5531590Srgrimes	char b[128];
5541590Srgrimes
5551590Srgrimes	move(l, c);
5561590Srgrimes	if (n == 0) {
5571590Srgrimes		while (w-- > 0)
5581590Srgrimes			addch(' ');
5591590Srgrimes		return;
5601590Srgrimes	}
5611590Srgrimes	sprintf(b, "%*d", w, n);
5621590Srgrimes	if (strlen(b) > w) {
5631590Srgrimes		while (w-- > 0)
5641590Srgrimes			addch('*');
5651590Srgrimes		return;
5661590Srgrimes	}
5671590Srgrimes	addstr(b);
5681590Srgrimes}
5691590Srgrimes
5701590Srgrimesstatic void
5711590Srgrimesputfloat(f, l, c, w, d, nz)
5721590Srgrimes	double f;
5731590Srgrimes	int l, c, w, d, nz;
5741590Srgrimes{
5751590Srgrimes	char b[128];
5761590Srgrimes
5771590Srgrimes	move(l, c);
5781590Srgrimes	if (nz && f == 0.0) {
5791590Srgrimes		while (--w >= 0)
5801590Srgrimes			addch(' ');
5811590Srgrimes		return;
5821590Srgrimes	}
5831590Srgrimes	sprintf(b, "%*.*f", w, d, f);
5841590Srgrimes	if (strlen(b) > w) {
5851590Srgrimes		while (--w >= 0)
5861590Srgrimes			addch('*');
5871590Srgrimes		return;
5881590Srgrimes	}
5891590Srgrimes	addstr(b);
5901590Srgrimes}
5911590Srgrimes
5921590Srgrimesstatic void
5931590Srgrimesgetinfo(s, st)
5941590Srgrimes	struct Info *s;
5951590Srgrimes	enum state st;
5961590Srgrimes{
5971590Srgrimes	int mib[2], size;
5981590Srgrimes	extern int errno;
5991590Srgrimes
6001590Srgrimes	NREAD(X_CPTIME, s->time, sizeof s->time);
6011590Srgrimes	NREAD(X_CNT, &s->Cnt, sizeof s->Cnt);
6026988Sdg	NREAD(X_BUFFERSPACE, &s->bufspace, LONG);
6031590Srgrimes	NREAD(X_DK_BUSY, &s->dk_busy, LONG);
6041590Srgrimes	NREAD(X_DK_TIME, s->dk_time, dk_ndrive * LONG);
6051590Srgrimes	NREAD(X_DK_XFER, s->dk_xfer, dk_ndrive * LONG);
6061590Srgrimes	NREAD(X_DK_WDS, s->dk_wds, dk_ndrive * LONG);
6071590Srgrimes	NREAD(X_DK_SEEK, s->dk_seek, dk_ndrive * LONG);
6081590Srgrimes	NREAD(X_NCHSTATS, &s->nchstats, sizeof s->nchstats);
6091590Srgrimes	NREAD(X_INTRCNT, s->intrcnt, nintr * LONG);
6101590Srgrimes	size = sizeof(s->Total);
6111590Srgrimes	mib[0] = CTL_VM;
6121590Srgrimes	mib[1] = VM_METER;
6131590Srgrimes	if (sysctl(mib, 2, &s->Total, &size, NULL, 0) < 0) {
6141590Srgrimes		error("Can't get kernel info: %s\n", strerror(errno));
6151590Srgrimes		bzero(&s->Total, sizeof(s->Total));
6161590Srgrimes	}
6171590Srgrimes}
6181590Srgrimes
6191590Srgrimesstatic void
6201590Srgrimesallocinfo(s)
6211590Srgrimes	struct Info *s;
6221590Srgrimes{
6231590Srgrimes
6241590Srgrimes	s->intrcnt = (long *) malloc(nintr * sizeof(long));
6251590Srgrimes	if (s->intrcnt == NULL) {
6261590Srgrimes		fprintf(stderr, "systat: out of memory\n");
6271590Srgrimes		exit(2);
6281590Srgrimes	}
6291590Srgrimes}
6301590Srgrimes
6311590Srgrimesstatic void
6321590Srgrimescopyinfo(from, to)
6331590Srgrimes	register struct Info *from, *to;
6341590Srgrimes{
6351590Srgrimes	long *time, *wds, *seek, *xfer;
6361590Srgrimes	long *intrcnt;
6371590Srgrimes
6381590Srgrimes	/*
6391590Srgrimes	 * time, wds, seek, and xfer are malloc'd so we have to
6408874Srgrimes	 * save the pointers before the structure copy and then
6411590Srgrimes	 * copy by hand.
6421590Srgrimes	 */
6431590Srgrimes	time = to->dk_time; wds = to->dk_wds; seek = to->dk_seek;
6441590Srgrimes	xfer = to->dk_xfer; intrcnt = to->intrcnt;
6451590Srgrimes	*to = *from;
6461590Srgrimes	bcopy(from->dk_time, to->dk_time = time, dk_ndrive * sizeof (long));
6471590Srgrimes	bcopy(from->dk_wds, to->dk_wds = wds, dk_ndrive * sizeof (long));
6481590Srgrimes	bcopy(from->dk_seek, to->dk_seek = seek, dk_ndrive * sizeof (long));
6491590Srgrimes	bcopy(from->dk_xfer, to->dk_xfer = xfer, dk_ndrive * sizeof (long));
6501590Srgrimes	bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int));
6511590Srgrimes}
6521590Srgrimes
6531590Srgrimesstatic void
6541590Srgrimesdinfo(dn, c)
6551590Srgrimes	int dn, c;
6561590Srgrimes{
6571590Srgrimes	double words, atime, itime, xtime;
6581590Srgrimes
6591590Srgrimes	c = DISKCOL + c * 5;
6601590Srgrimes	atime = s.dk_time[dn];
6611590Srgrimes	atime /= hertz;
6621590Srgrimes	words = s.dk_wds[dn]*32.0;	/* number of words transferred */
6631590Srgrimes	xtime = dk_mspw[dn]*words;	/* transfer time */
6641590Srgrimes	itime = atime - xtime;		/* time not transferring */
6651590Srgrimes	if (xtime < 0)
6661590Srgrimes		itime += xtime, xtime = 0;
6671590Srgrimes	if (itime < 0)
6681590Srgrimes		xtime += itime, itime = 0;
6691590Srgrimes	putint((int)((float)s.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5);
6701590Srgrimes	putint((int)((float)s.dk_xfer[dn]/etime+0.5), DISKROW + 2, c, 5);
6711590Srgrimes	putint((int)(words/etime/512.0 + 0.5), DISKROW + 3, c, 5);
6721590Srgrimes	if (s.dk_seek[dn])
6731590Srgrimes		putfloat(itime*1000.0/s.dk_seek[dn], DISKROW + 4, c, 5, 1, 1);
6741590Srgrimes	else
6751590Srgrimes		putint(0, DISKROW + 4, c, 5);
6761590Srgrimes}
677