Get rid of setgid kmem for systat, and while being there, fix some bugs

and compiler warnings.
The data for network statistics are still obtained via the kvm interface
if systat was started with the needed privileges, otherwise sysctls are
used. The reason for this is that with really many open sockets, the
sysctl method is probably slower, but it systat -netstat is probably not
really usable in either mode under these conditions.

Approved by:	rwatson
This commit is contained in:
tmm 2001-03-23 03:58:25 +00:00
parent 4b0f2fd499
commit 84e46a81a0
10 changed files with 396 additions and 150 deletions

View File

@ -8,7 +8,5 @@ SRCS= cmds.c cmdtab.c devs.c fetch.c iostat.c keyboard.c main.c \
vmstat.c vmstat.c
DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM} ${LIBDEVSTAT} DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM} ${LIBDEVSTAT}
LDADD= -lcurses -lm -lkvm -ldevstat LDADD= -lcurses -lm -lkvm -ldevstat
BINGRP= kmem
BINMODE=2555
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -31,6 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)extern.h 8.1 (Berkeley) 6/6/93 * @(#)extern.h 8.1 (Berkeley) 6/6/93
* $FreeBSD$
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -67,6 +68,8 @@ extern int num_selected;
extern int num_selections; extern int num_selections;
extern long select_generation; extern long select_generation;
extern struct nlist namelist[];
int checkhost __P((struct inpcb *)); int checkhost __P((struct inpcb *));
int checkport __P((struct inpcb *)); int checkport __P((struct inpcb *));
void closeiostat __P((WINDOW *)); void closeiostat __P((WINDOW *));
@ -97,6 +100,7 @@ void fetchnetstat __P((void));
void fetchpigs __P((void)); void fetchpigs __P((void));
void fetchswap __P((void)); void fetchswap __P((void));
void fetchtcp __P((void)); void fetchtcp __P((void));
void getsysctl __P((char *, void *, size_t));
int initicmp __P((void)); int initicmp __P((void));
int initip __P((void)); int initip __P((void));
int initiostat __P((void)); int initiostat __P((void));
@ -145,3 +149,4 @@ void showswap __P((void));
void showtcp __P((void)); void showtcp __P((void));
void status __P((void)); void status __P((void));
void suspend __P((int)); void suspend __P((int));
char *sysctl_dynread __P((char *, size_t *));

View File

@ -29,6 +29,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * 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 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $FreeBSD$
*/ */
#ifndef lint #ifndef lint
@ -36,6 +38,13 @@ static char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */ #endif /* not lint */
#include <sys/types.h> #include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <err.h>
#include <string.h>
#include <stdlib.h>
#include "systat.h" #include "systat.h"
#include "extern.h" #include "extern.h"
@ -46,9 +55,94 @@ kvm_ckread(a, b, l)
{ {
if (kvm_read(kd, (u_long)a, b, l) != l) { if (kvm_read(kd, (u_long)a, b, l) != l) {
if (verbose) if (verbose)
error("error reading kmem at %x\n", a); error("error reading kmem at %x", a);
return (0); return (0);
} }
else else
return (1); return (1);
} }
void getsysctl(name, ptr, len)
char *name;
void *ptr;
size_t len;
{
int err;
size_t nlen = len;
if ((err = sysctlbyname(name, ptr, &nlen, NULL, 0)) != 0) {
error("sysctl(%s...) failed: %s", name,
strerror(errno));
}
if (nlen != len) {
error("sysctl(%s...) expected %d, got %d", name,
len, nlen);
}
}
/*
* Read sysctl data with variable size. Try some times (with increasing
* buffers), fail if still too small.
* This is needed sysctls with possibly raplidly increasing data sizes,
* but imposes little overhead in the case of constant sizes.
* Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds
* the requested data.
* If szp is not NULL, the size of the returned data will be written into *szp.
*/
/* Some defines: Number of tries. */
#define SD_NTRIES 10
/* Percent of over-allocation (initial) */
#define SD_MARGIN 10
/*
* Factor for over-allocation in percent (the margin is increased by this on
* any failed try).
*/
#define SD_FACTOR 50
/* Maximum supported MIB depth */
#define SD_MAXMIB 16
char *
sysctl_dynread(n, szp)
char *n;
size_t *szp;
{
char *rv = NULL;
int mib[SD_MAXMIB];
size_t mibsz = SD_MAXMIB;
size_t mrg = SD_MARGIN;
size_t sz;
int i;
/* cache the MIB */
if (sysctlnametomib(n, mib, &mibsz) == -1) {
if (errno == ENOMEM) {
error("XXX: SD_MAXMIB too small, please bump!");
}
return NULL;
}
for (i = 0; i < SD_NTRIES; i++) {
/* get needed buffer size */
if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1)
break;
sz += sz * mrg / 100;
if ((rv = (char *)malloc(sz)) == NULL) {
error("Out of memory!");
return NULL;
}
if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) {
free(rv);
rv = NULL;
if (errno == ENOMEM) {
mrg += mrg * SD_FACTOR / 100;
} else
break;
} else {
/* success */
if (szp != NULL)
*szp = sz;
break;
}
}
return rv;
}

