Subject: top 3.5b5 patches for -current and not so -current
To: None <current-users@NetBSD.ORG>
From: Luke Mewburn <lukem@connect.com.au>
List: current-users
Date: 06/17/1997 17:51:49
Here's a patch to top3.5-beta5 that does the following:
* fixes up a minor bug in the configure script.
* adds process ordering (sorting on cpu, pri, res, size,
state, or time)
* removes attempted support for LASTPID - it didn't work,
and in any case, it's a security issue.
* adds a new module for netbsd 1.3 (and netbsd1.2G) -
m_netbsd13.c, which supports the new swap code.
You can get the source from:
ftp://ftp.groupsys.com/pub/top/top-3.5beta5.tar.gz
Here's the diff:
diff -Ncr /z/src/local/top-3.5beta5/Configure ./Configure
*** /z/src/local/top-3.5beta5/Configure Sat Dec 21 02:52:30 1996
--- ./Configure Tue Apr 22 19:19:34 1997
***************
*** 346,352 ****
EOF
set t_mode = 4711
- set mode = 4711
else if (-e /dev/kmem) then
$ls /dev/kmem >/tmp/$$.b
grep '^....r..r..' /tmp/$$.b >&/dev/null
--- 346,351 ----
diff -Ncr /z/src/local/top-3.5beta5/commands.c ./commands.c
*** /z/src/local/top-3.5beta5/commands.c Wed Aug 28 00:13:57 1996
--- ./commands.c Tue Apr 22 19:19:34 1997
***************
*** 23,30 ****
--- 23,33 ----
#include <sys/time.h>
#include <sys/resource.h>
+ #include "top.h"
+ #include "top.local.h"
#include "sigdesc.h" /* generated automatically */
#include "boolean.h"
+ #include "machine.h"
#include "utils.h"
extern int errno;
***************
*** 42,49 ****
* either 'h' or '?'.
*/
! show_help()
!
{
printf("Top version %s, %s\n", version_string(), copyright);
fputs("\n\n\
--- 45,52 ----
* either 'h' or '?'.
*/
! show_help(statics)
! struct statics *statics;
{
printf("Top version %s, %s\n", version_string(), copyright);
fputs("\n\n\
***************
*** 72,79 ****
k - kill processes; send a signal to a list of processes\n\
n or # - change number of processes to display\n", stdout);
#ifdef ORDER
! fputs("\
! o - specify sort order (size, res, cpu, time)\n", stdout);
#endif
fputs("\
r - renice a process\n\
--- 75,89 ----
k - kill processes; send a signal to a list of processes\n\
n or # - change number of processes to display\n", stdout);
#ifdef ORDER
! {
! int i;
!
! fputs("\
! o - specify sort order (", stdout);
! for (i = 0; statics->order_names[i] != NULL; i++)
! printf("%s%s", i == 0 ? "" : ", ", statics->order_names[i]);
! puts(")");
! }
#endif
fputs("\
r - renice a process\n\
diff -Ncr /z/src/local/top-3.5beta5/machine/m_netbsd10.c ./machine/m_netbsd10.c
*** /z/src/local/top-3.5beta5/machine/m_netbsd10.c Fri Jan 26 16:27:18 1996
--- ./machine/m_netbsd10.c Tue Jun 17 16:57:08 1997
***************
*** 1,49 ****
/*
* top - a top users display for Unix
*
! * SYNOPSIS: For a NetBSD-1.0 (4.4BSD) system
* Note process resident sizes could be wrong, but ps shows
* zero for them too..
*
* DESCRIPTION:
* Originally written for BSD4.4 system by Christos Zoulas.
! * Based on the FreeBSD 2.0 version by Steven Wallace && Wolfram Schneider
! * NetBSD-1.0 port by Arne Helme
! * .
! * This is the machine-dependent module for NetBSD-1.0
* Works for:
* NetBSD-1.0
*
* LIBS: -lkvm
*
! * CFLAGS: -DHAVE_GETOPT
*
- * AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
- * Steven Wallace <swallace@freebsd.org>
- * Wolfram Schneider <wosch@cs.tu-berlin.de>
- * Arne Helme <arne@acm.org>
*
* $Id: machine.c,v 1.5 1995/01/06 02:04:39 swallace Exp $
*/
!
! #define LASTPID /**/ /* use last pid, compiler depended */
! /* #define LASTPID_FIXED /**/
#define VM_REAL /**/ /* use the same values as vmstat -s */
#define USE_SWAP /**/ /* use swap usage (pstat -s),
need to much cpu time */
- /* #define DEBUG 1 /**/
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
-
- #include "os.h"
- #include <stdio.h>
- #include <nlist.h>
- #include <math.h>
- #include <kvm.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
#include <sys/dir.h>
--- 1,46 ----
/*
* top - a top users display for Unix
*
! * SYNOPSIS: For a NetBSD-1.0 through NetBSD-1.2.1 system
* Note process resident sizes could be wrong, but ps shows
* zero for them too..
*
* DESCRIPTION:
* Originally written for BSD4.4 system by Christos Zoulas.
! * Based on the FreeBSD 2.0 version by Steven Wallace and Wolfram Schneider.
! * NetBSD-1.0 port by Arne Helme. Process ordering added by Luke Mewburn.
! *
! * This is the machine-dependent module for NetBSD-1.0 and later
* Works for:
* NetBSD-1.0
+ * NetBSD-1.1
+ * NetBSD-1.2
+ * NetBSD-1.2.1
*
* LIBS: -lkvm
*
! * CFLAGS: -DHAVE_GETOPT -DORDER
! *
! * AUTHORS: Christos Zoulas <christos@ee.cornell.edu>
! * Steven Wallace <swallace@freebsd.org>
! * Wolfram Schneider <wosch@cs.tu-berlin.de>
! * Arne Helme <arne@acm.org>
! * Luke Mewburn <lukem@netbsd.org>
*
*
* $Id: machine.c,v 1.5 1995/01/06 02:04:39 swallace Exp $
*/
! /* #define LASTPID */ /* use last pid, compiler depended */
! /* #define LASTPID_FIXED */
#define VM_REAL /**/ /* use the same values as vmstat -s */
#define USE_SWAP /**/ /* use swap usage (pstat -s),
need to much cpu time */
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
#include <sys/dir.h>
***************
*** 51,56 ****
--- 48,61 ----
#include <sys/file.h>
#include <sys/time.h>
+ #include "os.h"
+ #include <err.h>
+ #include <kvm.h>
+ #include <math.h>
+ #include <nlist.h>
+ #include <stdio.h>
+ #include <unistd.h>
+
#ifdef USE_SWAP
#include <stdlib.h>
#include <sys/map.h>
***************
*** 85,91 ****
((pct) / (1.0 - exp(PP((pp), p_swtime) * logcpu))))
/* what we consider to be process size: */
! #define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
/* definitions for indices in the nlist array */
--- 90,97 ----
((pct) / (1.0 - exp(PP((pp), p_swtime) * logcpu))))
/* what we consider to be process size: */
! #define PROCSIZE(pp) \
! (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
/* definitions for indices in the nlist array */
***************
*** 169,175 ****
char *state_abbrev[] =
{
! "", "start", "run\0\0\0", "sleep", "stop", "zomb", "WAIT"
};
--- 175,181 ----
char *state_abbrev[] =
{
! "", "start", "run\0\0\0", "sleep", "stop", "zomb"
};
***************
*** 194,200 ****
#endif
#ifdef VM_REAL
static unsigned long cnt_offset;
- static long cnt;
#endif
/* these are for calculating cpu state percentages */
--- 200,205 ----
***************
*** 237,242 ****
--- 242,278 ----
#endif
};
+
+ /* these are names given to allowed sorting orders -- first is default */
+ char *ordernames[] = {
+ "cpu",
+ "pri",
+ "res",
+ "size",
+ "state",
+ "time",
+ NULL
+ };
+
+ /* forward definitions for comparison functions */
+ int compare_cpu();
+ int compare_prio();
+ int compare_res();
+ int compare_size();
+ int compare_state();
+ int compare_time();
+
+ int (*proc_compares[])() = {
+ compare_cpu,
+ compare_prio,
+ compare_res,
+ compare_size,
+ compare_state,
+ compare_time,
+ NULL
+ };
+
+
/* these are for keeping track of the proc array */
static int nproc;
***************
*** 258,269 ****
int
machine_init(statics)
!
! struct statics *statics;
!
{
! register int i = 0;
! register int pagesize;
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
return -1;
--- 294,303 ----
int
machine_init(statics)
! struct statics *statics;
{
! int i = 0;
! int pagesize;
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
return -1;
***************
*** 291,300 ****
}
- #if (defined DEBUG)
- fprintf(stderr, "Hertz: %d\n", hz);
- #endif
-
(void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
nlst[X_CCPU].n_name);
--- 325,330 ----
***************
*** 331,347 ****
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* all done! */
return(0);
}
! char *format_header(uname_field)
!
! register char *uname_field;
!
{
! register char *ptr;
ptr = header + UNAME_START;
while (*uname_field != '\0')
--- 361,377 ----
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
+ statics->order_names = ordernames;
/* all done! */
return(0);
}
! char *
! format_header(uname_field)
! char *uname_field;
{
! char *ptr;
ptr = header + UNAME_START;
while (*uname_field != '\0')
***************
*** 358,402 ****
void
get_system_info(si)
!
! struct system_info *si;
!
{
long total;
- load_avg avenrun[3];
/* 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);
#ifdef LASTPID
! (void) getkval(lastpid_offset, (int *)(&lastpid), sizeof(lastpid),
! "!");
#endif
! /* convert load averages to doubles */
! {
! register int i;
! register double *infoloadp;
! load_avg *avenrunp;
!
! #ifdef notyet
! struct loadavg sysload;
! int size;
! getkerninfo(KINFO_LOADAVG, &sysload, &size, 0);
! #endif
! infoloadp = si->load_avg;
! avenrunp = avenrun;
! for (i = 0; i < 3; i++)
! {
! #ifdef notyet
! *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
! #endif
! *infoloadp++ = loaddouble(*avenrunp++);
! }
}
/* convert cp_time counts to percentages */
--- 388,411 ----
void
get_system_info(si)
! struct system_info *si;
{
long total;
/* get the cp_time array */
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
nlst[X_CP_TIME].n_name);
#ifdef LASTPID
! (void) getkval(lastpid_offset, (int *)(&lastpid), sizeof(lastpid), "!");
#endif
! if (getloadavg(si->load_avg, NUM_AVERAGES) < 0) {
! int i;
! warn("can't getloadavg");
! for (i = 0; i < NUM_AVERAGES; i++)
! si->load_avg[i] = 0.0;
}
/* convert cp_time counts to percentages */
***************
*** 424,431 ****
memory_stats[5] = pagetok(total.t_vm);
memory_stats[6] = -1;
memory_stats[7] = pagetok(total.t_free);
! }
! #else
struct vmmeter sum;
static unsigned int swap_delay = 0;
--- 433,440 ----
memory_stats[5] = pagetok(total.t_vm);
memory_stats[6] = -1;
memory_stats[7] = pagetok(total.t_free);
!
! #else /* !VM_REAL */
struct vmmeter sum;
static unsigned int swap_delay = 0;
***************
*** 453,466 ****
memory_stats[4] = swapmode();
}
/* swap_delay++; XXX Arne */
! #else
memory_stats[4] = 0;
! #endif
memory_stats[7] = -1;
}
! #endif
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
--- 462,476 ----
memory_stats[4] = swapmode();
}
/* swap_delay++; XXX Arne */
! #else /* !USE_SWAP */
memory_stats[4] = 0;
! #endif /* !USE_SWAP */
memory_stats[7] = -1;
+ #endif /* !VM_REAL */
}
!
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
***************
*** 473,495 ****
#else
si->last_pid = -1;
#endif
-
}
static struct handle handle;
! caddr_t get_process_info(si, sel, compare)
!
! struct system_info *si;
! struct process_select *sel;
! int (*compare)();
!
{
! register int i;
! register int total_procs;
! register int active_procs;
! register struct kinfo_proc **prefp;
! register struct kinfo_proc *pp;
/* these are copied out of sel for speed */
int show_idle;
--- 483,503 ----
#else
si->last_pid = -1;
#endif
}
static struct handle handle;
! caddr_t
! get_process_info(si, sel, compare)
! struct system_info *si;
! struct process_select *sel;
! int (*compare)();
{
! int i;
! int total_procs;
! int active_procs;
! struct kinfo_proc **prefp;
! struct kinfo_proc *pp;
/* these are copied out of sel for speed */
int show_idle;
***************
*** 562,576 ****
char fmt[128]; /* static area where result is built */
! char *format_next_process(handle, get_userid)
!
! caddr_t handle;
! char *(*get_userid)();
!
{
! register struct kinfo_proc *pp;
! register long cputime;
! register double pct;
struct handle *hp;
/* find and remember the next proc structure */
--- 570,583 ----
char fmt[128]; /* static area where result is built */
! char *
! format_next_process(handle, get_userid)
! caddr_t handle;
! char *(*get_userid)();
{
! struct kinfo_proc *pp;
! long cputime;
! double pct;
struct handle *hp;
/* find and remember the next proc structure */
***************
*** 631,642 ****
* number of symbols NOT found.
*/
! static int check_nlist(nlst)
!
! register struct nlist *nlst;
!
{
! 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 */
--- 638,648 ----
* number of symbols NOT found.
*/
! static int
! check_nlist(nlst)
! struct nlist *nlst;
{
! 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 */
***************
*** 670,682 ****
*
*/
! 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)
{
--- 676,687 ----
*
*/
! 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)
{
***************
*** 694,768 ****
return(1);
}
! /* comparison routine for qsort */
/*
! * proc_compare - comparison function for "qsort"
! * Compares the resource consumption of two processes using five
! * distinct keys. The keys (in descending order of importance) are:
! * percent cpu, cpu ticks, state, resident set size, total virtual
! * memory usage. The process states are ordered as follows (from least
! * to most important): WAIT, zombie, sleep, stop, start, run. The
! * array declaration below maps a process state index into a number
! * that reflects this ordering.
*/
! static unsigned char sorted_state[] =
! {
! 0, /* not used */
! 3, /* sleep */
! 1, /* ABANDONED (WAIT) */
! 6, /* run */
! 5, /* start */
! 2, /* zombie */
! 4 /* stop */
};
!
int
! proc_compare(pp1, pp2)
! struct proc **pp1;
! struct proc **pp2;
{
! register struct kinfo_proc *p1;
! register struct kinfo_proc *p2;
! register int result;
! register pctcpu lresult;
/* remove one level of indirection */
p1 = *(struct kinfo_proc **) pp1;
p2 = *(struct kinfo_proc **) pp2;
! /* compare percent cpu (pctcpu) */
! if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0)
! {
! /* use cpticks to break the tie */
! if ((result = PP(p2, p_cpticks) - PP(p1, p_cpticks)) == 0)
! {
! /* use process state to break the tie */
! if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] -
! sorted_state[(unsigned char) PP(p1, p_stat)]) == 0)
! {
! /* use priority to break the tie */
! if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
! {
! /* use resident set size (rssize) to break the tie */
! if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
! {
! /* use total memory to break the tie */
! result = PROCSIZE(p2) - PROCSIZE(p1);
! }
! }
! }
! }
! }
! else
! {
! result = lresult < 0 ? -1 : 1;
! }
! return(result);
}
--- 699,913 ----
return(1);
}
! /* comparison routines for qsort */
/*
! * There are currently four possible comparison routines. main selects
! * one of these by indexing in to the array proc_compares.
! *
! * Possible keys are defined as macros below. Currently these keys are
! * defined: percent cpu, cpu ticks, process state, resident set size,
! * total virtual memory usage. The process states are ordered as follows
! * (from least to most important): WAIT, zombie, sleep, stop, start, run.
! * The array declaration below maps a process state index into a number
! * that reflects this ordering.
*/
! /*
! * First, the possible comparison keys. These are defined in such a way
! * that they can be merely listed in the source code to define the actual
! * desired ordering.
! */
!
! #define ORDERKEY_PCTCPU \
! if (lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu),\
! (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
!
! #define ORDERKEY_CPTICKS \
! if (lresult = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec,\
! (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
!
! #define ORDERKEY_STATE \
! if ((result = sorted_state[(int)PP(p2, p_stat)] - \
! sorted_state[(int)PP(p1, p_stat)] ) == 0)
!
! #define ORDERKEY_PRIO \
! if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
!
! #define ORDERKEY_RSSIZE \
! if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
!
! #define ORDERKEY_MEM \
! if ((result = (PROCSIZE(p2) - PROCSIZE(p1))) == 0)
!
! /*
! * Now the array that maps process state to a weight.
! * The order of the elements should match those in state_abbrev[]
! */
!
! static int sorted_state[] = {
! 0, /* (not used) ? */
! 4, /* "start" SIDL */
! 5, /* "run" SRUN */
! 2, /* "sleep" SSLEEP */
! 3, /* "stop" SSTOP */
! 1, /* "zomb" SZOMB */
};
!
! /* compare_cpu - the comparison function for sorting by cpu percentage */
!
int
! compare_cpu(pp1, pp2)
! struct proc **pp1, **pp2;
! {
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
! /* remove one level of indirection */
! p1 = *(struct kinfo_proc **) pp1;
! p2 = *(struct kinfo_proc **) pp2;
!
! ORDERKEY_PCTCPU
! ORDERKEY_CPTICKS
! ORDERKEY_STATE
! ORDERKEY_PRIO
! ORDERKEY_RSSIZE
! ORDERKEY_MEM
! ;
!
! return (result);
! }
+ /* compare_prio - the comparison function for sorting by process priority */
+
+ int
+ compare_prio(pp1, pp2)
+ struct proc **pp1, **pp2;
{
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
/* remove one level of indirection */
p1 = *(struct kinfo_proc **) pp1;
p2 = *(struct kinfo_proc **) pp2;
! ORDERKEY_PRIO
! ORDERKEY_PCTCPU
! ORDERKEY_CPTICKS
! ORDERKEY_STATE
! ORDERKEY_RSSIZE
! ORDERKEY_MEM
! ;
!
! return (result);
! }
!
! /* compare_res - the comparison function for sorting by resident set size */
!
! int
! compare_res(pp1, pp2)
! struct proc **pp1, **pp2;
! {
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
!
! /* remove one level of indirection */
! p1 = *(struct kinfo_proc **) pp1;
! p2 = *(struct kinfo_proc **) pp2;
! ORDERKEY_RSSIZE
! ORDERKEY_MEM
! ORDERKEY_PCTCPU
! ORDERKEY_CPTICKS
! ORDERKEY_STATE
! ORDERKEY_PRIO
! ;
!
! return (result);
! }
!
! /* compare_size - the comparison function for sorting by total memory usage */
!
! int
! compare_size(pp1, pp2)
! struct proc **pp1, **pp2;
! {
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
!
! /* remove one level of indirection */
! p1 = *(struct kinfo_proc **) pp1;
! p2 = *(struct kinfo_proc **) pp2;
!
! ORDERKEY_MEM
! ORDERKEY_RSSIZE
! ORDERKEY_PCTCPU
! ORDERKEY_CPTICKS
! ORDERKEY_STATE
! ORDERKEY_PRIO
! ;
!
! return (result);
! }
!
! /* compare_state - the comparison function for sorting by process state */
!
! int
! compare_state(pp1, pp2)
! struct proc **pp1, **pp2;
! {
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
!
! /* remove one level of indirection */
! p1 = *(struct kinfo_proc **) pp1;
! p2 = *(struct kinfo_proc **) pp2;
!
! ORDERKEY_STATE
! ORDERKEY_PCTCPU
! ORDERKEY_CPTICKS
! ORDERKEY_PRIO
! ORDERKEY_RSSIZE
! ORDERKEY_MEM
! ;
!
! return (result);
! }
!
! /* compare_time - the comparison function for sorting by total cpu time */
!
! int
! compare_time(pp1, pp2)
! struct proc **pp1, **pp2;
! {
! struct kinfo_proc *p1;
! struct kinfo_proc *p2;
! int result;
! pctcpu lresult;
!
! /* remove one level of indirection */
! p1 = *(struct kinfo_proc **) pp1;
! p2 = *(struct kinfo_proc **) pp2;
!
! ORDERKEY_CPTICKS
! ORDERKEY_PCTCPU
! ORDERKEY_STATE
! ORDERKEY_PRIO
! ORDERKEY_MEM
! ORDERKEY_RSSIZE
! ;
!
! return (result);
}
***************
*** 776,789 ****
* and "renice" commands.
*/
! int proc_owner(pid)
!
! int pid;
!
{
! register int cnt;
! register struct kinfo_proc **prefp;
! register struct kinfo_proc *pp;
prefp = pref;
cnt = pref_len;
--- 921,933 ----
* and "renice" commands.
*/
! int
! proc_owner(pid)
! int pid;
{
! int cnt;
! struct kinfo_proc **prefp;
! struct kinfo_proc *pp;
prefp = pref;
cnt = pref_len;
***************
*** 830,835 ****
--- 974,980 ----
struct map *swapmap, *kswapmap;
struct mapent *mp, *freemp;
+ l = 0;
KGET(VM_NSWAP, nswap);
KGET(VM_NSWDEV, nswdev);
KGET(VM_DMMAX, dmmax);
***************
*** 936,941 ****
return (int)(((double)used / (double)avail * 100.0) + 0.5);
}
!
! #endif
!
--- 1081,1084 ----
return (int)(((double)used / (double)avail * 100.0) + 0.5);
}
! #endif /* USE_SWAP */
diff -Ncr /z/src/local/top-3.5beta5/machine/m_netbsd13.c ./machine/m_netbsd13.c
*** /z/src/local/top-3.5beta5/machine/m_netbsd13.c Thu Jan 1 10:00:00 1970
--- ./machine/m_netbsd13.c Tue Jun 17 17:41:07 1997
***************
*** 0 ****
--- 1,841 ----
+ /*
+ * top - a top users display for Unix
+ *
+ * SYNOPSIS: For a NetBSD-1.3 (or later) system
+ *
+ * DESCRIPTION:
+ * Originally written for BSD4.4 system by Christos Zoulas.
+ * Based on the FreeBSD 2.0 version by Steven Wallace and Wolfram Schneider.
+ * NetBSD-1.0 port by Arne Helme. Process ordering by Luke Mewburn.
+ * NetBSD-1.3 port by Luke Mewburn, based on code by Matthew Green.
+ *
+ * This is the machine-dependent module for NetBSD-1.3 and later
+ * Works for:
+ * NetBSD-1.3
+ *
+ * LIBS: -lkvm
+ *
+ * CFLAGS: -DHAVE_GETOPT -DORDER
+ *
+ * AUTHORS: Christos Zoulas <christos@ee.cornell.edu>
+ * Steven Wallace <swallace@freebsd.org>
+ * Wolfram Schneider <wosch@cs.tu-berlin.de>
+ * Arne Helme <arne@acm.org>
+ * Luke Mewburn <lukem@netbsd.org>
+ * Matthew Green <mrg@eterna.com.au>
+ *
+ *
+ * $Id: machine.c,v 1.5 1995/01/06 02:04:39 swallace Exp $
+ */
+
+ #include <sys/types.h>
+ #include <sys/signal.h>
+ #include <sys/param.h>
+ #include <sys/stat.h>
+ #include <sys/errno.h>
+ #include <sys/sysctl.h>
+ #include <sys/dir.h>
+ #include <sys/dkstat.h>
+ #include <sys/file.h>
+ #include <sys/time.h>
+
+ #include <vm/vm_swap.h>
+
+ #include "os.h"
+ #include <err.h>
+ #include <errno.h>
+ #include <kvm.h>
+ #include <math.h>
+ #include <nlist.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+ static int check_nlist __P((struct nlist *));
+ static int getkval __P((unsigned long, int *, int, char *));
+ extern char* printable __P((char *));
+
+ #include "top.h"
+ #include "machine.h"
+ #include "utils.h"
+
+
+ /* get_process_info passes back a handle. This is what it looks like: */
+
+ struct handle
+ {
+ struct kinfo_proc **next_proc; /* points to next valid proc pointer */
+ int remaining; /* number of pointers remaining */
+ };
+
+ /* declarations for load_avg */
+ #include "loadavg.h"
+
+ #define PP(pp, field) ((pp)->kp_proc . field)
+ #define EP(pp, field) ((pp)->kp_eproc . field)
+ #define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
+
+ /* define what weighted cpu is. */
+ #define weighted_cpu(pct, pp) (PP((pp), p_swtime) == 0 ? 0.0 : \
+ ((pct) / (1.0 - exp(PP((pp), p_swtime) * logcpu))))
+
+ /* what we consider to be process size: */
+ #define PROCSIZE(pp) \
+ (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
+
+ /* definitions for indices in the nlist array */
+
+
+ static struct nlist nlst[] = {
+ #define X_CCPU 0
+ { "_ccpu" }, /* 0 */
+ #define X_CP_TIME 1
+ { "_cp_time" }, /* 1 */
+ #define X_HZ 2
+ { "_hz" }, /* 2 */
+ #define X_STATHZ 3
+ { "_stathz" }, /* 3 */
+ #define X_AVENRUN 4
+ { "_averunnable" }, /* 4 */
+ #define X_CNT 5
+ { "_cnt" },
+
+ { 0 }
+ };
+
+ /*
+ * These definitions control the format of the per-process area
+ */
+
+ static char header[] =
+ " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
+ /* 0123456 -- field to fill in starts at header+6 */
+ #define UNAME_START 6
+
+ #define Proc_format \
+ "%5d %-8.8s %3d %4d%7s %5s %-5s%7s %5.2f%% %5.2f%% %.14s"
+
+
+ /* process state names for the "STATE" column of the display */
+ /* the extra nulls in the string "run" are for adding a slash and
+ the processor number when needed */
+
+ char *state_abbrev[] =
+ {
+ "", "start", "run\0\0\0", "sleep", "stop", "zomb"
+ };
+
+
+ static kvm_t *kd;
+
+ /* values that we stash away in _init and use in later routines */
+
+ static double logcpu;
+
+ /* these are retrieved from the kernel in _init */
+
+ static long hz;
+ static load_avg ccpu;
+
+ /* these are offsets obtained via nlist and used in the get_ functions */
+
+ static unsigned long cp_time_offset;
+ static unsigned long avenrun_offset;
+ static unsigned long cnt_offset;
+ /* these are for calculating cpu state percentages */
+
+ static long cp_time[CPUSTATES];
+ static long cp_old[CPUSTATES];
+ static long cp_diff[CPUSTATES];
+
+ /* these are for detailing the process states */
+
+ int process_states[7];
+ char *procstatenames[] = {
+ "", " starting, ", " running, ", " sleeping, ", " stopped, ",
+ " zombie, ", " ABANDONED, ",
+ NULL
+ };
+
+ /* these are for detailing the cpu states */
+
+ int cpu_states[CPUSTATES];
+ char *cpustatenames[] = {
+ "user", "nice", "system", "interrupt", "idle", NULL
+ };
+
+ /* these are for detailing the memory statistics */
+
+ int memory_stats[7];
+ char *memorynames[] = {
+ "K Act ", "K Inact ", "K Wired ", "K Free ",
+ "K Swap ", "K Swap free ",
+ NULL
+ };
+
+
+ /* these are names given to allowed sorting orders -- first is default */
+ char *ordernames[] = {
+ "cpu",
+ "pri",
+ "res",
+ "size",
+ "state",
+ "time",
+ NULL
+ };
+
+ /* forward definitions for comparison functions */
+ int compare_cpu();
+ int compare_prio();
+ int compare_res();
+ int compare_size();
+ int compare_state();
+ int compare_time();
+
+ int (*proc_compares[])() = {
+ compare_cpu,
+ compare_prio,
+ compare_res,
+ compare_size,
+ compare_state,
+ compare_time,
+ NULL
+ };
+
+
+ /* these are for keeping track of the proc array */
+
+ static int nproc;
+ static int onproc = -1;
+ static int pref_len;
+ static struct kinfo_proc *pbase;
+ static struct kinfo_proc **pref;
+
+ /* these are for getting the memory statistics */
+
+ static int pageshift; /* log base 2 of the pagesize */
+
+ /* define pagetok in terms of pageshift */
+
+ #define pagetok(size) ((size) << pageshift)
+
+ /* useful externals */
+ long percentages();
+
+ int
+ machine_init(statics)
+ struct statics *statics;
+ {
+ int i = 0;
+ int pagesize;
+
+ if ((kd = kvm_open(NULL, NULL, 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);
+ }
+
+ /* get the symbol values out of kmem */
+ (void) getkval(nlst[X_STATHZ].n_value, (int *)(&hz), sizeof(hz), "!");
+ if (!hz) {
+ (void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
+ nlst[X_HZ].n_name);
+ }
+
+
+ (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;
+ cnt_offset = nlst[X_CNT].n_value;
+
+ /* this is used in calculating WCPU -- calculate it ahead of time */
+ logcpu = log(loaddouble(ccpu));
+
+ pbase = NULL;
+ pref = NULL;
+ nproc = 0;
+ onproc = -1;
+ /* get the page size with "getpagesize" and calculate pageshift from it */
+ pagesize = getpagesize();
+ pageshift = 0;
+ while (pagesize > 1)
+ {
+ pageshift++;
+ pagesize >>= 1;
+ }
+
+ /* we only need the amount of log(2)1024 for our conversion */
+ pageshift -= LOG1024;
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->order_names = ordernames;
+
+ /* all done! */
+ return(0);
+ }
+
+ char *
+ format_header(uname_field)
+ char *uname_field;
+ {
+ char *ptr;
+
+ ptr = header + UNAME_START;
+ while (*uname_field != '\0')
+ {
+ *ptr++ = *uname_field++;
+ }
+
+ return(header);
+ }
+
+ void
+ get_system_info(si)
+ struct system_info *si;
+ {
+ long total;
+ struct vmmeter sum;
+ struct swapent *sep;
+ int totalsize, size, totalinuse, inuse, ncounted;
+ int rnswap, nswap;
+
+ /* get the cp_time array */
+ (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
+ nlst[X_CP_TIME].n_name);
+
+ if (getloadavg(si->load_avg, NUM_AVERAGES) < 0) {
+ int i;
+
+ warn("can't getloadavg");
+ for (i = 0; i < NUM_AVERAGES; i++)
+ si->load_avg[i] = 0.0;
+ }
+
+ /* convert cp_time counts to percentages */
+ total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+
+ /* sum memory statistics */
+
+ (void) getkval(cnt_offset, (int *)(&sum), sizeof(sum), "_cnt");
+
+ /* 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_free_count);
+
+ memory_stats[4] = memory_stats[5] = 0;
+
+ sep = NULL;
+ do {
+ nswap = swapctl(SWAP_NSWAP, 0, 0);
+ if (nswap < 1)
+ break;
+ sep = (struct swapent *)malloc(nswap * sizeof(*sep));
+ if (sep == NULL)
+ break;
+ rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
+ if (nswap != rnswap)
+ break;
+
+ totalsize = totalinuse = ncounted = 0;
+ for (; rnswap-- > 0; sep++) {
+ ncounted++;
+ size = sep->se_nblks;
+ inuse = sep->se_inuse;
+ totalsize += size;
+ totalinuse += inuse;
+ }
+ memory_stats[4] = dbtob(totalinuse) / 1024;
+ memory_stats[5] = dbtob(totalsize) / 1024 - memory_stats[4];
+ } while (0);
+ if (sep)
+ free(sep);
+
+ memory_stats[6] = -1;
+
+ /* set arrays and strings */
+ si->cpustates = cpu_states;
+ si->memory = memory_stats;
+ si->last_pid = -1;
+ }
+
+ static struct handle handle;
+
+ caddr_t
+ get_process_info(si, sel, compare)
+ struct system_info *si;
+ struct process_select *sel;
+ int (*compare)();
+ {
+ int i;
+ int total_procs;
+ int active_procs;
+ struct kinfo_proc **prefp;
+ struct kinfo_proc *pp;
+
+ /* these are copied out of sel for speed */
+ int show_idle;
+ int show_system;
+ int show_uid;
+ int show_command;
+
+
+ pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
+ if (nproc > onproc)
+ pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
+ * (onproc = nproc));
+ if (pref == NULL || pbase == NULL) {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ /* get a pointer to the states summary array */
+ si->procstates = process_states;
+
+ /* set up flags which define what we are going to select */
+ show_idle = sel->idle;
+ show_system = sel->system;
+ show_uid = sel->uid != -1;
+ show_command = sel->command != NULL;
+
+ /* count up process states and get pointers to interesting procs */
+ total_procs = 0;
+ active_procs = 0;
+ memset((char *)process_states, 0, sizeof(process_states));
+ prefp = pref;
+ for (pp = pbase, i = 0; i < nproc; pp++, i++)
+ {
+ /*
+ * Place pointers to each valid proc structure in pref[].
+ * Process slots that are actually in use have a non-zero
+ * status field. Processes with P_SYSTEM set are system
+ * processes---these get ignored unless show_sysprocs is set.
+ */
+ if (PP(pp, p_stat) != 0 &&
+ (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0)))
+ {
+ total_procs++;
+ process_states[(unsigned char) PP(pp, p_stat)]++;
+ if ((PP(pp, p_stat) != SZOMB) &&
+ (show_idle || (PP(pp, p_pctcpu) != 0) ||
+ (PP(pp, p_stat) == SRUN)) &&
+ (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
+ {
+ *prefp++ = pp;
+ active_procs++;
+ }
+ }
+ }
+
+ /* if requested, sort the "interesting" processes */
+ if (compare != NULL)
+ {
+ qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare);
+ }
+
+ /* remember active and total counts */
+ si->p_total = total_procs;
+ si->p_active = pref_len = active_procs;
+
+ /* pass back a handle */
+ handle.next_proc = pref;
+ handle.remaining = active_procs;
+ return((caddr_t)&handle);
+ }
+
+ char fmt[128]; /* static area where result is built */
+
+ char *
+ format_next_process(handle, get_userid)
+ caddr_t handle;
+ char *(*get_userid)();
+ {
+ struct kinfo_proc *pp;
+ long cputime;
+ double pct;
+ struct handle *hp;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *)handle;
+ pp = *(hp->next_proc++);
+ hp->remaining--;
+
+
+ /* get the process's user struct and set cputime */
+ if ((PP(pp, p_flag) & P_INMEM) == 0) {
+ /*
+ * Print swapped processes as <pname>
+ */
+ char *comm = PP(pp, p_comm);
+ #define COMSIZ sizeof(PP(pp, p_comm))
+ char buf[COMSIZ];
+ (void) strncpy(buf, comm, COMSIZ);
+ comm[0] = '<';
+ (void) strncpy(&comm[1], buf, COMSIZ - 2);
+ comm[COMSIZ - 2] = '\0';
+ (void) strncat(comm, ">", COMSIZ - 1);
+ comm[COMSIZ - 1] = '\0';
+ }
+
+ #if 0
+ /* This does not produce the correct results */
+ cputime = PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks);
+ #endif
+ cputime = PP(pp, p_rtime).tv_sec; /* This does not count interrupts */
+
+ /* calculate the base for cpu percentages */
+ pct = pctdouble(PP(pp, p_pctcpu));
+
+ #define Proc_format \
+ "%5d %-8.8s %3d %4d%7s %5s %-5s%7s %5.2f%% %5.2f%% %.14s"
+
+ /* format this entry */
+ sprintf(fmt,
+ Proc_format,
+ PP(pp, p_pid),
+ (*get_userid)(EP(pp, e_pcred.p_ruid)),
+ PP(pp, p_priority) - PZERO,
+ PP(pp, p_nice) - NZERO,
+ format_k(pagetok(PROCSIZE(pp))),
+ format_k(pagetok(VP(pp, vm_rssize))),
+ state_abbrev[(unsigned char) PP(pp, p_stat)],
+ format_time(cputime),
+ 10000.0 * weighted_cpu(pct, pp) / hz,
+ 10000.0 * pct / hz,
+ printable(PP(pp, p_comm)));
+
+ /* return the result */
+ return(fmt);
+ }
+
+
+ /*
+ * 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)
+ struct nlist *nlst;
+ {
+ 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++;
+ }
+
+ 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));
+ quit(23);
+ }
+ }
+ return(1);
+ }
+
+ /* comparison routines for qsort */
+
+ /*
+ * There are currently four possible comparison routines. main selects
+ * one of these by indexing in to the array proc_compares.
+ *
+ * Possible keys are defined as macros below. Currently these keys are
+ * defined: percent cpu, cpu ticks, process state, resident set size,
+ * total virtual memory usage. The process states are ordered as follows
+ * (from least to most important): WAIT, zombie, sleep, stop, start, run.
+ * The array declaration below maps a process state index into a number
+ * that reflects this ordering.
+ */
+
+ /*
+ * First, the possible comparison keys. These are defined in such a way
+ * that they can be merely listed in the source code to define the actual
+ * desired ordering.
+ */
+
+ #define ORDERKEY_PCTCPU \
+ if (lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu),\
+ (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
+
+ #define ORDERKEY_CPTICKS \
+ if (lresult = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec,\
+ (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
+
+ #define ORDERKEY_STATE \
+ if ((result = sorted_state[(int)PP(p2, p_stat)] - \
+ sorted_state[(int)PP(p1, p_stat)] ) == 0)
+
+ #define ORDERKEY_PRIO \
+ if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
+
+ #define ORDERKEY_RSSIZE \
+ if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
+
+ #define ORDERKEY_MEM \
+ if ((result = (PROCSIZE(p2) - PROCSIZE(p1))) == 0)
+
+ /*
+ * Now the array that maps process state to a weight.
+ * The order of the elements should match those in state_abbrev[]
+ */
+
+ static int sorted_state[] = {
+ 0, /* (not used) ? */
+ 4, /* "start" SIDL */
+ 5, /* "run" SRUN */
+ 2, /* "sleep" SSLEEP */
+ 3, /* "stop" SSTOP */
+ 1, /* "zomb" SZOMB */
+ };
+
+ /* compare_cpu - the comparison function for sorting by cpu percentage */
+
+ int
+ compare_cpu(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return (result);
+ }
+
+ /* compare_prio - the comparison function for sorting by process priority */
+
+ int
+ compare_prio(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_PRIO
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return (result);
+ }
+
+ /* compare_res - the comparison function for sorting by resident set size */
+
+ int
+ compare_res(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return (result);
+ }
+
+ /* compare_size - the comparison function for sorting by total memory usage */
+
+ int
+ compare_size(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return (result);
+ }
+
+ /* compare_state - the comparison function for sorting by process state */
+
+ int
+ compare_state(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_STATE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return (result);
+ }
+
+ /* compare_time - the comparison function for sorting by total cpu time */
+
+ int
+ compare_time(pp1, pp2)
+ struct proc **pp1, **pp2;
+ {
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+
+ /*
+ * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
+ * the process does not exist.
+ * It is EXTREMLY IMPORTANT that this function work correctly.
+ * If top runs setuid root (as in SVR4), then this function
+ * is the only thing that stands in the way of a serious
+ * security problem. It validates requests for the "kill"
+ * and "renice" commands.
+ */
+
+ int
+ proc_owner(pid)
+ int pid;
+ {
+ int cnt;
+ struct kinfo_proc **prefp;
+ struct kinfo_proc *pp;
+
+ prefp = pref;
+ cnt = pref_len;
+ while (--cnt >= 0)
+ {
+ pp = *prefp++;
+ if (PP(pp, p_pid) == (pid_t)pid)
+ {
+ return((int)EP(pp, e_pcred.p_ruid));
+ }
+ }
+ return(-1);
+ }
diff -Ncr /z/src/local/top-3.5beta5/top.c ./top.c
*** /z/src/local/top-3.5beta5/top.c Fri Sep 13 05:50:53 1996
--- ./top.c Tue Apr 22 19:19:34 1997
***************
*** 714,720 ****
case CMD_help2:
reset_display();
clear();
! show_help();
standout("Hit any key to continue: ");
fflush(stdout);
(void) read(0, &ch, 1);
--- 714,720 ----
case CMD_help2:
reset_display();
clear();
! show_help(&statics);
standout("Hit any key to continue: ");
fflush(stdout);
(void) read(0, &ch, 1);
diff -Ncr /z/src/local/top-3.5beta5/utils.c ./utils.c
*** /z/src/local/top-3.5beta5/utils.c Wed Sep 11 06:15:14 1996
--- ./utils.c Tue Apr 22 19:19:34 1997
***************
*** 16,21 ****
--- 16,23 ----
#include "top.h"
#include "os.h"
+ #include <errno.h>
+
int atoiwi(str)
char *str;