summaryrefslogtreecommitdiffstats
path: root/usr.bin/top
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2001-02-23 18:52:37 +0000
committerrwatson <rwatson@FreeBSD.org>2001-02-23 18:52:37 +0000
commit6b94a67d0bad867b8dd713776eaf9147e3df4913 (patch)
treebdc8166c8faa126445849411e5bc95ed71b40f5b /usr.bin/top
parent78bbdcc2c47d0c8cca39617c5fb960c9d456ddfc (diff)
downloadFreeBSD-src-6b94a67d0bad867b8dd713776eaf9147e3df4913.zip
FreeBSD-src-6b94a67d0bad867b8dd713776eaf9147e3df4913.tar.gz
Adapt the top utility to not use kmem_read to retrieve variables now
available via sysctl(). As a result, top should now be able to run without setgid kmem. Submitted by: Thomas Moestl <tmoestl@gmx.net> Reviewed by: freebsd-audit
Diffstat (limited to 'usr.bin/top')
-rw-r--r--usr.bin/top/machine.c211
1 files changed, 44 insertions, 167 deletions
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index ff5e0a8..acd2d53 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -18,6 +18,7 @@
* AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
* Steven Wallace <swallace@freebsd.org>
* Wolfram Schneider <wosch@FreeBSD.org>
+ * Thomas Moestl <tmoestl@gmx.net>
*
* $FreeBSD$
*/
@@ -49,20 +50,26 @@
#include <stdlib.h>
#include <sys/conf.h>
+#include <unistd.h>
#include <osreldate.h> /* for changes in kernel structures */
#include "top.h"
#include "machine.h"
#include "screen.h"
+#include "utils.h"
+
+static void getsysctl __P((char *, void *, int));
+
+#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
-static int check_nlist __P((struct nlist *));
-static int getkval __P((unsigned long, int *, int, char *));
extern char* printable __P((char *));
int swapmode __P((int *retavail, int *retfree));
static int smpmode;
static int namelength;
static int cmdlengthdelta;
+/* Prototypes for top internals */
+void quit __P((int));
/* get_process_info passes back a handle. This is what it looks like: */
@@ -84,25 +91,6 @@ struct handle
/* definitions for indices in the nlist array */
-static struct nlist nlst[] = {
-#define X_CCPU 0
- { "_ccpu" },
-#define X_CP_TIME 1
- { "_cp_time" },
-#define X_AVENRUN 2
- { "_averunnable" },
-
-#define X_BUFSPACE 3
- { "_bufspace" }, /* K in buffer cache */
-#define X_CNT 4
- { "_cnt" }, /* struct vmmeter cnt */
-
-/* Last pid */
-#define X_LASTPID 5
- { "_nextpid" },
- { 0 }
-};
-
/*
* These definitions control the format of the per-process area
*/
@@ -141,15 +129,9 @@ static double logcpu;
static load_avg ccpu;
-/* these are offsets obtained via nlist and used in the get_ functions */
+/* these are used in the get_ functions */
-static unsigned long cp_time_offset;
-static unsigned long avenrun_offset;
-static unsigned long lastpid_offset;
-static long lastpid;
-static unsigned long cnt_offset;
-static unsigned long bufspace_offset;
-static long cnt;
+static int lastpid;
/* these are for calculating cpu state percentages */
@@ -221,7 +203,6 @@ machine_init(statics)
struct statics *statics;
{
- register int i = 0;
register int pagesize;
int modelen;
struct passwd *pw;
@@ -241,33 +222,10 @@ struct statics *statics;
if (namelength > 15)
namelength = 15;
- if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
+ if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open")) == NULL)
return -1;
-
- /* get the list of symbols we want to access in the kernel */
- (void) kvm_nlist(kd, nlst);
- if (nlst[0].n_type == 0)
- {
- fprintf(stderr, "top: nlist failed\n");
- return(-1);
- }
-
- /* make sure they were all found */
- if (i > 0 && check_nlist(nlst) > 0)
- {
- return(-1);
- }
-
- (void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
- nlst[X_CCPU].n_name);
-
- /* stash away certain offsets for later use */
- cp_time_offset = nlst[X_CP_TIME].n_value;
- avenrun_offset = nlst[X_AVENRUN].n_value;
- lastpid_offset = nlst[X_LASTPID].n_value;
- cnt_offset = nlst[X_CNT].n_value;
- bufspace_offset = nlst[X_BUFSPACE].n_value;
+ GETSYSCTL("kern.ccpu", ccpu);
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(loaddouble(ccpu));
@@ -306,7 +264,6 @@ char *format_header(uname_field)
register char *uname_field;
{
- register char *ptr;
static char Header[128];
snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
@@ -328,19 +285,15 @@ struct system_info *si;
{
long total;
- load_avg avenrun[3];
+ load_avg avenrun[4]; /* 3 values and FSCALE. */
int mib[2];
struct timeval boottime;
size_t bt_size;
/* get the cp_time array */
- (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
- nlst[X_CP_TIME].n_name);
- (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
- nlst[X_AVENRUN].n_name);
-
- (void) getkval(lastpid_offset, (int *)(&lastpid), sizeof(lastpid),
- "!");
+ GETSYSCTL("kern.cp_time", cp_time);
+ GETSYSCTL("vm.loadavg", avenrun);
+ GETSYSCTL("kern.lastpid", lastpid);
/* convert load averages to doubles */
{
@@ -370,24 +323,22 @@ struct system_info *si;
/* sum memory & swap statistics */
{
- struct vmmeter sum;
static unsigned int swap_delay = 0;
static int swapavail = 0;
static int swapfree = 0;
static int bufspace = 0;
-
- (void) getkval(cnt_offset, (int *)(&sum), sizeof(sum),
- "_cnt");
- (void) getkval(bufspace_offset, (int *)(&bufspace), sizeof(bufspace),
- "_bufspace");
-
+ static int nspgsin, nspgsout;
+
+ GETSYSCTL("vfs.bufspace", bufspace);
+ GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]);
+ GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]);
+ GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[2]);
+ GETSYSCTL("vm.stats.vm.v_cache_count", memory_stats[3]);
+ GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]);
+ GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin);
+ GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout);
/* convert memory stats to Kbytes */
- memory_stats[0] = pagetok(sum.v_active_count);
- memory_stats[1] = pagetok(sum.v_inactive_count);
- memory_stats[2] = pagetok(sum.v_wire_count);
- memory_stats[3] = pagetok(sum.v_cache_count);
memory_stats[4] = bufspace / 1024;
- memory_stats[5] = pagetok(sum.v_free_count);
memory_stats[6] = -1;
/* first interval */
@@ -398,12 +349,12 @@ struct system_info *si;
/* compute differences between old and new swap statistic */
else {
- swap_stats[4] = pagetok(((sum.v_swappgsin - swappgsin)));
- swap_stats[5] = pagetok(((sum.v_swappgsout - swappgsout)));
+ swap_stats[4] = pagetok(((nspgsin - swappgsin)));
+ swap_stats[5] = pagetok(((nspgsout - swappgsout)));
}
- swappgsin = sum.v_swappgsin;
- swappgsout = sum.v_swappgsout;
+ swappgsin = nspgsin;
+ swappgsout = nspgsout;
/* call CPU heavy swapmode() only for changes */
if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
@@ -640,77 +591,26 @@ char *(*get_userid)();
return(fmt);
}
+static void getsysctl (name, ptr, len)
-/*
- * check_nlist(nlst) - checks the nlist to see if any symbols were not
- * found. For every symbol that was not found, a one-line
- * message is printed to stderr. The routine returns the
- * number of symbols NOT found.
- */
-
-static int check_nlist(nlst)
-
-register struct nlist *nlst;
+char *name;
+void *ptr;
+int len;
{
- register int i;
-
- /* check to see if we got ALL the symbols we requested */
- /* this will write one line to stderr for every symbol not found */
-
- i = 0;
- while (nlst->n_name != NULL)
- {
- if (nlst->n_type == 0)
- {
- /* this one wasn't found */
- (void) fprintf(stderr, "kernel: no symbol named `%s'\n",
- nlst->n_name);
- i = 1;
- }
- nlst++;
+ int nlen = len;
+ if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
+ fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
+ strerror(errno));
+ quit(23);
}
-
- return(i);
-}
-
-
-/*
- * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
- * "offset" is the byte offset into the kernel for the desired value,
- * "ptr" points to a buffer into which the value is retrieved,
- * "size" is the size of the buffer (and the object to retrieve),
- * "refstr" is a reference string used when printing error meessages,
- * if "refstr" starts with a '!', then a failure on read will not
- * be fatal (this may seem like a silly way to do things, but I
- * really didn't want the overhead of another argument).
- *
- */
-
-static int getkval(offset, ptr, size, refstr)
-
-unsigned long offset;
-int *ptr;
-int size;
-char *refstr;
-
-{
- if (kvm_read(kd, offset, (char *) ptr, size) != size)
- {
- if (*refstr == '!')
- {
- return(0);
- }
- else
- {
- fprintf(stderr, "top: kvm_read for %s: %s\n",
- refstr, strerror(errno));
+ if (nlen != len) {
+ fprintf(stderr, "top: sysctl(%s...) expected %d, got %d\n", name,
+ len, nlen);
quit(23);
- }
}
- return(1);
}
-
+
/* comparison routines for qsort */
/*
@@ -952,29 +852,6 @@ int pid;
return(-1);
}
-
-/*
- * swapmode is based on a program called swapinfo written
- * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
- */
-
-#define SVAR(var) __STRING(var) /* to force expansion */
-#define KGET(idx, var) \
- KGET1(idx, &var, sizeof(var), SVAR(var))
-#define KGET1(idx, p, s, msg) \
- KGET2(nlst[idx].n_value, p, s, msg)
-#define KGET2(addr, p, s, msg) \
- if (kvm_read(kd, (u_long)(addr), p, s) != s) { \
- warnx("cannot read %s: %s", msg, kvm_geterr(kd)); \
- return (0); \
- }
-#define KGETRET(addr, p, s, msg) \
- if (kvm_read(kd, (u_long)(addr), p, s) != s) { \
- warnx("cannot read %s: %s", msg, kvm_geterr(kd)); \
- return (0); \
- }
-
-
int
swapmode(retavail, retfree)
int *retavail;
OpenPOWER on IntegriCloud