View File

@ -66,6 +66,7 @@ static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
#include <sys/param.h> #include <sys/param.h>
#include <sys/dkstat.h> #include <sys/dkstat.h>
#include <sys/sysctl.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -110,7 +111,7 @@ closeiostat(w)
int int
initiostat() initiostat()
{ {
if (num_devices = getnumdevs() < 0) if ((num_devices = getnumdevs()) < 0)
return(0); return(0);
cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));

View File

@ -47,6 +47,7 @@ static const char rcsid[] =
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/sysctl.h>
#include <err.h> #include <err.h>
#include <locale.h> #include <locale.h>
@ -74,6 +75,7 @@ char *namp;
char hostname[MAXHOSTNAMELEN]; char hostname[MAXHOSTNAMELEN];
WINDOW *wnd; WINDOW *wnd;
int CMDLINE; int CMDLINE;
int use_kvm = 1;
static WINDOW *wload; /* one line window for load average */ static WINDOW *wload; /* one line window for load average */
@ -82,7 +84,7 @@ main(argc, argv)
int argc; int argc;
char **argv; char **argv;
{ {
char errbuf[80]; char errbuf[80], dummy;
size_t size; size_t size;
int err; int err;
@ -107,9 +109,29 @@ main(argc, argv)
argc--, argv++; argc--, argv++;
} }
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if (kd != NULL) {
/*
* Try to actually read something, we may be in a jail, and
* have /dev/null opened as /dev/mem.
*/
if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 ||
kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) !=
sizeof(dummy)) {
kvm_close(kd);
kd = NULL;
}
}
if (kd == NULL) { if (kd == NULL) {
error("%s", errbuf); /*
exit(1); * Maybe we are lacking permissions? Retry, this time with bogus
* devices. We can now use sysctl only.
*/
use_kvm = 0;
kd = kvm_openfiles("/dev/null", "/dev/null", "/dev/null", O_RDONLY, errbuf);
if (kd == NULL) {
error("%s", errbuf);
exit(1);
}
} }
signal(SIGINT, die); signal(SIGINT, die);
signal(SIGQUIT, die); signal(SIGQUIT, die);

View File

@ -253,7 +253,7 @@ showports()
for (p = ports; p < ports+nports; p++) { for (p = ports; p < ports+nports; p++) {
sp = getservbyport(p->port, sp = getservbyport(p->port,
protos == TCP|UDP ? 0 : protos == TCP ? "tcp" : "udp"); protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
if (!p->onoff) if (!p->onoff)
addch('!'); addch('!');
if (sp) if (sp)

View File

@ -60,6 +60,7 @@ static const char rcsid[] =
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netinet/tcpip.h> #include <netinet/tcpip.h>
#include <netinet/tcp_seq.h> #include <netinet/tcp_seq.h>
#include <netinet/tcp_var.h>
#define TCPSTATES #define TCPSTATES
#include <netinet/tcp_fsm.h> #include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h> #include <netinet/tcp_timer.h>
@ -76,7 +77,11 @@ static const char rcsid[] =
#include "systat.h" #include "systat.h"
#include "extern.h" #include "extern.h"
static void enter __P((struct inpcb *, struct socket *, int, char *)); static struct netinfo *enter __P((struct inpcb *, int, char *));
static void enter_kvm __P((struct inpcb *, struct socket *, int, char *));
static void enter_sysctl __P((struct inpcb *, struct xsocket *, int, char *));
static void fetchnetstat_kvm __P((void));
static void fetchnetstat_sysctl __P((void));
static char *inetname __P((struct in_addr)); static char *inetname __P((struct in_addr));
static void inetprint __P((struct in_addr *, int, char *)); static void inetprint __P((struct in_addr *, int, char *));
@ -113,7 +118,6 @@ TAILQ_HEAD(netinfohead, netinfo) netcb = TAILQ_HEAD_INITIALIZER(netcb);
static int aflag = 0; static int aflag = 0;
static int nflag = 0; static int nflag = 0;
static int lastrow = 1; static int lastrow = 1;
static void enter(), inetprint();
static char *inetname(); static char *inetname();
void void
@ -136,31 +140,37 @@ closenetstat(w)
} }
} }
static struct nlist namelist[] = { static char *miblist[] = {
"net.inet.tcp.pcblist",
"net.inet.udp.pcblist"
};
struct nlist namelist[] = {
#define X_TCB 0 #define X_TCB 0
{ "_tcb" }, { "tcb" },
#define X_UDB 1 #define X_UDB 1
{ "_udb" }, { "udb" },
{ "" }, { "" },
}; };
int int
initnetstat() initnetstat()
{ {
if (kvm_nlist(kd, namelist)) {
nlisterr(namelist);
return(0);
}
if (namelist[X_TCB].n_value == 0) {
error("No symbols in namelist");
return(0);
}
protos = TCP|UDP; protos = TCP|UDP;
return(1); return(1);
} }
void void
fetchnetstat() fetchnetstat()
{
if (use_kvm)
fetchnetstat_kvm();
else
fetchnetstat_sysctl();
}
static void
fetchnetstat_kvm()
{ {
register struct inpcb *next; register struct inpcb *next;
register struct netinfo *p; register struct netinfo *p;
@ -201,9 +211,9 @@ fetchnetstat()
KREAD(inpcb.inp_socket, &sockb, sizeof (sockb)); KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
if (istcp) { if (istcp) {
KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb)); KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
enter(&inpcb, &sockb, tcpcb.t_state, "tcp"); enter_kvm(&inpcb, &sockb, tcpcb.t_state, "tcp");
} else } else
enter(&inpcb, &sockb, 0, "udp"); enter_kvm(&inpcb, &sockb, 0, "udp");
} }
if (istcp && (protos&UDP)) { if (istcp && (protos&UDP)) {
istcp = 0; istcp = 0;
@ -213,7 +223,84 @@ fetchnetstat()
} }
static void static void
enter(inp, so, state, proto) fetchnetstat_sysctl()
{
register struct netinfo *p;
int idx;
struct xinpgen *inpg;
char *cur, *end;
struct inpcb *inpcb;
struct xinpcb *xip;
struct xtcpcb *xtp;
int plen;
size_t lsz;
TAILQ_FOREACH(p, &netcb, chain)
p->ni_seen = 0;
if (protos&TCP) {
idx = 0;
} else if (protos&UDP) {
idx = 1;
} else {
error("No protocols to display");
return;
}
for (;idx < 2; idx++) {
if (idx == 1 && !(protos&UDP))
break;
inpg = (struct xinpgen *)sysctl_dynread(miblist[idx], &lsz);
if (inpg == NULL) {
error("sysctl(%s...) failed", miblist[idx]);
continue;
}
/*
* We currently do no require a consistent pcb list.
* Try to be robust in case of struct size changes
*/
cur = ((char *)inpg) + inpg->xig_len;
/* There is also a trailing struct xinpgen */
end = ((char *)inpg) + lsz - inpg->xig_len;
if (end <= cur) {
free(inpg);
continue;
}
if (idx == 0) { /* TCP */
xtp = (struct xtcpcb *)cur;
plen = xtp->xt_len;
} else {
xip = (struct xinpcb *)cur;
plen = xip->xi_len;
}
while (cur + plen <= end) {
if (idx == 0) { /* TCP */
xtp = (struct xtcpcb *)cur;
inpcb = &xtp->xt_inp;
} else {
xip = (struct xinpcb *)cur;
inpcb = &xip->xi_inp;
}
cur += plen;
if (!aflag && inet_lnaof(inpcb->inp_laddr) ==
INADDR_ANY)
continue;
if (nhosts && !checkhost(inpcb))
continue;
if (nports && !checkport(inpcb))
continue;
if (idx == 0) /* TCP */
enter_sysctl(inpcb, &xtp->xt_socket,
xtp->xt_tp.t_state, "tcp");
else /* UDP */
enter_sysctl(inpcb, &xip->xi_socket, 0, "udp");
}
free(inpg);
}
}
static void
enter_kvm(inp, so, state, proto)
register struct inpcb *inp; register struct inpcb *inp;
register struct socket *so; register struct socket *so;
int state; int state;
@ -221,6 +308,36 @@ enter(inp, so, state, proto)
{ {
register struct netinfo *p; register struct netinfo *p;
if ((p = enter(inp, state, proto)) != NULL) {
p->ni_rcvcc = so->so_rcv.sb_cc;
p->ni_sndcc = so->so_snd.sb_cc;
}
}
static void
enter_sysctl(inp, so, state, proto)
register struct inpcb *inp;
register struct xsocket *so;
int state;
char *proto;
{
register struct netinfo *p;
if ((p = enter(inp, state, proto)) != NULL) {
p->ni_rcvcc = so->so_rcv.sb_cc;
p->ni_sndcc = so->so_snd.sb_cc;
}
}
static struct netinfo *
enter(inp, state, proto)
register struct inpcb *inp;
int state;
char *proto;
{
register struct netinfo *p;
/* /*
* Only take exact matches, any sockets with * Only take exact matches, any sockets with
* previously unbound addresses will be deleted * previously unbound addresses will be deleted
@ -241,7 +358,7 @@ enter(inp, so, state, proto)
if (p == NULL) { if (p == NULL) {
if ((p = malloc(sizeof(*p))) == NULL) { if ((p = malloc(sizeof(*p))) == NULL) {
error("Out of memory"); error("Out of memory");
return; return NULL;
} }
TAILQ_INSERT_HEAD(&netcb, p, chain); TAILQ_INSERT_HEAD(&netcb, p, chain);
p->ni_line = -1; p->ni_line = -1;
@ -252,10 +369,9 @@ enter(inp, so, state, proto)
p->ni_proto = proto; p->ni_proto = proto;
p->ni_flags = NIF_LACHG|NIF_FACHG; p->ni_flags = NIF_LACHG|NIF_FACHG;
} }
p->ni_rcvcc = so->so_rcv.sb_cc;
p->ni_sndcc = so->so_snd.sb_cc;
p->ni_state = state; p->ni_state = state;
p->ni_seen = 1; p->ni_seen = 1;
return p;
} }
/* column locations */ /* column locations */
@ -270,7 +386,7 @@ enter(inp, so, state, proto)
void void
labelnetstat() labelnetstat()
{ {
if (namelist[X_TCB].n_type == 0) if (use_kvm && namelist[X_TCB].n_type == 0)
return; return;
wmove(wnd, 0, 0); wclrtobot(wnd); wmove(wnd, 0, 0); wclrtobot(wnd);
mvwaddstr(wnd, 0, LADDR, "Local Address"); mvwaddstr(wnd, 0, LADDR, "Local Address");
@ -291,9 +407,12 @@ shownetstat()
* away and adjust the position of connections * away and adjust the position of connections
* below to reflect the deleted line. * below to reflect the deleted line.
*/ */
TAILQ_FOREACH(p, &netcb, chain) { p = TAILQ_FIRST(&netcb);
if (p->ni_line == -1 || p->ni_seen) while (p != NULL) {
if (p->ni_line == -1 || p->ni_seen) {
p = TAILQ_NEXT(p, chain);
continue; continue;
}
wmove(wnd, p->ni_line, 0); wdeleteln(wnd); wmove(wnd, p->ni_line, 0); wdeleteln(wnd);
TAILQ_FOREACH(q, &netcb, chain) TAILQ_FOREACH(q, &netcb, chain)
if (q != p && q->ni_line > p->ni_line) { if (q != p && q->ni_line > p->ni_line) {
@ -302,7 +421,7 @@ shownetstat()
q->ni_flags |= NIF_LACHG|NIF_FACHG; q->ni_flags |= NIF_LACHG|NIF_FACHG;
} }
lastrow--; lastrow--;
q = TAILQ_PREV(p, netinfohead, chain); q = TAILQ_NEXT(p, chain);
TAILQ_REMOVE(&netcb, p, chain); TAILQ_REMOVE(&netcb, p, chain);
free(p); free(p);
p = q; p = q;

View File

@ -92,11 +92,8 @@ closeswap(w)
int int
initswap() initswap()
{ {
int i;
char msgbuf[BUFSIZ]; char msgbuf[BUFSIZ];
char *cp;
static int once = 0; static int once = 0;
u_long ptr;
struct kvm_swap dummy; struct kvm_swap dummy;
if (once) if (once)
@ -124,7 +121,7 @@ fetchswap()
void void
labelswap() labelswap()
{ {
char *header, *p; char *header;
int row, i; int row, i;
fetchswap(); fetchswap();

View File

@ -49,12 +49,20 @@ struct cmdtab {
char c_flags; /* see below */ char c_flags; /* see below */
}; };
/*
* If we are started with privileges, use a kmem interface for netstat handling,
* otherwise use sysctl.
* In case of many open sockets, the sysctl handling might become slow.
*/
extern int use_kvm;
#define CF_INIT 0x1 /* been initialized */ #define CF_INIT 0x1 /* been initialized */
#define CF_LOADAV 0x2 /* display w/ load average */ #define CF_LOADAV 0x2 /* display w/ load average */
#define TCP 0x1 #define TCP 0x1
#define UDP 0x2 #define UDP 0x2
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
#define KREAD(addr, buf, len) kvm_ckread((addr), (buf), (len)) #define KREAD(addr, buf, len) kvm_ckread((addr), (buf), (len))
#define NVAL(indx) namelist[(indx)].n_value #define NVAL(indx) namelist[(indx)].n_value
#define NPTR(indx) (void *)NVAL((indx)) #define NPTR(indx) (void *)NVAL((indx))

View File

@ -74,7 +74,43 @@ static const char rcsid[] =
static struct Info { static struct Info {
long time[CPUSTATES]; long time[CPUSTATES];
struct vmmeter Cnt; u_int v_swtch; /* context switches */
u_int v_trap; /* calls to trap */
u_int v_syscall; /* calls to syscall() */
u_int v_intr; /* device interrupts */
u_int v_soft; /* software interrupts */
/*
* Virtual memory activity.
*/
u_int v_vm_faults; /* number of address memory faults */
u_int v_cow_faults; /* number of copy-on-writes */
u_int v_zfod; /* pages zero filled on demand */
u_int v_ozfod; /* optimized zero fill pages */
u_int v_swapin; /* swap pager pageins */
u_int v_swapout; /* swap pager pageouts */
u_int v_swappgsin; /* swap pager pages paged in */
u_int v_swappgsout; /* swap pager pages paged out */
u_int v_vnodein; /* vnode pager pageins */
u_int v_vnodeout; /* vnode pager pageouts */
u_int v_vnodepgsin; /* vnode_pager pages paged in */
u_int v_vnodepgsout; /* vnode pager pages paged out */
u_int v_intrans; /* intransit blocking page faults */
u_int v_reactivated; /* number of pages reactivated from free list */
u_int v_pdwakeups; /* number of times daemon has awaken from sleep */
u_int v_pdpages; /* number of pages analyzed by daemon */
u_int v_dfree; /* pages freed by daemon */
u_int v_pfree; /* pages freed by exiting processes */
u_int v_tfree; /* total pages freed */
/*
* Distribution of page usages.
*/
u_int v_page_size; /* page size in bytes */
u_int v_free_count; /* number of pages free */
u_int v_wire_count; /* number of pages wired down */
u_int v_active_count; /* number of pages active */
u_int v_inactive_count; /* number of pages inactive */
u_int v_cache_count; /* number of pages on buffer cache queue */
struct vmtotal Total; struct vmtotal Total;
struct nchstats nchstats; struct nchstats nchstats;
long nchcount; long nchcount;
@ -88,8 +124,6 @@ static struct Info {
struct statinfo cur, last, run; struct statinfo cur, last, run;
#define cnt s.Cnt
#define oldcnt s1.Cnt
#define total s.Total #define total s.Total
#define nchtotal s.nchstats #define nchtotal s.nchstats
#define oldnchtotal s1.nchstats #define oldnchtotal s1.nchstats
@ -142,21 +176,6 @@ closekre(w)
wrefresh(w); wrefresh(w);
} }
static struct nlist namelist[] = {
#define X_CNT 0
{ "_cnt" },
#define X_INTRNAMES 1
{ "_intrnames" },
#define X_EINTRNAMES 2
{ "_eintrnames" },
#define X_INTRCNT 3
{ "_intrcnt" },
#define X_EINTRCNT 4
{ "_eintrcnt" },
{ "" },
};
/* /*
* These constants define where the major pieces are laid out * These constants define where the major pieces are laid out
*/ */
@ -191,18 +210,7 @@ initkre()
char *intrnamebuf, *cp; char *intrnamebuf, *cp;
int i; int i;
if (namelist[0].n_type == 0) { if ((num_devices = getnumdevs()) < 0) {
if (kvm_nlist(kd, namelist)) {
nlisterr(namelist);
return(0);
}
if (namelist[0].n_type == 0) {
error("No namelist");
return(0);
}
}
if (num_devices = getnumdevs() < 0) {
warnx("%s", devstat_errbuf); warnx("%s", devstat_errbuf);
return(0); return(0);
} }
@ -218,14 +226,13 @@ initkre()
return(0); return(0);
if (nintr == 0) { if (nintr == 0) {
nintr = (namelist[X_EINTRCNT].n_value - GETSYSCTL("hw.nintr", nintr);
namelist[X_INTRCNT].n_value) / sizeof (long);
intrloc = calloc(nintr, sizeof (long)); intrloc = calloc(nintr, sizeof (long));
intrname = calloc(nintr, sizeof (long)); intrname = calloc(nintr, sizeof (long));
intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value - intrnamebuf = sysctl_dynread("hw.intrnames", NULL);
namelist[X_INTRNAMES].n_value); if (intrnamebuf == NULL || intrname == NULL ||
if (intrnamebuf == 0 || intrname == 0 || intrloc == 0) { intrloc == NULL) {
error("Out of memory\n"); error("Out of memory");
if (intrnamebuf) if (intrnamebuf)
free(intrnamebuf); free(intrnamebuf);
if (intrname) if (intrname)
@ -235,8 +242,6 @@ initkre()
nintr = 0; nintr = 0;
return(0); return(0);
} }
NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
NVAL(X_INTRNAMES));
for (cp = intrnamebuf, i = 0; i < nintr; i++) { for (cp = intrnamebuf, i = 0; i < nintr; i++) {
intrname[i] = cp; intrname[i] = cp;
cp += strlen(cp) + 1; cp += strlen(cp) + 1;
@ -453,7 +458,7 @@ showkre()
putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0); putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0);
putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0); putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0);
mvaddstr(STATROW, STATCOL + 53, buf); mvaddstr(STATROW, STATCOL + 53, buf);
#define pgtokb(pg) ((pg) * cnt.v_page_size / 1024) #define pgtokb(pg) ((pg) * s.v_page_size / 1024)
putint(pgtokb(total.t_arm), MEMROW + 2, MEMCOL + 3, 8); putint(pgtokb(total.t_arm), MEMROW + 2, MEMCOL + 3, 8);
putint(pgtokb(total.t_armshr), MEMROW + 2, MEMCOL + 11, 8); putint(pgtokb(total.t_armshr), MEMROW + 2, MEMCOL + 11, 8);
putint(pgtokb(total.t_avm), MEMROW + 2, MEMCOL + 19, 9); putint(pgtokb(total.t_avm), MEMROW + 2, MEMCOL + 19, 9);
@ -469,34 +474,34 @@ showkre()
putint(total.t_sl, PROCSROW + 1, PROCSCOL + 12, 3); putint(total.t_sl, PROCSROW + 1, PROCSCOL + 12, 3);
putint(total.t_sw, PROCSROW + 1, PROCSCOL + 15, 3); putint(total.t_sw, PROCSROW + 1, PROCSCOL + 15, 3);
if (extended_vm_stats == 0) { if (extended_vm_stats == 0) {
PUTRATE(Cnt.v_zfod, VMSTATROW + 0, VMSTATCOL + 4, 5); PUTRATE(v_zfod, VMSTATROW + 0, VMSTATCOL + 4, 5);
} }
PUTRATE(Cnt.v_cow_faults, VMSTATROW + 1, VMSTATCOL + 3, 6); PUTRATE(v_cow_faults, VMSTATROW + 1, VMSTATCOL + 3, 6);
putint(pgtokb(cnt.v_wire_count), VMSTATROW + 2, VMSTATCOL, 9); putint(pgtokb(s.v_wire_count), VMSTATROW + 2, VMSTATCOL, 9);
putint(pgtokb(cnt.v_active_count), VMSTATROW + 3, VMSTATCOL, 9); putint(pgtokb(s.v_active_count), VMSTATROW + 3, VMSTATCOL, 9);
putint(pgtokb(cnt.v_inactive_count), VMSTATROW + 4, VMSTATCOL, 9); putint(pgtokb(s.v_inactive_count), VMSTATROW + 4, VMSTATCOL, 9);
putint(pgtokb(cnt.v_cache_count), VMSTATROW + 5, VMSTATCOL, 9); putint(pgtokb(s.v_cache_count), VMSTATROW + 5, VMSTATCOL, 9);
putint(pgtokb(cnt.v_free_count), VMSTATROW + 6, VMSTATCOL, 9); putint(pgtokb(s.v_free_count), VMSTATROW + 6, VMSTATCOL, 9);
PUTRATE(Cnt.v_dfree, VMSTATROW + 7, VMSTATCOL, 9); PUTRATE(v_dfree, VMSTATROW + 7, VMSTATCOL, 9);
PUTRATE(Cnt.v_pfree, VMSTATROW + 8, VMSTATCOL, 9); PUTRATE(v_pfree, VMSTATROW + 8, VMSTATCOL, 9);
PUTRATE(Cnt.v_reactivated, VMSTATROW + 9, VMSTATCOL, 9); PUTRATE(v_reactivated, VMSTATROW + 9, VMSTATCOL, 9);
PUTRATE(Cnt.v_pdwakeups, VMSTATROW + 10, VMSTATCOL, 9); PUTRATE(v_pdwakeups, VMSTATROW + 10, VMSTATCOL, 9);
PUTRATE(Cnt.v_pdpages, VMSTATROW + 11, VMSTATCOL, 9); PUTRATE(v_pdpages, VMSTATROW + 11, VMSTATCOL, 9);
PUTRATE(Cnt.v_intrans, VMSTATROW + 12, VMSTATCOL, 9); PUTRATE(v_intrans, VMSTATROW + 12, VMSTATCOL, 9);
if (extended_vm_stats) { if (extended_vm_stats) {
PUTRATE(Cnt.v_zfod, VMSTATROW + 11, VMSTATCOL - 16, 9); PUTRATE(v_zfod, VMSTATROW + 11, VMSTATCOL - 16, 9);
PUTRATE(Cnt.v_ozfod, VMSTATROW + 12, VMSTATCOL - 16, 9); PUTRATE(v_ozfod, VMSTATROW + 12, VMSTATCOL - 16, 9);
putint( putint(
((s.Cnt.v_ozfod < s.Cnt.v_zfod) ? ((s.v_ozfod < s.v_zfod) ?
s.Cnt.v_ozfod * 100 / s.Cnt.v_zfod : s.v_ozfod * 100 / s.v_zfod :
0 0
), ),
VMSTATROW + 13, VMSTATROW + 13,
VMSTATCOL - 16, VMSTATCOL - 16,
9 9
); );
PUTRATE(Cnt.v_tfree, VMSTATROW + 14, VMSTATCOL - 16, 9); PUTRATE(v_tfree, VMSTATROW + 14, VMSTATCOL - 16, 9);
} }
putint(s.bufspace/1024, VMSTATROW + 13, VMSTATCOL, 9); putint(s.bufspace/1024, VMSTATROW + 13, VMSTATCOL, 9);
@ -504,20 +509,20 @@ showkre()
putint(s.desiredvnodes, VMSTATROW + 15, VMSTATCOL, 9); putint(s.desiredvnodes, VMSTATROW + 15, VMSTATCOL, 9);
putint(s.numvnodes, VMSTATROW + 16, VMSTATCOL, 9); putint(s.numvnodes, VMSTATROW + 16, VMSTATCOL, 9);
putint(s.freevnodes, VMSTATROW + 17, VMSTATCOL, 9); putint(s.freevnodes, VMSTATROW + 17, VMSTATCOL, 9);
PUTRATE(Cnt.v_vnodein, PAGEROW + 2, PAGECOL + 5, 5); PUTRATE(v_vnodein, PAGEROW + 2, PAGECOL + 5, 5);
PUTRATE(Cnt.v_vnodeout, PAGEROW + 2, PAGECOL + 10, 5); PUTRATE(v_vnodeout, PAGEROW + 2, PAGECOL + 10, 5);
PUTRATE(Cnt.v_swapin, PAGEROW + 2, PAGECOL + 17, 5); PUTRATE(v_swapin, PAGEROW + 2, PAGECOL + 17, 5);
PUTRATE(Cnt.v_swapout, PAGEROW + 2, PAGECOL + 22, 5); PUTRATE(v_swapout, PAGEROW + 2, PAGECOL + 22, 5);
PUTRATE(Cnt.v_vnodepgsin, PAGEROW + 3, PAGECOL + 5, 5); PUTRATE(v_vnodepgsin, PAGEROW + 3, PAGECOL + 5, 5);
PUTRATE(Cnt.v_vnodepgsout, PAGEROW + 3, PAGECOL + 10, 5); PUTRATE(v_vnodepgsout, PAGEROW + 3, PAGECOL + 10, 5);
PUTRATE(Cnt.v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5); PUTRATE(v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5);
PUTRATE(Cnt.v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5); PUTRATE(v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5);
PUTRATE(Cnt.v_swtch, GENSTATROW + 1, GENSTATCOL, 5); PUTRATE(v_swtch, GENSTATROW + 1, GENSTATCOL, 5);
PUTRATE(Cnt.v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5); PUTRATE(v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5);
PUTRATE(Cnt.v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5); PUTRATE(v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5);
PUTRATE(Cnt.v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5); PUTRATE(v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5);
PUTRATE(Cnt.v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5); PUTRATE(v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5);
PUTRATE(Cnt.v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5); PUTRATE(v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5);
mvprintw(DISKROW, DISKCOL + 5, " "); mvprintw(DISKROW, DISKCOL + 5, " ");
for (i = 0, c = 0; i < num_devices && c < MAXDRIVES; i++) for (i = 0, c = 0; i < num_devices && c < MAXDRIVES; i++)
if (dev_select[i].selected) { if (dev_select[i].selected) {
@ -721,51 +726,48 @@ getinfo(s, st)
enum state st; enum state st;
{ {
struct devinfo *tmp_dinfo; struct devinfo *tmp_dinfo;
size_t len, size; size_t size;
int mib[2], err; int mib[2];
len = sizeof(s->time); GETSYSCTL("kern.cp_time", s->time);
err = sysctlbyname("kern.cp_time", &s->time, &len, NULL, 0); GETSYSCTL("kern.cp_time", cur.cp_time);
if (err || len != sizeof(s->time)) GETSYSCTL("vm.stats.sys.v_swtch", s->v_swtch);
perror("kern.cp_time"); GETSYSCTL("vm.stats.sys.v_trap", s->v_trap);
GETSYSCTL("vm.stats.sys.v_syscall", s->v_syscall);
len = sizeof(cur.cp_time); GETSYSCTL("vm.stats.sys.v_intr", s->v_intr);
err = sysctlbyname("kern.cp_time", &cur.cp_time, &len, NULL, 0); GETSYSCTL("vm.stats.sys.v_soft", s->v_soft);
if (err || len != sizeof(cur.cp_time)) GETSYSCTL("vm.stats.vm.v_vm_faults", s->v_vm_faults);
perror("kern.cp_time"); GETSYSCTL("vm.stats.vm.v_cow_faults", s->v_cow_faults);
GETSYSCTL("vm.stats.vm.v_zfod", s->v_zfod);
NREAD(X_CNT, &s->Cnt, sizeof s->Cnt); GETSYSCTL("vm.stats.vm.v_ozfod", s->v_ozfod);
GETSYSCTL("vm.stats.vm.v_swapin", s->v_swapin);
len = sizeof(s->bufspace); GETSYSCTL("vm.stats.vm.v_swapout", s->v_swapout);
err = sysctlbyname("vfs.bufspace", &s->bufspace, &len, NULL, 0); GETSYSCTL("vm.stats.vm.v_swappgsin", s->v_swappgsin);
if (err || len != sizeof(s->bufspace)) GETSYSCTL("vm.stats.vm.v_swappgsout", s->v_swappgsout);
perror("vfs.bufspace"); GETSYSCTL("vm.stats.vm.v_vnodein", s->v_vnodein);
GETSYSCTL("vm.stats.vm.v_vnodeout", s->v_vnodeout);
len = sizeof(s->desiredvnodes); GETSYSCTL("vm.stats.vm.v_vnodepgsin", s->v_vnodepgsin);
err = sysctlbyname("kern.maxvnodes", &s->desiredvnodes, &len, NULL, 0); GETSYSCTL("vm.stats.vm.v_vnodepgsout", s->v_vnodepgsout);
if (err || len != sizeof(s->desiredvnodes)) GETSYSCTL("vm.stats.vm.v_intrans", s->v_intrans);
perror("kern.maxvnodes"); GETSYSCTL("vm.stats.vm.v_reactivated", s->v_reactivated);
GETSYSCTL("vm.stats.vm.v_pdwakeups", s->v_pdwakeups);
len = sizeof(s->numvnodes); GETSYSCTL("vm.stats.vm.v_pdpages", s->v_pdpages);
err = sysctlbyname("debug.numvnodes", &s->numvnodes, &len, NULL, 0); GETSYSCTL("vm.stats.vm.v_dfree", s->v_dfree);
if (err || len != sizeof(s->numvnodes)) GETSYSCTL("vm.stats.vm.v_pfree", s->v_pfree);
perror("debug.numvnodes"); GETSYSCTL("vm.stats.vm.v_tfree", s->v_tfree);
GETSYSCTL("vm.stats.vm.v_page_size", s->v_page_size);
len = sizeof(s->freevnodes); GETSYSCTL("vm.stats.vm.v_free_count", s->v_free_count);
err = sysctlbyname("debug.freevnodes", &s->freevnodes, &len, NULL, 0); GETSYSCTL("vm.stats.vm.v_wire_count", s->v_wire_count);
if (err || len != sizeof(s->freevnodes)) GETSYSCTL("vm.stats.vm.v_active_count", s->v_active_count);
perror("debug.freevnodes"); GETSYSCTL("vm.stats.vm.v_inactive_count", s->v_inactive_count);
GETSYSCTL("vm.stats.vm.v_cache_count", s->v_cache_count);
len = sizeof(s->nchstats); GETSYSCTL("vfs.bufspace", s->bufspace);
err = sysctlbyname("vfs.cache.nchstats", &s->nchstats, &len, NULL, 0); GETSYSCTL("kern.maxvnodes", s->desiredvnodes);
if (err || len != sizeof(s->nchstats)) GETSYSCTL("debug.numvnodes", s->numvnodes);
perror("vfs.cache.nchstats"); GETSYSCTL("debug.freevnodes", s->freevnodes);
GETSYSCTL("vfs.cache.nchstats", s->nchstats);
NREAD(X_INTRCNT, s->intrcnt, nintr * LONG); GETSYSCTL("vfs.numdirtybuffers", s->numdirtybuffers);
getsysctl("hw.intrcnt", s->intrcnt, nintr * LONG);
len = sizeof(s->numdirtybuffers);
err = sysctlbyname("vfs.numdirtybuffers", &s->numdirtybuffers, &len,
NULL, 0);
size = sizeof(s->Total); size = sizeof(s->Total);
mib[0] = CTL_VM; mib[0] = CTL_VM;