xref: /minix3/external/bsd/top/dist/machine/m_sunos5.c (revision b89261ba018da33f0bd8cd05f5a1fe9e7a9c837b)
1*b89261baSDavid van Moolenbroek /*
2*b89261baSDavid van Moolenbroek  * top - a top users display for Unix
3*b89261baSDavid van Moolenbroek  *
4*b89261baSDavid van Moolenbroek  * SYNOPSIS:  Any Sun running SunOS 5.x (Solaris 2.x)
5*b89261baSDavid van Moolenbroek  *
6*b89261baSDavid van Moolenbroek  * DESCRIPTION:
7*b89261baSDavid van Moolenbroek  * This is the machine-dependent module for SunOS 5.x (Solaris 2).
8*b89261baSDavid van Moolenbroek  * There is some support for MP architectures.
9*b89261baSDavid van Moolenbroek  * This makes top work on all revisions of SunOS 5 from 5.0
10*b89261baSDavid van Moolenbroek  * through 5.9 (otherwise known as Solaris 9).  It has not been
11*b89261baSDavid van Moolenbroek  * tested on SunOS 5.10.
12*b89261baSDavid van Moolenbroek  *
13*b89261baSDavid van Moolenbroek  * AUTHORS:      Torsten Kasch 		<torsten@techfak.uni-bielefeld.de>
14*b89261baSDavid van Moolenbroek  *               Robert Boucher		<boucher@sofkin.ca>
15*b89261baSDavid van Moolenbroek  * CONTRIBUTORS: Marc Cohen 		<marc@aai.com>
16*b89261baSDavid van Moolenbroek  *               Charles Hedrick 	<hedrick@geneva.rutgers.edu>
17*b89261baSDavid van Moolenbroek  *	         William L. Jones 	<jones@chpc>
18*b89261baSDavid van Moolenbroek  *               Petri Kutvonen         <kutvonen@cs.helsinki.fi>
19*b89261baSDavid van Moolenbroek  *	         Casper Dik             <casper.dik@sun.com>
20*b89261baSDavid van Moolenbroek  *               Tim Pugh               <tpugh@oce.orst.edu>
21*b89261baSDavid van Moolenbroek  */
22*b89261baSDavid van Moolenbroek 
23*b89261baSDavid van Moolenbroek #define _KMEMUSER
24*b89261baSDavid van Moolenbroek 
25*b89261baSDavid van Moolenbroek #include "os.h"
26*b89261baSDavid van Moolenbroek #include "utils.h"
27*b89261baSDavid van Moolenbroek #include "username.h"
28*b89261baSDavid van Moolenbroek #include "display.h"
29*b89261baSDavid van Moolenbroek 
30*b89261baSDavid van Moolenbroek #if (OSREV == 551)
31*b89261baSDavid van Moolenbroek #undef OSREV
32*b89261baSDavid van Moolenbroek #define OSREV 55
33*b89261baSDavid van Moolenbroek #endif
34*b89261baSDavid van Moolenbroek 
35*b89261baSDavid van Moolenbroek /*
36*b89261baSDavid van Moolenbroek  * Starting with SunOS 5.6 the data in /proc changed along with the
37*b89261baSDavid van Moolenbroek  * means by which it is accessed.  In this case we define USE_NEW_PROC.
38*b89261baSDavid van Moolenbroek  * Note that with USE_NEW_PROC defined the structure named "prpsinfo"
39*b89261baSDavid van Moolenbroek  * is redefined to be "psinfo".  This will be confusing as you read
40*b89261baSDavid van Moolenbroek  * the code.
41*b89261baSDavid van Moolenbroek  */
42*b89261baSDavid van Moolenbroek 
43*b89261baSDavid van Moolenbroek #if OSREV >= 56
44*b89261baSDavid van Moolenbroek #define USE_NEW_PROC
45*b89261baSDavid van Moolenbroek #endif
46*b89261baSDavid van Moolenbroek 
47*b89261baSDavid van Moolenbroek #if defined(USE_NEW_PROC)
48*b89261baSDavid van Moolenbroek #define _STRUCTURED_PROC 1
49*b89261baSDavid van Moolenbroek #define prpsinfo psinfo
50*b89261baSDavid van Moolenbroek #include <sys/procfs.h>
51*b89261baSDavid van Moolenbroek #define pr_fill pr_nlwp
52*b89261baSDavid van Moolenbroek /* the "px" macros are used where the actual member could be in a substructure */
53*b89261baSDavid van Moolenbroek #define px_state pr_lwp.pr_state
54*b89261baSDavid van Moolenbroek #define px_nice pr_lwp.pr_nice
55*b89261baSDavid van Moolenbroek #define px_pri pr_lwp.pr_pri
56*b89261baSDavid van Moolenbroek #define px_onpro pr_lwp.pr_onpro
57*b89261baSDavid van Moolenbroek #define ZOMBIE(p)	((p)->pr_nlwp == 0)
58*b89261baSDavid van Moolenbroek #define SIZE_K(p)	(long)((p)->pr_size)
59*b89261baSDavid van Moolenbroek #define RSS_K(p)	(long)((p)->pr_rssize)
60*b89261baSDavid van Moolenbroek #else
61*b89261baSDavid van Moolenbroek #define px_state pr_state
62*b89261baSDavid van Moolenbroek #define px_oldpri pr_oldpri
63*b89261baSDavid van Moolenbroek #define px_nice pr_nice
64*b89261baSDavid van Moolenbroek #define px_pri pr_pri
65*b89261baSDavid van Moolenbroek #define px_onpro pr_filler[5]
66*b89261baSDavid van Moolenbroek #define ZOMBIE(p)	((p)->pr_zomb)
67*b89261baSDavid van Moolenbroek #define SIZE_K(p)	(long)((p)->pr_bysize/1024)
68*b89261baSDavid van Moolenbroek #define RSS_K(p)	(long)((p)->pr_byrssize/1024)
69*b89261baSDavid van Moolenbroek #endif
70*b89261baSDavid van Moolenbroek 
71*b89261baSDavid van Moolenbroek #include "top.h"
72*b89261baSDavid van Moolenbroek #include "machine.h"
73*b89261baSDavid van Moolenbroek #include <limits.h>
74*b89261baSDavid van Moolenbroek #include <stdio.h>
75*b89261baSDavid van Moolenbroek #include <fcntl.h>
76*b89261baSDavid van Moolenbroek #include <unistd.h>
77*b89261baSDavid van Moolenbroek #include <stdlib.h>
78*b89261baSDavid van Moolenbroek #include <errno.h>
79*b89261baSDavid van Moolenbroek #include <dirent.h>
80*b89261baSDavid van Moolenbroek #include <nlist.h>
81*b89261baSDavid van Moolenbroek #include <string.h>
82*b89261baSDavid van Moolenbroek #include <kvm.h>
83*b89261baSDavid van Moolenbroek #include <signal.h>
84*b89261baSDavid van Moolenbroek #include <sys/types.h>
85*b89261baSDavid van Moolenbroek #include <sys/param.h>
86*b89261baSDavid van Moolenbroek #include <sys/signal.h>
87*b89261baSDavid van Moolenbroek #include <sys/fault.h>
88*b89261baSDavid van Moolenbroek #include <sys/sysinfo.h>
89*b89261baSDavid van Moolenbroek #include <sys/sysmacros.h>
90*b89261baSDavid van Moolenbroek #include <sys/syscall.h>
91*b89261baSDavid van Moolenbroek #include <sys/user.h>
92*b89261baSDavid van Moolenbroek #include <sys/proc.h>
93*b89261baSDavid van Moolenbroek #include <sys/procfs.h>
94*b89261baSDavid van Moolenbroek #include <sys/vm.h>
95*b89261baSDavid van Moolenbroek #include <sys/var.h>
96*b89261baSDavid van Moolenbroek #include <sys/cpuvar.h>
97*b89261baSDavid van Moolenbroek #include <sys/file.h>
98*b89261baSDavid van Moolenbroek #include <sys/time.h>
99*b89261baSDavid van Moolenbroek #include <sys/priocntl.h>
100*b89261baSDavid van Moolenbroek #include <sys/tspriocntl.h>
101*b89261baSDavid van Moolenbroek #include <sys/processor.h>
102*b89261baSDavid van Moolenbroek #include <sys/resource.h>
103*b89261baSDavid van Moolenbroek #include <sys/swap.h>
104*b89261baSDavid van Moolenbroek #include <sys/stat.h>
105*b89261baSDavid van Moolenbroek #include <vm/anon.h>
106*b89261baSDavid van Moolenbroek #include <math.h>
107*b89261baSDavid van Moolenbroek #include <utmpx.h>
108*b89261baSDavid van Moolenbroek #include "utils.h"
109*b89261baSDavid van Moolenbroek #include "hash.h"
110*b89261baSDavid van Moolenbroek 
111*b89261baSDavid van Moolenbroek #if OSREV >= 53
112*b89261baSDavid van Moolenbroek #define USE_KSTAT
113*b89261baSDavid van Moolenbroek #endif
114*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
115*b89261baSDavid van Moolenbroek #include <kstat.h>
116*b89261baSDavid van Moolenbroek /*
117*b89261baSDavid van Moolenbroek  * Some kstats are fixed at 32 bits, these will be specified as ui32; some
118*b89261baSDavid van Moolenbroek  * are "natural" size (32 bit on 32 bit Solaris, 64 on 64 bit Solaris
119*b89261baSDavid van Moolenbroek  * we'll make those unsigned long)
120*b89261baSDavid van Moolenbroek  * Older Solaris doesn't define KSTAT_DATA_UINT32, those are always 32 bit.
121*b89261baSDavid van Moolenbroek  */
122*b89261baSDavid van Moolenbroek # ifndef KSTAT_DATA_UINT32
123*b89261baSDavid van Moolenbroek #  define ui32 ul
124*b89261baSDavid van Moolenbroek # endif
125*b89261baSDavid van Moolenbroek #endif
126*b89261baSDavid van Moolenbroek 
127*b89261baSDavid van Moolenbroek #define UNIX "/dev/ksyms"
128*b89261baSDavid van Moolenbroek #define KMEM "/dev/kmem"
129*b89261baSDavid van Moolenbroek #define PROCFS "/proc"
130*b89261baSDavid van Moolenbroek #define CPUSTATES     5
131*b89261baSDavid van Moolenbroek #ifndef PRIO_MIN
132*b89261baSDavid van Moolenbroek #define PRIO_MIN	-20
133*b89261baSDavid van Moolenbroek #endif
134*b89261baSDavid van Moolenbroek #ifndef PRIO_MAX
135*b89261baSDavid van Moolenbroek #define PRIO_MAX	20
136*b89261baSDavid van Moolenbroek #endif
137*b89261baSDavid van Moolenbroek 
138*b89261baSDavid van Moolenbroek #ifndef FSCALE
139*b89261baSDavid van Moolenbroek #define FSHIFT  8		/* bits to right of fixed binary point */
140*b89261baSDavid van Moolenbroek #define FSCALE  (1<<FSHIFT)
141*b89261baSDavid van Moolenbroek #endif /* FSCALE */
142*b89261baSDavid van Moolenbroek 
143*b89261baSDavid van Moolenbroek #define loaddouble(la) ((double)(la) / FSCALE)
144*b89261baSDavid van Moolenbroek #define dbl_align(x)	(((unsigned long)(x)+(sizeof(double)-1)) & \
145*b89261baSDavid van Moolenbroek 						~(sizeof(double)-1))
146*b89261baSDavid van Moolenbroek 
147*b89261baSDavid van Moolenbroek /*
148*b89261baSDavid van Moolenbroek  * SunOS 5.4 and above track pctcpu in the proc structure as pr_pctcpu.
149*b89261baSDavid van Moolenbroek  * These values are weighted over one minute whereas top output prefers
150*b89261baSDavid van Moolenbroek  * a near-instantaneous measure of cpu utilization.  So we choose to
151*b89261baSDavid van Moolenbroek  * ignore pr_pctcpu: we calculate our own cpu percentage and store it in
152*b89261baSDavid van Moolenbroek  * one of the spare slots in the prinfo structure.
153*b89261baSDavid van Moolenbroek  */
154*b89261baSDavid van Moolenbroek 
155*b89261baSDavid van Moolenbroek #define percent_cpu(pp) (*(double *)dbl_align(&pp->pr_filler[0]))
156*b89261baSDavid van Moolenbroek 
157*b89261baSDavid van Moolenbroek /* definitions for indices in the nlist array */
158*b89261baSDavid van Moolenbroek #define X_V			 0
159*b89261baSDavid van Moolenbroek #define X_MPID			 1
160*b89261baSDavid van Moolenbroek #define X_ANONINFO		 2
161*b89261baSDavid van Moolenbroek #define X_MAXMEM		 3
162*b89261baSDavid van Moolenbroek #define X_FREEMEM		 4
163*b89261baSDavid van Moolenbroek #define X_AVENRUN		 5
164*b89261baSDavid van Moolenbroek #define X_CPU			 6
165*b89261baSDavid van Moolenbroek #define X_NPROC			 7
166*b89261baSDavid van Moolenbroek #define X_NCPUS		   	 8
167*b89261baSDavid van Moolenbroek 
168*b89261baSDavid van Moolenbroek static struct nlist nlst[] =
169*b89261baSDavid van Moolenbroek {
170*b89261baSDavid van Moolenbroek   {"v"},			/* 0 */	/* replaced by dynamic allocation */
171*b89261baSDavid van Moolenbroek   {"mpid"},			/* 1 */
172*b89261baSDavid van Moolenbroek #if OSREV >= 56
173*b89261baSDavid van Moolenbroek   /* this structure really has some extra fields, but the first three match */
174*b89261baSDavid van Moolenbroek   {"k_anoninfo"},		/* 2 */
175*b89261baSDavid van Moolenbroek #else
176*b89261baSDavid van Moolenbroek   {"anoninfo"},			/* 2 */
177*b89261baSDavid van Moolenbroek #endif
178*b89261baSDavid van Moolenbroek   {"maxmem"},			/* 3 */ /* use sysconf */
179*b89261baSDavid van Moolenbroek   {"freemem"},			/* 4 */	/* available from kstat >= 2.5 */
180*b89261baSDavid van Moolenbroek   {"avenrun"},			/* 5 */ /* available from kstat */
181*b89261baSDavid van Moolenbroek   {"cpu"},			/* 6 */ /* available from kstat */
182*b89261baSDavid van Moolenbroek   {"nproc"},			/* 7 */ /* available from kstat */
183*b89261baSDavid van Moolenbroek   {"ncpus"},			/* 8 */ /* available from kstat */
184*b89261baSDavid van Moolenbroek   {0}
185*b89261baSDavid van Moolenbroek };
186*b89261baSDavid van Moolenbroek 
187*b89261baSDavid van Moolenbroek static unsigned long avenrun_offset;
188*b89261baSDavid van Moolenbroek static unsigned long mpid_offset;
189*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
190*b89261baSDavid van Moolenbroek static kstat_ctl_t *kc = NULL;
191*b89261baSDavid van Moolenbroek static kid_t kcid = 0;
192*b89261baSDavid van Moolenbroek #else
193*b89261baSDavid van Moolenbroek static unsigned long *cpu_offset;
194*b89261baSDavid van Moolenbroek #endif
195*b89261baSDavid van Moolenbroek static unsigned long nproc_offset;
196*b89261baSDavid van Moolenbroek static unsigned long freemem_offset;
197*b89261baSDavid van Moolenbroek static unsigned long maxmem_offset;
198*b89261baSDavid van Moolenbroek static unsigned long anoninfo_offset;
199*b89261baSDavid van Moolenbroek static int maxfiles = 256;
200*b89261baSDavid van Moolenbroek #define MAXFILES 2048
201*b89261baSDavid van Moolenbroek static int *display_fields;
202*b89261baSDavid van Moolenbroek static int show_threads = 0;
203*b89261baSDavid van Moolenbroek static int show_fullcmd;
204*b89261baSDavid van Moolenbroek 
205*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle.  This is what it looks like: */
206*b89261baSDavid van Moolenbroek struct handle
207*b89261baSDavid van Moolenbroek {
208*b89261baSDavid van Moolenbroek     struct prpsinfo **next_proc;/* points to next valid proc pointer */
209*b89261baSDavid van Moolenbroek     int remaining;		/* number of pointers remaining */
210*b89261baSDavid van Moolenbroek };
211*b89261baSDavid van Moolenbroek 
212*b89261baSDavid van Moolenbroek /*
213*b89261baSDavid van Moolenbroek  * Structure for keeping track processes between updates.
214*b89261baSDavid van Moolenbroek  * We keep these things in a hash table, which is updated at every cycle.
215*b89261baSDavid van Moolenbroek  */
216*b89261baSDavid van Moolenbroek struct oldproc
217*b89261baSDavid van Moolenbroek {
218*b89261baSDavid van Moolenbroek     pid_t pid;
219*b89261baSDavid van Moolenbroek     id_t lwpid;
220*b89261baSDavid van Moolenbroek     double oldtime;
221*b89261baSDavid van Moolenbroek     double oldpct;
222*b89261baSDavid van Moolenbroek     uid_t  owner_uid;
223*b89261baSDavid van Moolenbroek     int fd_psinfo;
224*b89261baSDavid van Moolenbroek     int fd_lpsinfo;
225*b89261baSDavid van Moolenbroek     int seen;
226*b89261baSDavid van Moolenbroek };
227*b89261baSDavid van Moolenbroek 
228*b89261baSDavid van Moolenbroek #define TIMESPEC_TO_DOUBLE(ts) ((ts).tv_sec * 1.0e9 + (ts).tv_nsec)
229*b89261baSDavid van Moolenbroek 
230*b89261baSDavid van Moolenbroek hash_table *prochash;
231*b89261baSDavid van Moolenbroek hash_table *threadhash;
232*b89261baSDavid van Moolenbroek 
233*b89261baSDavid van Moolenbroek /*
234*b89261baSDavid van Moolenbroek  * Structure for tracking per-cpu information
235*b89261baSDavid van Moolenbroek  */
236*b89261baSDavid van Moolenbroek struct cpustats
237*b89261baSDavid van Moolenbroek {
238*b89261baSDavid van Moolenbroek     unsigned int states[CPUSTATES];
239*b89261baSDavid van Moolenbroek     uint_t pswitch;
240*b89261baSDavid van Moolenbroek     uint_t trap;
241*b89261baSDavid van Moolenbroek     uint_t intr;
242*b89261baSDavid van Moolenbroek     uint_t syscall;
243*b89261baSDavid van Moolenbroek     uint_t sysfork;
244*b89261baSDavid van Moolenbroek     uint_t sysvfork;
245*b89261baSDavid van Moolenbroek     uint_t pfault;
246*b89261baSDavid van Moolenbroek     uint_t pgin;
247*b89261baSDavid van Moolenbroek     uint_t pgout;
248*b89261baSDavid van Moolenbroek };
249*b89261baSDavid van Moolenbroek 
250*b89261baSDavid van Moolenbroek /*
251*b89261baSDavid van Moolenbroek  * GCC assumes that all doubles are aligned.  Unfortunately it
252*b89261baSDavid van Moolenbroek  * doesn't round up the structure size to be a multiple of 8.
253*b89261baSDavid van Moolenbroek  * Thus we'll get a coredump when going through array.  The
254*b89261baSDavid van Moolenbroek  * following is a size rounded up to 8.
255*b89261baSDavid van Moolenbroek  */
256*b89261baSDavid van Moolenbroek #define PRPSINFOSIZE dbl_align(sizeof(struct prpsinfo))
257*b89261baSDavid van Moolenbroek 
258*b89261baSDavid van Moolenbroek /* this defines one field (or column) in the process display */
259*b89261baSDavid van Moolenbroek 
260*b89261baSDavid van Moolenbroek struct proc_field {
261*b89261baSDavid van Moolenbroek     char *name;
262*b89261baSDavid van Moolenbroek     int width;
263*b89261baSDavid van Moolenbroek     int rjust;
264*b89261baSDavid van Moolenbroek     int min_screenwidth;
265*b89261baSDavid van Moolenbroek     int (*format)(char *, int, struct prpsinfo *);
266*b89261baSDavid van Moolenbroek };
267*b89261baSDavid van Moolenbroek 
268*b89261baSDavid van Moolenbroek #define PROCSTATES 8
269*b89261baSDavid van Moolenbroek /* process state names for the "STATE" column of the display */
270*b89261baSDavid van Moolenbroek char *state_abbrev[] =
271*b89261baSDavid van Moolenbroek {"", "sleep", "run", "zombie", "stop", "start", "cpu", "swap"};
272*b89261baSDavid van Moolenbroek 
273*b89261baSDavid van Moolenbroek int process_states[PROCSTATES];
274*b89261baSDavid van Moolenbroek char *procstatenames[] =
275*b89261baSDavid van Moolenbroek {
276*b89261baSDavid van Moolenbroek   "", " sleeping, ", " running, ", " zombie, ", " stopped, ",
277*b89261baSDavid van Moolenbroek   " starting, ", " on cpu, ", " swapped, ",
278*b89261baSDavid van Moolenbroek   NULL
279*b89261baSDavid van Moolenbroek };
280*b89261baSDavid van Moolenbroek 
281*b89261baSDavid van Moolenbroek int cpu_states[CPUSTATES];
282*b89261baSDavid van Moolenbroek char *cpustatenames[] =
283*b89261baSDavid van Moolenbroek {"idle", "user", "kernel", "iowait", "swap", NULL};
284*b89261baSDavid van Moolenbroek #define CPUSTATE_IOWAIT 3
285*b89261baSDavid van Moolenbroek #define CPUSTATE_SWAP   4
286*b89261baSDavid van Moolenbroek 
287*b89261baSDavid van Moolenbroek 
288*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
289*b89261baSDavid van Moolenbroek long memory_stats[5];
290*b89261baSDavid van Moolenbroek char *memorynames[] =
291*b89261baSDavid van Moolenbroek {"K phys mem, ", "K free mem, ", "K total swap, ", "K free swap", NULL};
292*b89261baSDavid van Moolenbroek #define MEMORY_TOTALMEM  0
293*b89261baSDavid van Moolenbroek #define MEMORY_FREEMEM   1
294*b89261baSDavid van Moolenbroek #define MEMORY_TOTALSWAP 2
295*b89261baSDavid van Moolenbroek #define MEMORY_FREESWAP  3
296*b89261baSDavid van Moolenbroek 
297*b89261baSDavid van Moolenbroek /* these are for detailing kernel statistics */
298*b89261baSDavid van Moolenbroek int kernel_stats[8];
299*b89261baSDavid van Moolenbroek char *kernelnames[] =
300*b89261baSDavid van Moolenbroek {" ctxsw, ", " trap, ", " intr, ", " syscall, ", " fork, ",
301*b89261baSDavid van Moolenbroek  " flt, ", " pgin, ", " pgout, ", NULL};
302*b89261baSDavid van Moolenbroek #define KERNEL_CSWITCH 0
303*b89261baSDavid van Moolenbroek #define KERNEL_TRAP 1
304*b89261baSDavid van Moolenbroek #define KERNEL_INTR 2
305*b89261baSDavid van Moolenbroek #define KERNEL_SYSCALL 3
306*b89261baSDavid van Moolenbroek #define KERNEL_FORK 4
307*b89261baSDavid van Moolenbroek #define KERNEL_PFAULT 5
308*b89261baSDavid van Moolenbroek #define KERNEL_PGIN 6
309*b89261baSDavid van Moolenbroek #define KERNEL_PGOUT 7
310*b89261baSDavid van Moolenbroek 
311*b89261baSDavid van Moolenbroek /* these are names given to allowed sorting orders -- first is default */
312*b89261baSDavid van Moolenbroek char *ordernames[] =
313*b89261baSDavid van Moolenbroek {"cpu", "size", "res", "time", "pid", NULL};
314*b89261baSDavid van Moolenbroek 
315*b89261baSDavid van Moolenbroek /* forward definitions for comparison functions */
316*b89261baSDavid van Moolenbroek int compare_cpu();
317*b89261baSDavid van Moolenbroek int compare_size();
318*b89261baSDavid van Moolenbroek int compare_res();
319*b89261baSDavid van Moolenbroek int compare_time();
320*b89261baSDavid van Moolenbroek int compare_pid();
321*b89261baSDavid van Moolenbroek 
322*b89261baSDavid van Moolenbroek int (*proc_compares[])() = {
323*b89261baSDavid van Moolenbroek     compare_cpu,
324*b89261baSDavid van Moolenbroek     compare_size,
325*b89261baSDavid van Moolenbroek     compare_res,
326*b89261baSDavid van Moolenbroek     compare_time,
327*b89261baSDavid van Moolenbroek     compare_pid,
328*b89261baSDavid van Moolenbroek     NULL };
329*b89261baSDavid van Moolenbroek 
330*b89261baSDavid van Moolenbroek kvm_t *kd;
331*b89261baSDavid van Moolenbroek static DIR *procdir;
332*b89261baSDavid van Moolenbroek 
333*b89261baSDavid van Moolenbroek /* "cpucount" is used to store the value for the kernel variable "ncpus".
334*b89261baSDavid van Moolenbroek    But since <sys/cpuvar.h> actually defines a variable "ncpus" we need
335*b89261baSDavid van Moolenbroek    to use a different name here.   --wnl */
336*b89261baSDavid van Moolenbroek static int cpucount;
337*b89261baSDavid van Moolenbroek 
338*b89261baSDavid van Moolenbroek /* pagetok function is really a pointer to an appropriate function */
339*b89261baSDavid van Moolenbroek static int pageshift;
340*b89261baSDavid van Moolenbroek static long (*p_pagetok) ();
341*b89261baSDavid van Moolenbroek #define pagetok(size) ((*p_pagetok)(size))
342*b89261baSDavid van Moolenbroek 
343*b89261baSDavid van Moolenbroek /* useful externals */
344*b89261baSDavid van Moolenbroek extern char *myname;
345*b89261baSDavid van Moolenbroek extern void perror ();
346*b89261baSDavid van Moolenbroek extern int getptable ();
347*b89261baSDavid van Moolenbroek extern void quit ();
348*b89261baSDavid van Moolenbroek 
349*b89261baSDavid van Moolenbroek /* process formatting functions and data */
350*b89261baSDavid van Moolenbroek 
351*b89261baSDavid van Moolenbroek int
fmt_pid(char * buf,int sz,struct prpsinfo * pp)352*b89261baSDavid van Moolenbroek fmt_pid(char *buf, int sz, struct prpsinfo *pp)
353*b89261baSDavid van Moolenbroek 
354*b89261baSDavid van Moolenbroek {
355*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%6d", (int)pp->pr_pid);
356*b89261baSDavid van Moolenbroek }
357*b89261baSDavid van Moolenbroek 
358*b89261baSDavid van Moolenbroek int
fmt_username(char * buf,int sz,struct prpsinfo * pp)359*b89261baSDavid van Moolenbroek fmt_username(char *buf, int sz, struct prpsinfo *pp)
360*b89261baSDavid van Moolenbroek 
361*b89261baSDavid van Moolenbroek {
362*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%-8.8s", username(pp->pr_uid));
363*b89261baSDavid van Moolenbroek }
364*b89261baSDavid van Moolenbroek 
365*b89261baSDavid van Moolenbroek int
fmt_uid(char * buf,int sz,struct prpsinfo * pp)366*b89261baSDavid van Moolenbroek fmt_uid(char *buf, int sz, struct prpsinfo *pp)
367*b89261baSDavid van Moolenbroek 
368*b89261baSDavid van Moolenbroek {
369*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%6d", (int)pp->pr_uid);
370*b89261baSDavid van Moolenbroek }
371*b89261baSDavid van Moolenbroek 
372*b89261baSDavid van Moolenbroek int
fmt_nlwp(char * buf,int sz,struct prpsinfo * pp)373*b89261baSDavid van Moolenbroek fmt_nlwp(char *buf, int sz, struct prpsinfo *pp)
374*b89261baSDavid van Moolenbroek 
375*b89261baSDavid van Moolenbroek {
376*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%4d", pp->pr_fill < 999 ? pp->pr_fill: 999);
377*b89261baSDavid van Moolenbroek }
378*b89261baSDavid van Moolenbroek 
379*b89261baSDavid van Moolenbroek int
fmt_pri(char * buf,int sz,struct prpsinfo * pp)380*b89261baSDavid van Moolenbroek fmt_pri(char *buf, int sz, struct prpsinfo *pp)
381*b89261baSDavid van Moolenbroek 
382*b89261baSDavid van Moolenbroek {
383*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%3d", pp->px_pri);
384*b89261baSDavid van Moolenbroek }
385*b89261baSDavid van Moolenbroek 
386*b89261baSDavid van Moolenbroek int
fmt_nice(char * buf,int sz,struct prpsinfo * pp)387*b89261baSDavid van Moolenbroek fmt_nice(char *buf, int sz, struct prpsinfo *pp)
388*b89261baSDavid van Moolenbroek 
389*b89261baSDavid van Moolenbroek {
390*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%4d", pp->px_nice - NZERO);
391*b89261baSDavid van Moolenbroek }
392*b89261baSDavid van Moolenbroek 
393*b89261baSDavid van Moolenbroek int
fmt_size(char * buf,int sz,struct prpsinfo * pp)394*b89261baSDavid van Moolenbroek fmt_size(char *buf, int sz, struct prpsinfo *pp)
395*b89261baSDavid van Moolenbroek 
396*b89261baSDavid van Moolenbroek {
397*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%5s", format_k(SIZE_K(pp)));
398*b89261baSDavid van Moolenbroek }
399*b89261baSDavid van Moolenbroek 
400*b89261baSDavid van Moolenbroek int
fmt_res(char * buf,int sz,struct prpsinfo * pp)401*b89261baSDavid van Moolenbroek fmt_res(char *buf, int sz, struct prpsinfo *pp)
402*b89261baSDavid van Moolenbroek 
403*b89261baSDavid van Moolenbroek {
404*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%5s", format_k(RSS_K(pp)));
405*b89261baSDavid van Moolenbroek }
406*b89261baSDavid van Moolenbroek 
407*b89261baSDavid van Moolenbroek int
fmt_state(char * buf,int sz,struct prpsinfo * pp)408*b89261baSDavid van Moolenbroek fmt_state(char *buf, int sz, struct prpsinfo *pp)
409*b89261baSDavid van Moolenbroek 
410*b89261baSDavid van Moolenbroek {
411*b89261baSDavid van Moolenbroek     if (pp->px_state == SONPROC && cpucount > 1)
412*b89261baSDavid van Moolenbroek     {
413*b89261baSDavid van Moolenbroek 	/* large #s may overflow colums */
414*b89261baSDavid van Moolenbroek 	if (pp->px_onpro < 100)
415*b89261baSDavid van Moolenbroek 	{
416*b89261baSDavid van Moolenbroek 	    return snprintf(buf, sz, "cpu/%-2d", pp->px_onpro);
417*b89261baSDavid van Moolenbroek 	}
418*b89261baSDavid van Moolenbroek 	return snprintf(buf, sz, "cpu/**");
419*b89261baSDavid van Moolenbroek     }
420*b89261baSDavid van Moolenbroek 
421*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%-6s", state_abbrev[(int)pp->px_state]);
422*b89261baSDavid van Moolenbroek }
423*b89261baSDavid van Moolenbroek 
424*b89261baSDavid van Moolenbroek int
fmt_time(char * buf,int sz,struct prpsinfo * pp)425*b89261baSDavid van Moolenbroek fmt_time(char *buf, int sz, struct prpsinfo *pp)
426*b89261baSDavid van Moolenbroek 
427*b89261baSDavid van Moolenbroek {
428*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%6s", format_time(pp->pr_time.tv_sec));
429*b89261baSDavid van Moolenbroek }
430*b89261baSDavid van Moolenbroek 
431*b89261baSDavid van Moolenbroek int
fmt_cpu(char * buf,int sz,struct prpsinfo * pp)432*b89261baSDavid van Moolenbroek fmt_cpu(char *buf, int sz, struct prpsinfo *pp)
433*b89261baSDavid van Moolenbroek 
434*b89261baSDavid van Moolenbroek {
435*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%5s%%",
436*b89261baSDavid van Moolenbroek 		    format_percent(percent_cpu(pp) / cpucount));
437*b89261baSDavid van Moolenbroek }
438*b89261baSDavid van Moolenbroek 
439*b89261baSDavid van Moolenbroek int
fmt_command(char * buf,int sz,struct prpsinfo * pp)440*b89261baSDavid van Moolenbroek fmt_command(char *buf, int sz, struct prpsinfo *pp)
441*b89261baSDavid van Moolenbroek 
442*b89261baSDavid van Moolenbroek {
443*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%s",
444*b89261baSDavid van Moolenbroek 		    printable(show_fullcmd ? pp->pr_psargs : pp->pr_fname));
445*b89261baSDavid van Moolenbroek }
446*b89261baSDavid van Moolenbroek 
447*b89261baSDavid van Moolenbroek int
fmt_lwp(char * buf,int sz,struct prpsinfo * pp)448*b89261baSDavid van Moolenbroek fmt_lwp(char *buf, int sz, struct prpsinfo *pp)
449*b89261baSDavid van Moolenbroek 
450*b89261baSDavid van Moolenbroek {
451*b89261baSDavid van Moolenbroek     return snprintf(buf, sz, "%4d", ((int)pp->pr_lwp.pr_lwpid < 10000 ?
452*b89261baSDavid van Moolenbroek 		(int)pp->pr_lwp.pr_lwpid : 9999));
453*b89261baSDavid van Moolenbroek }
454*b89261baSDavid van Moolenbroek 
455*b89261baSDavid van Moolenbroek struct proc_field proc_field[] = {
456*b89261baSDavid van Moolenbroek     { "PID", 6, 1, 0, fmt_pid },
457*b89261baSDavid van Moolenbroek     { "USERNAME", 8, 0, 0, fmt_username },
458*b89261baSDavid van Moolenbroek #define FIELD_USERNAME 1
459*b89261baSDavid van Moolenbroek     { "UID", 6, 1, 0, fmt_uid },
460*b89261baSDavid van Moolenbroek #define FIELD_UID 2
461*b89261baSDavid van Moolenbroek     { "NLWP", 4, 1, 0, fmt_nlwp },
462*b89261baSDavid van Moolenbroek     { "PRI", 3, 1, 0, fmt_pri },
463*b89261baSDavid van Moolenbroek     { "NICE", 4, 1, 0, fmt_nice },
464*b89261baSDavid van Moolenbroek     { "SIZE", 5, 1, 0, fmt_size },
465*b89261baSDavid van Moolenbroek     { "RES", 5, 1, 0, fmt_res },
466*b89261baSDavid van Moolenbroek     { "STATE", 6, 0, 0, fmt_state },
467*b89261baSDavid van Moolenbroek     { "TIME", 6, 1, 0, fmt_time },
468*b89261baSDavid van Moolenbroek     { "CPU", 6, 1, 0, fmt_cpu },
469*b89261baSDavid van Moolenbroek     { "COMMAND", 7, 0, 0, fmt_command },
470*b89261baSDavid van Moolenbroek     { "LWP", 4, 1, 0, fmt_lwp },
471*b89261baSDavid van Moolenbroek };
472*b89261baSDavid van Moolenbroek #define MAX_FIELDS 13
473*b89261baSDavid van Moolenbroek 
474*b89261baSDavid van Moolenbroek static int proc_display[MAX_FIELDS];
475*b89261baSDavid van Moolenbroek static int thr_display[MAX_FIELDS];
476*b89261baSDavid van Moolenbroek 
477*b89261baSDavid van Moolenbroek int
field_index(char * col)478*b89261baSDavid van Moolenbroek field_index(char *col)
479*b89261baSDavid van Moolenbroek 
480*b89261baSDavid van Moolenbroek {
481*b89261baSDavid van Moolenbroek     struct proc_field *fp;
482*b89261baSDavid van Moolenbroek     int i = 0;
483*b89261baSDavid van Moolenbroek 
484*b89261baSDavid van Moolenbroek     fp = proc_field;
485*b89261baSDavid van Moolenbroek     while (fp->name != NULL)
486*b89261baSDavid van Moolenbroek     {
487*b89261baSDavid van Moolenbroek 	if (strcmp(col, fp->name) == 0)
488*b89261baSDavid van Moolenbroek 	{
489*b89261baSDavid van Moolenbroek 	    return i;
490*b89261baSDavid van Moolenbroek 	}
491*b89261baSDavid van Moolenbroek 	fp++;
492*b89261baSDavid van Moolenbroek 	i++;
493*b89261baSDavid van Moolenbroek     }
494*b89261baSDavid van Moolenbroek 
495*b89261baSDavid van Moolenbroek     return -1;
496*b89261baSDavid van Moolenbroek }
497*b89261baSDavid van Moolenbroek 
498*b89261baSDavid van Moolenbroek void
field_subst(int * fp,int old,int new)499*b89261baSDavid van Moolenbroek field_subst(int *fp, int old, int new)
500*b89261baSDavid van Moolenbroek 
501*b89261baSDavid van Moolenbroek {
502*b89261baSDavid van Moolenbroek     while (*fp != -1)
503*b89261baSDavid van Moolenbroek     {
504*b89261baSDavid van Moolenbroek 	if (*fp == old)
505*b89261baSDavid van Moolenbroek 	{
506*b89261baSDavid van Moolenbroek 	    *fp = new;
507*b89261baSDavid van Moolenbroek 	}
508*b89261baSDavid van Moolenbroek 	fp++;
509*b89261baSDavid van Moolenbroek     }
510*b89261baSDavid van Moolenbroek }
511*b89261baSDavid van Moolenbroek 
512*b89261baSDavid van Moolenbroek /* p_pagetok points to one of the following, depending on which
513*b89261baSDavid van Moolenbroek    direction data has to be shifted: */
514*b89261baSDavid van Moolenbroek 
pagetok_none(long size)515*b89261baSDavid van Moolenbroek long pagetok_none(long size)
516*b89261baSDavid van Moolenbroek 
517*b89261baSDavid van Moolenbroek {
518*b89261baSDavid van Moolenbroek     return(size);
519*b89261baSDavid van Moolenbroek }
520*b89261baSDavid van Moolenbroek 
pagetok_left(long size)521*b89261baSDavid van Moolenbroek long pagetok_left(long size)
522*b89261baSDavid van Moolenbroek 
523*b89261baSDavid van Moolenbroek {
524*b89261baSDavid van Moolenbroek     return(size << pageshift);
525*b89261baSDavid van Moolenbroek }
526*b89261baSDavid van Moolenbroek 
pagetok_right(long size)527*b89261baSDavid van Moolenbroek long pagetok_right(long size)
528*b89261baSDavid van Moolenbroek 
529*b89261baSDavid van Moolenbroek {
530*b89261baSDavid van Moolenbroek     return(size >> pageshift);
531*b89261baSDavid van Moolenbroek }
532*b89261baSDavid van Moolenbroek 
533*b89261baSDavid van Moolenbroek /*
534*b89261baSDavid van Moolenbroek  *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
535*b89261baSDavid van Moolenbroek  *	"offset" is the byte offset into the kernel for the desired value,
536*b89261baSDavid van Moolenbroek  *  	"ptr" points to a buffer into which the value is retrieved,
537*b89261baSDavid van Moolenbroek  *  	"size" is the size of the buffer (and the object to retrieve),
538*b89261baSDavid van Moolenbroek  *  	"refstr" is a reference string used when printing error meessages,
539*b89261baSDavid van Moolenbroek  *	    if "refstr" starts with a '!', then a failure on read will not
540*b89261baSDavid van Moolenbroek  *  	    be fatal (this may seem like a silly way to do things, but I
541*b89261baSDavid van Moolenbroek  *  	    really didn't want the overhead of another argument).
542*b89261baSDavid van Moolenbroek  *
543*b89261baSDavid van Moolenbroek  */
544*b89261baSDavid van Moolenbroek int
getkval(unsigned long offset,int * ptr,int size,char * refstr)545*b89261baSDavid van Moolenbroek getkval (unsigned long offset,
546*b89261baSDavid van Moolenbroek 	 int *ptr,
547*b89261baSDavid van Moolenbroek 	 int size,
548*b89261baSDavid van Moolenbroek 	 char *refstr)
549*b89261baSDavid van Moolenbroek {
550*b89261baSDavid van Moolenbroek     dprintf("getkval(%08x, %08x, %d, %s)\n", offset, ptr, size, refstr);
551*b89261baSDavid van Moolenbroek 
552*b89261baSDavid van Moolenbroek     if (kvm_read (kd, offset, (char *) ptr, size) != size)
553*b89261baSDavid van Moolenbroek     {
554*b89261baSDavid van Moolenbroek 	dprintf("getkval: read failed\n");
555*b89261baSDavid van Moolenbroek 	if (*refstr == '!')
556*b89261baSDavid van Moolenbroek 	{
557*b89261baSDavid van Moolenbroek 	    return (0);
558*b89261baSDavid van Moolenbroek 	}
559*b89261baSDavid van Moolenbroek 	else
560*b89261baSDavid van Moolenbroek 	{
561*b89261baSDavid van Moolenbroek 	    fprintf (stderr, "top: kvm_read for %s: %s\n", refstr, strerror(errno));
562*b89261baSDavid van Moolenbroek 	    quit (23);
563*b89261baSDavid van Moolenbroek 	}
564*b89261baSDavid van Moolenbroek     }
565*b89261baSDavid van Moolenbroek 
566*b89261baSDavid van Moolenbroek     dprintf("getkval read %d (%08x)\n", *ptr);
567*b89261baSDavid van Moolenbroek 
568*b89261baSDavid van Moolenbroek     return (1);
569*b89261baSDavid van Moolenbroek 
570*b89261baSDavid van Moolenbroek }
571*b89261baSDavid van Moolenbroek 
572*b89261baSDavid van Moolenbroek /* procs structure memory management */
573*b89261baSDavid van Moolenbroek 
574*b89261baSDavid van Moolenbroek static struct prpsinfo **allprocs = NULL;
575*b89261baSDavid van Moolenbroek static struct prpsinfo **nextproc = NULL;
576*b89261baSDavid van Moolenbroek static int maxprocs = 0;
577*b89261baSDavid van Moolenbroek static int idxprocs = 0;
578*b89261baSDavid van Moolenbroek 
579*b89261baSDavid van Moolenbroek /*
580*b89261baSDavid van Moolenbroek  * void procs_prealloc(int cnt)
581*b89261baSDavid van Moolenbroek  *
582*b89261baSDavid van Moolenbroek  * Preallocate "cnt" procs structures.  If "cnt" is less than or equal
583*b89261baSDavid van Moolenbroek  * to procs_max() then this function has no effect.
584*b89261baSDavid van Moolenbroek  */
585*b89261baSDavid van Moolenbroek 
586*b89261baSDavid van Moolenbroek void
procs_prealloc(int max)587*b89261baSDavid van Moolenbroek procs_prealloc(int max)
588*b89261baSDavid van Moolenbroek 
589*b89261baSDavid van Moolenbroek {
590*b89261baSDavid van Moolenbroek     int cnt;
591*b89261baSDavid van Moolenbroek     struct prpsinfo *new;
592*b89261baSDavid van Moolenbroek     struct prpsinfo **pp;
593*b89261baSDavid van Moolenbroek 
594*b89261baSDavid van Moolenbroek     cnt = max - maxprocs;
595*b89261baSDavid van Moolenbroek     if (cnt > 0)
596*b89261baSDavid van Moolenbroek     {
597*b89261baSDavid van Moolenbroek 	dprintf("procs_prealloc: need %d, deficit %d\n", max, cnt);
598*b89261baSDavid van Moolenbroek 	allprocs = (struct prpsinfo **)
599*b89261baSDavid van Moolenbroek 	    realloc((void *)allprocs, max * sizeof(struct prpsinfo *));
600*b89261baSDavid van Moolenbroek 	pp = nextproc = allprocs + idxprocs;
601*b89261baSDavid van Moolenbroek 	new = (struct prpsinfo *)malloc(cnt * PRPSINFOSIZE);
602*b89261baSDavid van Moolenbroek 	dprintf("procs_prealloc: idxprocs %d, allprocs %08x, nextproc %08x, new %08x\n",
603*b89261baSDavid van Moolenbroek 		idxprocs, allprocs, nextproc, new);
604*b89261baSDavid van Moolenbroek 	while (--cnt >= 0)
605*b89261baSDavid van Moolenbroek 	{
606*b89261baSDavid van Moolenbroek 	    *pp++ = new;
607*b89261baSDavid van Moolenbroek 	    new = (struct prpsinfo *) ((char *)new + PRPSINFOSIZE);
608*b89261baSDavid van Moolenbroek 	}
609*b89261baSDavid van Moolenbroek 	dprintf("procs_prealloc: done filling at %08x\n", new);
610*b89261baSDavid van Moolenbroek 	maxprocs = max;
611*b89261baSDavid van Moolenbroek     }
612*b89261baSDavid van Moolenbroek }
613*b89261baSDavid van Moolenbroek 
614*b89261baSDavid van Moolenbroek /*
615*b89261baSDavid van Moolenbroek  * struct prpsinfo *procs_next()
616*b89261baSDavid van Moolenbroek  *
617*b89261baSDavid van Moolenbroek  * Return the next available procs structure, allocating a new one
618*b89261baSDavid van Moolenbroek  * if needed.
619*b89261baSDavid van Moolenbroek  */
620*b89261baSDavid van Moolenbroek 
621*b89261baSDavid van Moolenbroek struct prpsinfo *
procs_next()622*b89261baSDavid van Moolenbroek procs_next()
623*b89261baSDavid van Moolenbroek 
624*b89261baSDavid van Moolenbroek {
625*b89261baSDavid van Moolenbroek     if (idxprocs >= maxprocs)
626*b89261baSDavid van Moolenbroek     {
627*b89261baSDavid van Moolenbroek 	/* allocate some more */
628*b89261baSDavid van Moolenbroek 	procs_prealloc(maxprocs + 128);
629*b89261baSDavid van Moolenbroek     }
630*b89261baSDavid van Moolenbroek     idxprocs++;
631*b89261baSDavid van Moolenbroek     return *nextproc++;
632*b89261baSDavid van Moolenbroek }
633*b89261baSDavid van Moolenbroek 
634*b89261baSDavid van Moolenbroek struct prpsinfo *
procs_dup(struct prpsinfo * p)635*b89261baSDavid van Moolenbroek procs_dup(struct prpsinfo *p)
636*b89261baSDavid van Moolenbroek 
637*b89261baSDavid van Moolenbroek {
638*b89261baSDavid van Moolenbroek     struct prpsinfo *n;
639*b89261baSDavid van Moolenbroek 
640*b89261baSDavid van Moolenbroek     n = procs_next();
641*b89261baSDavid van Moolenbroek     memcpy(n, p, PRPSINFOSIZE);
642*b89261baSDavid van Moolenbroek     return n;
643*b89261baSDavid van Moolenbroek }
644*b89261baSDavid van Moolenbroek 
645*b89261baSDavid van Moolenbroek /*
646*b89261baSDavid van Moolenbroek  * struct prpsinfo *procs_start()
647*b89261baSDavid van Moolenbroek  *
648*b89261baSDavid van Moolenbroek  * Return the first procs structure.
649*b89261baSDavid van Moolenbroek  */
650*b89261baSDavid van Moolenbroek 
651*b89261baSDavid van Moolenbroek struct prpsinfo *
procs_start()652*b89261baSDavid van Moolenbroek procs_start()
653*b89261baSDavid van Moolenbroek 
654*b89261baSDavid van Moolenbroek {
655*b89261baSDavid van Moolenbroek     idxprocs = 0;
656*b89261baSDavid van Moolenbroek     nextproc = allprocs;
657*b89261baSDavid van Moolenbroek     return procs_next();
658*b89261baSDavid van Moolenbroek }
659*b89261baSDavid van Moolenbroek 
660*b89261baSDavid van Moolenbroek /*
661*b89261baSDavid van Moolenbroek  * int procs_max()
662*b89261baSDavid van Moolenbroek  *
663*b89261baSDavid van Moolenbroek  * Return the maximum number of procs structures currently allocated.
664*b89261baSDavid van Moolenbroek  */
665*b89261baSDavid van Moolenbroek 
666*b89261baSDavid van Moolenbroek int
procs_max()667*b89261baSDavid van Moolenbroek procs_max()
668*b89261baSDavid van Moolenbroek 
669*b89261baSDavid van Moolenbroek {
670*b89261baSDavid van Moolenbroek     return maxprocs;
671*b89261baSDavid van Moolenbroek }
672*b89261baSDavid van Moolenbroek 
673*b89261baSDavid van Moolenbroek /*
674*b89261baSDavid van Moolenbroek  * check_nlist(nlst) - checks the nlist to see if any symbols were not
675*b89261baSDavid van Moolenbroek  *		found.  For every symbol that was not found, a one-line
676*b89261baSDavid van Moolenbroek  *		message is printed to stderr.  The routine returns the
677*b89261baSDavid van Moolenbroek  *		number of symbols NOT found.
678*b89261baSDavid van Moolenbroek  */
679*b89261baSDavid van Moolenbroek int
check_nlist(register struct nlist * nlst)680*b89261baSDavid van Moolenbroek check_nlist (register struct nlist *nlst)
681*b89261baSDavid van Moolenbroek {
682*b89261baSDavid van Moolenbroek     register int i;
683*b89261baSDavid van Moolenbroek 
684*b89261baSDavid van Moolenbroek     /* check to see if we got ALL the symbols we requested */
685*b89261baSDavid van Moolenbroek     /* this will write one line to stderr for every symbol not found */
686*b89261baSDavid van Moolenbroek 
687*b89261baSDavid van Moolenbroek     i = 0;
688*b89261baSDavid van Moolenbroek     while (nlst->n_name != NULL)
689*b89261baSDavid van Moolenbroek     {
690*b89261baSDavid van Moolenbroek 	if (nlst->n_type == 0)
691*b89261baSDavid van Moolenbroek 	{
692*b89261baSDavid van Moolenbroek 	    /* this one wasn't found */
693*b89261baSDavid van Moolenbroek 	    fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
694*b89261baSDavid van Moolenbroek 	    i = 1;
695*b89261baSDavid van Moolenbroek 	}
696*b89261baSDavid van Moolenbroek 	nlst++;
697*b89261baSDavid van Moolenbroek     }
698*b89261baSDavid van Moolenbroek     return (i);
699*b89261baSDavid van Moolenbroek }
700*b89261baSDavid van Moolenbroek 
701*b89261baSDavid van Moolenbroek 
702*b89261baSDavid van Moolenbroek char *
format_header(register char * uname_field)703*b89261baSDavid van Moolenbroek format_header (register char *uname_field)
704*b89261baSDavid van Moolenbroek {
705*b89261baSDavid van Moolenbroek   return ("");
706*b89261baSDavid van Moolenbroek }
707*b89261baSDavid van Moolenbroek 
708*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
709*b89261baSDavid van Moolenbroek 
710*b89261baSDavid van Moolenbroek long
kstat_data_value_l(kstat_named_t * kn)711*b89261baSDavid van Moolenbroek kstat_data_value_l(kstat_named_t *kn)
712*b89261baSDavid van Moolenbroek 
713*b89261baSDavid van Moolenbroek {
714*b89261baSDavid van Moolenbroek #ifdef KSTAT_DATA_UINT32
715*b89261baSDavid van Moolenbroek     switch(kn->data_type)
716*b89261baSDavid van Moolenbroek     {
717*b89261baSDavid van Moolenbroek     case KSTAT_DATA_INT32:
718*b89261baSDavid van Moolenbroek 	return ((long)(kn->value.i32));
719*b89261baSDavid van Moolenbroek     case KSTAT_DATA_UINT32:
720*b89261baSDavid van Moolenbroek 	return ((long)(kn->value.ui32));
721*b89261baSDavid van Moolenbroek     case KSTAT_DATA_INT64:
722*b89261baSDavid van Moolenbroek 	return ((long)(kn->value.i64));
723*b89261baSDavid van Moolenbroek     case KSTAT_DATA_UINT64:
724*b89261baSDavid van Moolenbroek 	return ((long)(kn->value.ui64));
725*b89261baSDavid van Moolenbroek     }
726*b89261baSDavid van Moolenbroek     return 0;
727*b89261baSDavid van Moolenbroek #else
728*b89261baSDavid van Moolenbroek     return ((long)(kn->value.ui32));
729*b89261baSDavid van Moolenbroek #endif
730*b89261baSDavid van Moolenbroek }
731*b89261baSDavid van Moolenbroek 
732*b89261baSDavid van Moolenbroek int
kstat_safe_retrieve(kstat_t ** ksp,char * module,int instance,char * name,void * buf)733*b89261baSDavid van Moolenbroek kstat_safe_retrieve(kstat_t **ksp,
734*b89261baSDavid van Moolenbroek 		    char *module, int instance, char *name, void *buf)
735*b89261baSDavid van Moolenbroek 
736*b89261baSDavid van Moolenbroek {
737*b89261baSDavid van Moolenbroek     kstat_t *ks;
738*b89261baSDavid van Moolenbroek     kid_t new_kcid;
739*b89261baSDavid van Moolenbroek     int changed;
740*b89261baSDavid van Moolenbroek 
741*b89261baSDavid van Moolenbroek     dprintf("kstat_safe_retrieve(%08x -> %08x, %s, %d, %s, %08x)\n",
742*b89261baSDavid van Moolenbroek 	    ksp, *ksp, module, instance, name, buf);
743*b89261baSDavid van Moolenbroek 
744*b89261baSDavid van Moolenbroek     ks = *ksp;
745*b89261baSDavid van Moolenbroek     do {
746*b89261baSDavid van Moolenbroek 	changed = 0;
747*b89261baSDavid van Moolenbroek 	/* if we dont already have the kstat, retrieve it */
748*b89261baSDavid van Moolenbroek 	if (ks == NULL)
749*b89261baSDavid van Moolenbroek 	{
750*b89261baSDavid van Moolenbroek 	    if ((ks = kstat_lookup(kc, module, instance, name)) == NULL)
751*b89261baSDavid van Moolenbroek 	    {
752*b89261baSDavid van Moolenbroek 		return (-1);
753*b89261baSDavid van Moolenbroek 	    }
754*b89261baSDavid van Moolenbroek 	    *ksp = ks;
755*b89261baSDavid van Moolenbroek 	}
756*b89261baSDavid van Moolenbroek 
757*b89261baSDavid van Moolenbroek 	/* attempt to read it */
758*b89261baSDavid van Moolenbroek 	new_kcid = kstat_read(kc, ks, buf);
759*b89261baSDavid van Moolenbroek 	/* chance for an infinite loop here if kstat_read keeps
760*b89261baSDavid van Moolenbroek 	   returning -1 */
761*b89261baSDavid van Moolenbroek 
762*b89261baSDavid van Moolenbroek 	/* if the chain changed, update it */
763*b89261baSDavid van Moolenbroek 	if (new_kcid != kcid)
764*b89261baSDavid van Moolenbroek 	{
765*b89261baSDavid van Moolenbroek 	    dprintf("kstat_safe_retrieve: chain changed to %d...updating\n",
766*b89261baSDavid van Moolenbroek 		    new_kcid);
767*b89261baSDavid van Moolenbroek 	    changed = 1;
768*b89261baSDavid van Moolenbroek 	    kcid = kstat_chain_update(kc);
769*b89261baSDavid van Moolenbroek 	}
770*b89261baSDavid van Moolenbroek     } while (changed);
771*b89261baSDavid van Moolenbroek 
772*b89261baSDavid van Moolenbroek     return (0);
773*b89261baSDavid van Moolenbroek }
774*b89261baSDavid van Moolenbroek 
775*b89261baSDavid van Moolenbroek /*
776*b89261baSDavid van Moolenbroek  * int kstat_safe_namematch(int num, kstat_t *ksp, char *name, void *buf)
777*b89261baSDavid van Moolenbroek  *
778*b89261baSDavid van Moolenbroek  * Safe scan of kstat chain for names starting with "name".  Matches
779*b89261baSDavid van Moolenbroek  * are copied in to "ksp", and kstat_read is called on each match using
780*b89261baSDavid van Moolenbroek  * "buf" as a buffer of length "size".  The actual number of records
781*b89261baSDavid van Moolenbroek  * found is returned.  Up to "num" kstats are copied in to "ksp", but
782*b89261baSDavid van Moolenbroek  * no more.  If any kstat_read indicates that the chain has changed, then
783*b89261baSDavid van Moolenbroek  * the whole process is restarted.
784*b89261baSDavid van Moolenbroek  */
785*b89261baSDavid van Moolenbroek 
786*b89261baSDavid van Moolenbroek int
kstat_safe_namematch(int num,kstat_t ** ksparg,char * name,void * buf,int size)787*b89261baSDavid van Moolenbroek kstat_safe_namematch(int num, kstat_t **ksparg, char *name, void *buf, int size)
788*b89261baSDavid van Moolenbroek 
789*b89261baSDavid van Moolenbroek {
790*b89261baSDavid van Moolenbroek     kstat_t *ks;
791*b89261baSDavid van Moolenbroek     kstat_t **ksp;
792*b89261baSDavid van Moolenbroek     kid_t new_kcid;
793*b89261baSDavid van Moolenbroek     int namelen;
794*b89261baSDavid van Moolenbroek     int count;
795*b89261baSDavid van Moolenbroek     int changed;
796*b89261baSDavid van Moolenbroek     char *cbuf;
797*b89261baSDavid van Moolenbroek 
798*b89261baSDavid van Moolenbroek     dprintf("kstat_safe_namematch(%d, %08x, %s, %08x, %d)\n",
799*b89261baSDavid van Moolenbroek 	    num, ksparg, name, buf, size);
800*b89261baSDavid van Moolenbroek 
801*b89261baSDavid van Moolenbroek     namelen = strlen(name);
802*b89261baSDavid van Moolenbroek 
803*b89261baSDavid van Moolenbroek     do {
804*b89261baSDavid van Moolenbroek 	/* initialize before the scan */
805*b89261baSDavid van Moolenbroek 	cbuf = (char *)buf;
806*b89261baSDavid van Moolenbroek 	ksp = ksparg;
807*b89261baSDavid van Moolenbroek 	count = 0;
808*b89261baSDavid van Moolenbroek 	changed = 0;
809*b89261baSDavid van Moolenbroek 
810*b89261baSDavid van Moolenbroek 	/* scan the chain for matching kstats */
811*b89261baSDavid van Moolenbroek 	for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next)
812*b89261baSDavid van Moolenbroek 	{
813*b89261baSDavid van Moolenbroek 	    if (strncmp(ks->ks_name, name, namelen) == 0)
814*b89261baSDavid van Moolenbroek 	    {
815*b89261baSDavid van Moolenbroek 		/* this kstat matches: save it if there is room */
816*b89261baSDavid van Moolenbroek 		if (count++ < num)
817*b89261baSDavid van Moolenbroek 		{
818*b89261baSDavid van Moolenbroek 		    /* read the kstat */
819*b89261baSDavid van Moolenbroek 		    new_kcid = kstat_read(kc, ks, cbuf);
820*b89261baSDavid van Moolenbroek 
821*b89261baSDavid van Moolenbroek 		    /* if the chain changed, update it */
822*b89261baSDavid van Moolenbroek 		    if (new_kcid != kcid)
823*b89261baSDavid van Moolenbroek 		    {
824*b89261baSDavid van Moolenbroek 			dprintf("kstat_safe_namematch: chain changed to %d...updating\n",
825*b89261baSDavid van Moolenbroek 				new_kcid);
826*b89261baSDavid van Moolenbroek 			changed = 1;
827*b89261baSDavid van Moolenbroek 			kcid = kstat_chain_update(kc);
828*b89261baSDavid van Moolenbroek 
829*b89261baSDavid van Moolenbroek 			/* there's no sense in continuing the scan */
830*b89261baSDavid van Moolenbroek 			/* so break out of the for loop */
831*b89261baSDavid van Moolenbroek 			break;
832*b89261baSDavid van Moolenbroek 		    }
833*b89261baSDavid van Moolenbroek 
834*b89261baSDavid van Moolenbroek 		    /* move to the next buffers */
835*b89261baSDavid van Moolenbroek 		    cbuf += size;
836*b89261baSDavid van Moolenbroek 		    *ksp++ = ks;
837*b89261baSDavid van Moolenbroek 		}
838*b89261baSDavid van Moolenbroek 	    }
839*b89261baSDavid van Moolenbroek 	}
840*b89261baSDavid van Moolenbroek     } while(changed);
841*b89261baSDavid van Moolenbroek 
842*b89261baSDavid van Moolenbroek     dprintf("kstat_safe_namematch returns %d\n", count);
843*b89261baSDavid van Moolenbroek 
844*b89261baSDavid van Moolenbroek     return count;
845*b89261baSDavid van Moolenbroek }
846*b89261baSDavid van Moolenbroek 
847*b89261baSDavid van Moolenbroek static kstat_t *ks_system_misc = NULL;
848*b89261baSDavid van Moolenbroek 
849*b89261baSDavid van Moolenbroek #endif /* USE_KSTAT */
850*b89261baSDavid van Moolenbroek 
851*b89261baSDavid van Moolenbroek 
852*b89261baSDavid van Moolenbroek int
get_avenrun(int avenrun[3])853*b89261baSDavid van Moolenbroek get_avenrun(int avenrun[3])
854*b89261baSDavid van Moolenbroek 
855*b89261baSDavid van Moolenbroek {
856*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
857*b89261baSDavid van Moolenbroek     int status;
858*b89261baSDavid van Moolenbroek     kstat_named_t *kn;
859*b89261baSDavid van Moolenbroek 
860*b89261baSDavid van Moolenbroek     dprintf("get_avenrun(%08x)\n", avenrun);
861*b89261baSDavid van Moolenbroek 
862*b89261baSDavid van Moolenbroek     if ((status = kstat_safe_retrieve(&ks_system_misc,
863*b89261baSDavid van Moolenbroek 				      "unix", 0, "system_misc", NULL)) == 0)
864*b89261baSDavid van Moolenbroek     {
865*b89261baSDavid van Moolenbroek 	if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_1min")) != NULL)
866*b89261baSDavid van Moolenbroek 	{
867*b89261baSDavid van Moolenbroek 	    avenrun[0] = kn->value.ui32;
868*b89261baSDavid van Moolenbroek 	}
869*b89261baSDavid van Moolenbroek 	if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_5min")) != NULL)
870*b89261baSDavid van Moolenbroek 	{
871*b89261baSDavid van Moolenbroek 	    avenrun[1] = kn->value.ui32;
872*b89261baSDavid van Moolenbroek 	}
873*b89261baSDavid van Moolenbroek 	if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_15min")) != NULL)
874*b89261baSDavid van Moolenbroek 	{
875*b89261baSDavid van Moolenbroek 	    avenrun[2] = kn->value.ui32;
876*b89261baSDavid van Moolenbroek 	}
877*b89261baSDavid van Moolenbroek     }
878*b89261baSDavid van Moolenbroek     dprintf("get_avenrun returns %d\n", status);
879*b89261baSDavid van Moolenbroek     return (status);
880*b89261baSDavid van Moolenbroek 
881*b89261baSDavid van Moolenbroek #else /* !USE_KSTAT */
882*b89261baSDavid van Moolenbroek 
883*b89261baSDavid van Moolenbroek     (void) getkval (avenrun_offset, (int *) avenrun, sizeof (int [3]), "avenrun");
884*b89261baSDavid van Moolenbroek 
885*b89261baSDavid van Moolenbroek     return 0;
886*b89261baSDavid van Moolenbroek 
887*b89261baSDavid van Moolenbroek #endif /* USE_KSTAT */
888*b89261baSDavid van Moolenbroek }
889*b89261baSDavid van Moolenbroek 
890*b89261baSDavid van Moolenbroek int
get_ncpus()891*b89261baSDavid van Moolenbroek get_ncpus()
892*b89261baSDavid van Moolenbroek 
893*b89261baSDavid van Moolenbroek {
894*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
895*b89261baSDavid van Moolenbroek     kstat_named_t *kn;
896*b89261baSDavid van Moolenbroek     int ret = -1;
897*b89261baSDavid van Moolenbroek 
898*b89261baSDavid van Moolenbroek     if ((kn = kstat_data_lookup(ks_system_misc, "ncpus")) != NULL)
899*b89261baSDavid van Moolenbroek     {
900*b89261baSDavid van Moolenbroek 	ret = (int)(kn->value.ui32);
901*b89261baSDavid van Moolenbroek     }
902*b89261baSDavid van Moolenbroek 
903*b89261baSDavid van Moolenbroek     return ret;
904*b89261baSDavid van Moolenbroek #else
905*b89261baSDavid van Moolenbroek     int ret;
906*b89261baSDavid van Moolenbroek 
907*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_NCPUS].n_value, (int *)(&ret), sizeof(ret), "ncpus");
908*b89261baSDavid van Moolenbroek     return ret;
909*b89261baSDavid van Moolenbroek #endif
910*b89261baSDavid van Moolenbroek }
911*b89261baSDavid van Moolenbroek 
912*b89261baSDavid van Moolenbroek int
get_nproc()913*b89261baSDavid van Moolenbroek get_nproc()
914*b89261baSDavid van Moolenbroek 
915*b89261baSDavid van Moolenbroek {
916*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
917*b89261baSDavid van Moolenbroek     kstat_named_t *kn;
918*b89261baSDavid van Moolenbroek     int ret = -1;
919*b89261baSDavid van Moolenbroek 
920*b89261baSDavid van Moolenbroek     if ((kn = kstat_data_lookup(ks_system_misc, "nproc")) != NULL)
921*b89261baSDavid van Moolenbroek     {
922*b89261baSDavid van Moolenbroek 	ret = (int)(kn->value.ui32);
923*b89261baSDavid van Moolenbroek     }
924*b89261baSDavid van Moolenbroek #else
925*b89261baSDavid van Moolenbroek     int ret;
926*b89261baSDavid van Moolenbroek 
927*b89261baSDavid van Moolenbroek     (void) getkval (nproc_offset, (int *) (&ret), sizeof (ret), "nproc");
928*b89261baSDavid van Moolenbroek #endif
929*b89261baSDavid van Moolenbroek 
930*b89261baSDavid van Moolenbroek     dprintf("get_nproc returns %d\n", ret);
931*b89261baSDavid van Moolenbroek     return ret;
932*b89261baSDavid van Moolenbroek }
933*b89261baSDavid van Moolenbroek 
934*b89261baSDavid van Moolenbroek struct cpustats *
get_cpustats(int * cnt,struct cpustats * cpustats)935*b89261baSDavid van Moolenbroek get_cpustats(int *cnt, struct cpustats *cpustats)
936*b89261baSDavid van Moolenbroek 
937*b89261baSDavid van Moolenbroek {
938*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
939*b89261baSDavid van Moolenbroek     static kstat_t **cpu_ks = NULL;
940*b89261baSDavid van Moolenbroek     static cpu_stat_t *cpu_stat = NULL;
941*b89261baSDavid van Moolenbroek     static unsigned int nelems = 0;
942*b89261baSDavid van Moolenbroek     cpu_stat_t *cpu_stat_p;
943*b89261baSDavid van Moolenbroek     int i, cpu_num;
944*b89261baSDavid van Moolenbroek     struct cpustats *cpustats_p;
945*b89261baSDavid van Moolenbroek 
946*b89261baSDavid van Moolenbroek     dprintf("get_cpustats(%d -> %d, %08x)\n", cnt, *cnt, cpustats);
947*b89261baSDavid van Moolenbroek 
948*b89261baSDavid van Moolenbroek     while (nelems > 0 ?
949*b89261baSDavid van Moolenbroek 	   (cpu_num = kstat_safe_namematch(nelems,
950*b89261baSDavid van Moolenbroek 					   cpu_ks,
951*b89261baSDavid van Moolenbroek 					   "cpu_stat",
952*b89261baSDavid van Moolenbroek 					   cpu_stat,
953*b89261baSDavid van Moolenbroek 					   sizeof(cpu_stat_t))) > nelems :
954*b89261baSDavid van Moolenbroek 	   (cpu_num = get_ncpus()) > 0)
955*b89261baSDavid van Moolenbroek     {
956*b89261baSDavid van Moolenbroek 	/* reallocate the arrays */
957*b89261baSDavid van Moolenbroek 	dprintf("realloc from %d to %d\n", nelems, cpu_num);
958*b89261baSDavid van Moolenbroek 	nelems = cpu_num;
959*b89261baSDavid van Moolenbroek 	if (cpu_ks != NULL)
960*b89261baSDavid van Moolenbroek 	{
961*b89261baSDavid van Moolenbroek 	    free(cpu_ks);
962*b89261baSDavid van Moolenbroek 	}
963*b89261baSDavid van Moolenbroek 	cpu_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
964*b89261baSDavid van Moolenbroek 	if (cpu_stat != NULL)
965*b89261baSDavid van Moolenbroek 	{
966*b89261baSDavid van Moolenbroek 	    free(cpu_stat);
967*b89261baSDavid van Moolenbroek 	}
968*b89261baSDavid van Moolenbroek 	cpu_stat = (cpu_stat_t *)malloc(nelems * sizeof(cpu_stat_t));
969*b89261baSDavid van Moolenbroek     }
970*b89261baSDavid van Moolenbroek 
971*b89261baSDavid van Moolenbroek     /* do we have more cpus than our caller? */
972*b89261baSDavid van Moolenbroek     if (cpu_num > *cnt)
973*b89261baSDavid van Moolenbroek     {
974*b89261baSDavid van Moolenbroek 	/* yes, so realloc their array, too */
975*b89261baSDavid van Moolenbroek 	dprintf("realloc array from %d to %d\n", *cnt, cpu_num);
976*b89261baSDavid van Moolenbroek 	*cnt = cpu_num;
977*b89261baSDavid van Moolenbroek 	cpustats = (struct cpustats *)realloc(cpustats,
978*b89261baSDavid van Moolenbroek 					      cpu_num * sizeof(struct cpustats));
979*b89261baSDavid van Moolenbroek     }
980*b89261baSDavid van Moolenbroek 
981*b89261baSDavid van Moolenbroek     cpu_stat_p = cpu_stat;
982*b89261baSDavid van Moolenbroek     cpustats_p = cpustats;
983*b89261baSDavid van Moolenbroek     for (i = 0; i < cpu_num; i++)
984*b89261baSDavid van Moolenbroek     {
985*b89261baSDavid van Moolenbroek 	dprintf("cpu %d %08x: idle %u, user %u, syscall %u\n", i, cpu_stat_p,
986*b89261baSDavid van Moolenbroek 		cpu_stat_p->cpu_sysinfo.cpu[0],
987*b89261baSDavid van Moolenbroek 		cpu_stat_p->cpu_sysinfo.cpu[1],
988*b89261baSDavid van Moolenbroek 		cpu_stat_p->cpu_sysinfo.syscall);
989*b89261baSDavid van Moolenbroek 
990*b89261baSDavid van Moolenbroek 	cpustats_p->states[CPU_IDLE] = cpu_stat_p->cpu_sysinfo.cpu[CPU_IDLE];
991*b89261baSDavid van Moolenbroek 	cpustats_p->states[CPU_USER] = cpu_stat_p->cpu_sysinfo.cpu[CPU_USER];
992*b89261baSDavid van Moolenbroek 	cpustats_p->states[CPU_KERNEL] = cpu_stat_p->cpu_sysinfo.cpu[CPU_KERNEL];
993*b89261baSDavid van Moolenbroek 	cpustats_p->states[CPUSTATE_IOWAIT] = cpu_stat_p->cpu_sysinfo.wait[W_IO] +
994*b89261baSDavid van Moolenbroek 	    cpu_stat_p->cpu_sysinfo.wait[W_PIO];
995*b89261baSDavid van Moolenbroek 	cpustats_p->states[CPUSTATE_SWAP] = cpu_stat_p->cpu_sysinfo.wait[W_SWAP];
996*b89261baSDavid van Moolenbroek 	cpustats_p->pswitch = cpu_stat_p->cpu_sysinfo.pswitch;
997*b89261baSDavid van Moolenbroek 	cpustats_p->trap = cpu_stat_p->cpu_sysinfo.trap;
998*b89261baSDavid van Moolenbroek 	cpustats_p->intr = cpu_stat_p->cpu_sysinfo.intr;
999*b89261baSDavid van Moolenbroek 	cpustats_p->syscall = cpu_stat_p->cpu_sysinfo.syscall;
1000*b89261baSDavid van Moolenbroek 	cpustats_p->sysfork = cpu_stat_p->cpu_sysinfo.sysfork;
1001*b89261baSDavid van Moolenbroek 	cpustats_p->sysvfork = cpu_stat_p->cpu_sysinfo.sysvfork;
1002*b89261baSDavid van Moolenbroek 	cpustats_p->pfault = cpu_stat_p->cpu_vminfo.hat_fault +
1003*b89261baSDavid van Moolenbroek 	    cpu_stat_p->cpu_vminfo.as_fault;
1004*b89261baSDavid van Moolenbroek 	cpustats_p->pgin = cpu_stat_p->cpu_vminfo.pgin;
1005*b89261baSDavid van Moolenbroek 	cpustats_p->pgout = cpu_stat_p->cpu_vminfo.pgout;
1006*b89261baSDavid van Moolenbroek 	cpustats_p++;
1007*b89261baSDavid van Moolenbroek 	cpu_stat_p++;
1008*b89261baSDavid van Moolenbroek     }
1009*b89261baSDavid van Moolenbroek 
1010*b89261baSDavid van Moolenbroek     cpucount = cpu_num;
1011*b89261baSDavid van Moolenbroek 
1012*b89261baSDavid van Moolenbroek     dprintf("get_cpustats sees %d cpus and returns %08x\n", cpucount, cpustats);
1013*b89261baSDavid van Moolenbroek 
1014*b89261baSDavid van Moolenbroek     return (cpustats);
1015*b89261baSDavid van Moolenbroek #else /* !USE_KSTAT */
1016*b89261baSDavid van Moolenbroek     int i;
1017*b89261baSDavid van Moolenbroek     struct cpu cpu;
1018*b89261baSDavid van Moolenbroek     unsigned int (*cp_stats_p)[CPUSTATES];
1019*b89261baSDavid van Moolenbroek 
1020*b89261baSDavid van Moolenbroek     /* do we have more cpus than our caller? */
1021*b89261baSDavid van Moolenbroek     if (cpucount > *cnt)
1022*b89261baSDavid van Moolenbroek     {
1023*b89261baSDavid van Moolenbroek 	/* yes, so realloc their array, too */
1024*b89261baSDavid van Moolenbroek 	dprintf("realloc array from %d to %d\n", *cnt, cpucount);
1025*b89261baSDavid van Moolenbroek 	*cnt = cpucount;
1026*b89261baSDavid van Moolenbroek 	cp_stats = (unsigned int (*)[CPUSTATES])realloc(cp_stats,
1027*b89261baSDavid van Moolenbroek 			 cpucount * sizeof(unsigned int) * CPUSTATES);
1028*b89261baSDavid van Moolenbroek     }
1029*b89261baSDavid van Moolenbroek 
1030*b89261baSDavid van Moolenbroek     cp_stats_p = cp_stats;
1031*b89261baSDavid van Moolenbroek     for (i = 0; i < cpucount; i++)
1032*b89261baSDavid van Moolenbroek     {
1033*b89261baSDavid van Moolenbroek 	if (cpu_offset[i] != 0)
1034*b89261baSDavid van Moolenbroek 	{
1035*b89261baSDavid van Moolenbroek 	    /* get struct cpu for this processor */
1036*b89261baSDavid van Moolenbroek 	    (void) getkval (cpu_offset[i], (int *)(&cpu), sizeof (struct cpu), "cpu");
1037*b89261baSDavid van Moolenbroek 
1038*b89261baSDavid van Moolenbroek 	    (*cp_stats_p)[CPU_IDLE] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_IDLE];
1039*b89261baSDavid van Moolenbroek 	    (*cp_stats_p)[CPU_USER] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_USER];
1040*b89261baSDavid van Moolenbroek 	    (*cp_stats_p)[CPU_KERNEL] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_KERNEL];
1041*b89261baSDavid van Moolenbroek 	    (*cp_stats_p)[CPUSTATE_IOWAIT] = cpu.cpu_stat.cpu_sysinfo.wait[W_IO] +
1042*b89261baSDavid van Moolenbroek 		cpu.cpu_stat.cpu_sysinfo.wait[W_PIO];
1043*b89261baSDavid van Moolenbroek 	    (*cp_stats_p)[CPUSTATE_SWAP] = cpu.cpu_stat.cpu_sysinfo.wait[W_SWAP];
1044*b89261baSDavid van Moolenbroek 	    cp_stats_p++;
1045*b89261baSDavid van Moolenbroek 	}
1046*b89261baSDavid van Moolenbroek     }
1047*b89261baSDavid van Moolenbroek 
1048*b89261baSDavid van Moolenbroek     return (cp_stats);
1049*b89261baSDavid van Moolenbroek #endif /* USE_KSTAT */
1050*b89261baSDavid van Moolenbroek }
1051*b89261baSDavid van Moolenbroek 
1052*b89261baSDavid van Moolenbroek /*
1053*b89261baSDavid van Moolenbroek  * void get_meminfo(long *total, long *fr)
1054*b89261baSDavid van Moolenbroek  *
1055*b89261baSDavid van Moolenbroek  * Get information about the system's physical memory.  Pass back values
1056*b89261baSDavid van Moolenbroek  * for total available and amount of memory that is free (in kilobytes).
1057*b89261baSDavid van Moolenbroek  * It returns 0 on success and -1 on any kind of failure.
1058*b89261baSDavid van Moolenbroek  */
1059*b89261baSDavid van Moolenbroek 
1060*b89261baSDavid van Moolenbroek int
get_meminfo(long * total,long * fr)1061*b89261baSDavid van Moolenbroek get_meminfo(long *total, long *fr)
1062*b89261baSDavid van Moolenbroek 
1063*b89261baSDavid van Moolenbroek {
1064*b89261baSDavid van Moolenbroek     long freemem;
1065*b89261baSDavid van Moolenbroek     static kstat_t *ks = NULL;
1066*b89261baSDavid van Moolenbroek     kstat_named_t *kn;
1067*b89261baSDavid van Moolenbroek 
1068*b89261baSDavid van Moolenbroek     /* total comes from sysconf */
1069*b89261baSDavid van Moolenbroek     *total = pagetok(sysconf(_SC_PHYS_PAGES));
1070*b89261baSDavid van Moolenbroek 
1071*b89261baSDavid van Moolenbroek     /* free comes from the kernel's freemem or from kstat */
1072*b89261baSDavid van Moolenbroek     /* prefer kmem for this because kstat unix:0:system_pages
1073*b89261baSDavid van Moolenbroek        can be slow on systems with lots of memory */
1074*b89261baSDavid van Moolenbroek     if (kd)
1075*b89261baSDavid van Moolenbroek     {
1076*b89261baSDavid van Moolenbroek 	(void) getkval(freemem_offset, (int *)(&freemem), sizeof(freemem),
1077*b89261baSDavid van Moolenbroek 		       "freemem");
1078*b89261baSDavid van Moolenbroek     }
1079*b89261baSDavid van Moolenbroek     else
1080*b89261baSDavid van Moolenbroek     {
1081*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
1082*b89261baSDavid van Moolenbroek 	/* only need to grab kstat chain once */
1083*b89261baSDavid van Moolenbroek 	if (ks == NULL)
1084*b89261baSDavid van Moolenbroek 	{
1085*b89261baSDavid van Moolenbroek 	    ks = kstat_lookup(kc, "unix", 0, "system_pages");
1086*b89261baSDavid van Moolenbroek 	}
1087*b89261baSDavid van Moolenbroek 
1088*b89261baSDavid van Moolenbroek 	if (ks != NULL &&
1089*b89261baSDavid van Moolenbroek 	    kstat_read(kc, ks, 0) != -1 &&
1090*b89261baSDavid van Moolenbroek 	    (kn = kstat_data_lookup(ks, "freemem")) != NULL)
1091*b89261baSDavid van Moolenbroek 	{
1092*b89261baSDavid van Moolenbroek 	    freemem = kstat_data_value_l(kn);
1093*b89261baSDavid van Moolenbroek 	}
1094*b89261baSDavid van Moolenbroek 	else
1095*b89261baSDavid van Moolenbroek 	{
1096*b89261baSDavid van Moolenbroek 	    freemem = -1;
1097*b89261baSDavid van Moolenbroek 	}
1098*b89261baSDavid van Moolenbroek #else
1099*b89261baSDavid van Moolenbroek 	freemem = -1;
1100*b89261baSDavid van Moolenbroek #endif
1101*b89261baSDavid van Moolenbroek     }
1102*b89261baSDavid van Moolenbroek 
1103*b89261baSDavid van Moolenbroek     *fr = freemem == -1 ? -1 : pagetok(freemem);
1104*b89261baSDavid van Moolenbroek 
1105*b89261baSDavid van Moolenbroek     return (0);
1106*b89261baSDavid van Moolenbroek }
1107*b89261baSDavid van Moolenbroek 
1108*b89261baSDavid van Moolenbroek /*
1109*b89261baSDavid van Moolenbroek  * void get_swapinfo(long *total, long *fr)
1110*b89261baSDavid van Moolenbroek  *
1111*b89261baSDavid van Moolenbroek  * Get information about the system's swap.  Pass back values for
1112*b89261baSDavid van Moolenbroek  * total swap available and amount of swap that is free (in kilobytes).
1113*b89261baSDavid van Moolenbroek  * It returns 0 on success and -1 on any kind of failure.
1114*b89261baSDavid van Moolenbroek  */
1115*b89261baSDavid van Moolenbroek 
1116*b89261baSDavid van Moolenbroek int
get_swapinfo(long * total,long * fr)1117*b89261baSDavid van Moolenbroek get_swapinfo(long *total, long *fr)
1118*b89261baSDavid van Moolenbroek 
1119*b89261baSDavid van Moolenbroek {
1120*b89261baSDavid van Moolenbroek     register int cnt, i;
1121*b89261baSDavid van Moolenbroek     register long t, f;
1122*b89261baSDavid van Moolenbroek     struct swaptable *swt;
1123*b89261baSDavid van Moolenbroek     struct swapent *ste;
1124*b89261baSDavid van Moolenbroek     static char path[256];
1125*b89261baSDavid van Moolenbroek 
1126*b89261baSDavid van Moolenbroek     /* preset values to 0 just in case we have to return early */
1127*b89261baSDavid van Moolenbroek     *total = 0;
1128*b89261baSDavid van Moolenbroek     *fr = 0;
1129*b89261baSDavid van Moolenbroek 
1130*b89261baSDavid van Moolenbroek     /* get total number of swap entries */
1131*b89261baSDavid van Moolenbroek     if ((cnt = swapctl(SC_GETNSWP, 0)) == -1)
1132*b89261baSDavid van Moolenbroek     {
1133*b89261baSDavid van Moolenbroek 	return (-1);
1134*b89261baSDavid van Moolenbroek     }
1135*b89261baSDavid van Moolenbroek 
1136*b89261baSDavid van Moolenbroek     /* allocate enough space to hold count + n swapents */
1137*b89261baSDavid van Moolenbroek     swt = (struct swaptable *)malloc(sizeof(int) +
1138*b89261baSDavid van Moolenbroek 				     cnt * sizeof(struct swapent));
1139*b89261baSDavid van Moolenbroek     if (swt == NULL)
1140*b89261baSDavid van Moolenbroek     {
1141*b89261baSDavid van Moolenbroek 	return (-1);
1142*b89261baSDavid van Moolenbroek     }
1143*b89261baSDavid van Moolenbroek     swt->swt_n = cnt;
1144*b89261baSDavid van Moolenbroek 
1145*b89261baSDavid van Moolenbroek     /* fill in ste_path pointers: we don't care about the paths, so we point
1146*b89261baSDavid van Moolenbroek        them all to the same buffer */
1147*b89261baSDavid van Moolenbroek     ste = &(swt->swt_ent[0]);
1148*b89261baSDavid van Moolenbroek     i = cnt;
1149*b89261baSDavid van Moolenbroek     while (--i >= 0)
1150*b89261baSDavid van Moolenbroek     {
1151*b89261baSDavid van Moolenbroek 	ste++->ste_path = path;
1152*b89261baSDavid van Moolenbroek     }
1153*b89261baSDavid van Moolenbroek 
1154*b89261baSDavid van Moolenbroek     /* grab all swap info */
1155*b89261baSDavid van Moolenbroek     if (swapctl(SC_LIST, swt) == -1)
1156*b89261baSDavid van Moolenbroek     {
1157*b89261baSDavid van Moolenbroek 	return (-1);
1158*b89261baSDavid van Moolenbroek     }
1159*b89261baSDavid van Moolenbroek 
1160*b89261baSDavid van Moolenbroek     /* walk thru the structs and sum up the fields */
1161*b89261baSDavid van Moolenbroek     t = f = 0;
1162*b89261baSDavid van Moolenbroek     ste = &(swt->swt_ent[0]);
1163*b89261baSDavid van Moolenbroek     i = cnt;
1164*b89261baSDavid van Moolenbroek     while (--i >= 0)
1165*b89261baSDavid van Moolenbroek     {
1166*b89261baSDavid van Moolenbroek 	/* dont count slots being deleted */
1167*b89261baSDavid van Moolenbroek 	if (!(ste->ste_flags & ST_INDEL) &&
1168*b89261baSDavid van Moolenbroek 	    !(ste->ste_flags & ST_DOINGDEL))
1169*b89261baSDavid van Moolenbroek 	{
1170*b89261baSDavid van Moolenbroek 	    t += ste->ste_pages;
1171*b89261baSDavid van Moolenbroek 	    f += ste->ste_free;
1172*b89261baSDavid van Moolenbroek 	}
1173*b89261baSDavid van Moolenbroek 	ste++;
1174*b89261baSDavid van Moolenbroek     }
1175*b89261baSDavid van Moolenbroek 
1176*b89261baSDavid van Moolenbroek     /* fill in the results */
1177*b89261baSDavid van Moolenbroek     *total = pagetok(t);
1178*b89261baSDavid van Moolenbroek     *fr = pagetok(f);
1179*b89261baSDavid van Moolenbroek     free(swt);
1180*b89261baSDavid van Moolenbroek 
1181*b89261baSDavid van Moolenbroek     /* good to go */
1182*b89261baSDavid van Moolenbroek     return (0);
1183*b89261baSDavid van Moolenbroek }
1184*b89261baSDavid van Moolenbroek 
1185*b89261baSDavid van Moolenbroek int
machine_init(struct statics * statics)1186*b89261baSDavid van Moolenbroek machine_init (struct statics *statics)
1187*b89261baSDavid van Moolenbroek {
1188*b89261baSDavid van Moolenbroek     struct utmpx ut;
1189*b89261baSDavid van Moolenbroek     struct utmpx *up;
1190*b89261baSDavid van Moolenbroek     struct rlimit rlim;
1191*b89261baSDavid van Moolenbroek     int i;
1192*b89261baSDavid van Moolenbroek     char *p;
1193*b89261baSDavid van Moolenbroek     int *ip;
1194*b89261baSDavid van Moolenbroek     int nproc;
1195*b89261baSDavid van Moolenbroek #ifndef USE_KSTAT
1196*b89261baSDavid van Moolenbroek     int offset;
1197*b89261baSDavid van Moolenbroek #endif
1198*b89261baSDavid van Moolenbroek 
1199*b89261baSDavid van Moolenbroek     /* There's a buffer overflow bug in curses that can be exploited when
1200*b89261baSDavid van Moolenbroek        we run as root.  By making sure that TERMINFO is set to something
1201*b89261baSDavid van Moolenbroek        this bug is avoided.  This code thanks to Casper */
1202*b89261baSDavid van Moolenbroek     if ((p = getenv("TERMINFO")) == NULL || *p == '\0')
1203*b89261baSDavid van Moolenbroek     {
1204*b89261baSDavid van Moolenbroek         putenv("TERMINFO=/usr/share/lib/terminfo/");
1205*b89261baSDavid van Moolenbroek     }
1206*b89261baSDavid van Moolenbroek 
1207*b89261baSDavid van Moolenbroek     /* perform the kvm_open - suppress error here */
1208*b89261baSDavid van Moolenbroek     if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
1209*b89261baSDavid van Moolenbroek     {
1210*b89261baSDavid van Moolenbroek 	/* save the error message: we may need it later */
1211*b89261baSDavid van Moolenbroek 	p = strerror(errno);
1212*b89261baSDavid van Moolenbroek     }
1213*b89261baSDavid van Moolenbroek     dprintf("kvm_open: fd %d\n", kd);
1214*b89261baSDavid van Moolenbroek 
1215*b89261baSDavid van Moolenbroek     /*
1216*b89261baSDavid van Moolenbroek      * turn off super group/user privs - but beware; we might
1217*b89261baSDavid van Moolenbroek      * want the privs back later and we still have a fd to
1218*b89261baSDavid van Moolenbroek      * /dev/kmem open so we can't use setgid()/setuid() as that
1219*b89261baSDavid van Moolenbroek      * would allow a debugger to attach to this process. CD
1220*b89261baSDavid van Moolenbroek      */
1221*b89261baSDavid van Moolenbroek     setegid(getgid());
1222*b89261baSDavid van Moolenbroek     seteuid(getuid()); /* super user not needed for NEW_PROC */
1223*b89261baSDavid van Moolenbroek 
1224*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
1225*b89261baSDavid van Moolenbroek     /* open kstat */
1226*b89261baSDavid van Moolenbroek     if ((kc = kstat_open()) == NULL)
1227*b89261baSDavid van Moolenbroek     {
1228*b89261baSDavid van Moolenbroek 	fprintf(stderr, "Unable to open kstat.\n");
1229*b89261baSDavid van Moolenbroek 	return(-1);
1230*b89261baSDavid van Moolenbroek     }
1231*b89261baSDavid van Moolenbroek     kcid = kc->kc_chain_id;
1232*b89261baSDavid van Moolenbroek     dprintf("kstat_open: chain %d\n", kcid);
1233*b89261baSDavid van Moolenbroek #endif
1234*b89261baSDavid van Moolenbroek 
1235*b89261baSDavid van Moolenbroek     /* fill in the statics information */
1236*b89261baSDavid van Moolenbroek     statics->procstate_names = procstatenames;
1237*b89261baSDavid van Moolenbroek     statics->cpustate_names = cpustatenames;
1238*b89261baSDavid van Moolenbroek     statics->memory_names = memorynames;
1239*b89261baSDavid van Moolenbroek     statics->kernel_names = kernelnames;
1240*b89261baSDavid van Moolenbroek     statics->order_names = ordernames;
1241*b89261baSDavid van Moolenbroek     statics->flags.fullcmds = 1;
1242*b89261baSDavid van Moolenbroek     statics->flags.warmup = 1;
1243*b89261baSDavid van Moolenbroek     statics->flags.threads = 1;
1244*b89261baSDavid van Moolenbroek 
1245*b89261baSDavid van Moolenbroek     /* get boot time */
1246*b89261baSDavid van Moolenbroek     ut.ut_type = BOOT_TIME;
1247*b89261baSDavid van Moolenbroek     if ((up = getutxid(&ut)) != NULL)
1248*b89261baSDavid van Moolenbroek     {
1249*b89261baSDavid van Moolenbroek 	statics->boottime = up->ut_tv.tv_sec;
1250*b89261baSDavid van Moolenbroek     }
1251*b89261baSDavid van Moolenbroek     endutxent();
1252*b89261baSDavid van Moolenbroek 
1253*b89261baSDavid van Moolenbroek     /* if the kvm_open succeeded, get the nlist */
1254*b89261baSDavid van Moolenbroek     if (kd)
1255*b89261baSDavid van Moolenbroek     {
1256*b89261baSDavid van Moolenbroek 	if (kvm_nlist (kd, nlst) < 0)
1257*b89261baSDavid van Moolenbroek         {
1258*b89261baSDavid van Moolenbroek 	    perror ("kvm_nlist");
1259*b89261baSDavid van Moolenbroek 	    return (-1);
1260*b89261baSDavid van Moolenbroek         }
1261*b89261baSDavid van Moolenbroek 	if (check_nlist (nlst) != 0)
1262*b89261baSDavid van Moolenbroek 	    return (-1);
1263*b89261baSDavid van Moolenbroek     }
1264*b89261baSDavid van Moolenbroek #ifndef USE_KSTAT
1265*b89261baSDavid van Moolenbroek     /* if KSTAT is not available to us and we can't open /dev/kmem,
1266*b89261baSDavid van Moolenbroek        this is a serious problem.
1267*b89261baSDavid van Moolenbroek     */
1268*b89261baSDavid van Moolenbroek     else
1269*b89261baSDavid van Moolenbroek     {
1270*b89261baSDavid van Moolenbroek 	/* Print the error message here */
1271*b89261baSDavid van Moolenbroek 	(void) fprintf(stderr, "kvm_open: %s\n", p);
1272*b89261baSDavid van Moolenbroek 	return (-1);
1273*b89261baSDavid van Moolenbroek     }
1274*b89261baSDavid van Moolenbroek #endif
1275*b89261baSDavid van Moolenbroek 
1276*b89261baSDavid van Moolenbroek     /* stash away certain offsets for later use */
1277*b89261baSDavid van Moolenbroek     mpid_offset = nlst[X_MPID].n_value;
1278*b89261baSDavid van Moolenbroek     nproc_offset = nlst[X_NPROC].n_value;
1279*b89261baSDavid van Moolenbroek     avenrun_offset = nlst[X_AVENRUN].n_value;
1280*b89261baSDavid van Moolenbroek     anoninfo_offset = nlst[X_ANONINFO].n_value;
1281*b89261baSDavid van Moolenbroek     freemem_offset = nlst[X_FREEMEM].n_value;
1282*b89261baSDavid van Moolenbroek     maxmem_offset = nlst[X_MAXMEM].n_value;
1283*b89261baSDavid van Moolenbroek 
1284*b89261baSDavid van Moolenbroek #ifndef USE_KSTAT
1285*b89261baSDavid van Moolenbroek     (void) getkval (nlst[X_NCPUS].n_value, (int *) (&cpucount),
1286*b89261baSDavid van Moolenbroek 		    sizeof (cpucount), "ncpus");
1287*b89261baSDavid van Moolenbroek 
1288*b89261baSDavid van Moolenbroek     cpu_offset = (unsigned long *) malloc (cpucount * sizeof (unsigned long));
1289*b89261baSDavid van Moolenbroek     for (i = offset = 0; i < cpucount; offset += sizeof(unsigned long)) {
1290*b89261baSDavid van Moolenbroek         (void) getkval (nlst[X_CPU].n_value + offset,
1291*b89261baSDavid van Moolenbroek                         (int *)(&cpu_offset[i]), sizeof (unsigned long),
1292*b89261baSDavid van Moolenbroek                         nlst[X_CPU].n_name );
1293*b89261baSDavid van Moolenbroek         if (cpu_offset[i] != 0)
1294*b89261baSDavid van Moolenbroek             i++;
1295*b89261baSDavid van Moolenbroek     }
1296*b89261baSDavid van Moolenbroek #endif
1297*b89261baSDavid van Moolenbroek 
1298*b89261baSDavid van Moolenbroek     /* we need to get the current nproc */
1299*b89261baSDavid van Moolenbroek #ifdef USE_KSTAT
1300*b89261baSDavid van Moolenbroek     /* get_nproc assumes that the chain has already been retrieved,
1301*b89261baSDavid van Moolenbroek        so we need to do that here */
1302*b89261baSDavid van Moolenbroek     kstat_safe_retrieve(&ks_system_misc, "unix", 0, "system_misc", NULL);
1303*b89261baSDavid van Moolenbroek #endif
1304*b89261baSDavid van Moolenbroek     nproc = get_nproc();
1305*b89261baSDavid van Moolenbroek     dprintf("machine_init: nproc=%d\n", nproc);
1306*b89261baSDavid van Moolenbroek 
1307*b89261baSDavid van Moolenbroek     /* hash table for procs and threads sized based on current nproc*/
1308*b89261baSDavid van Moolenbroek     prochash = hash_create(nproc > 100 ? nproc * 2 + 1 : 521);
1309*b89261baSDavid van Moolenbroek     threadhash = hash_create(nproc > 100 ? nproc * 4 + 1 : 2053);
1310*b89261baSDavid van Moolenbroek 
1311*b89261baSDavid van Moolenbroek     /* calculate pageshift value */
1312*b89261baSDavid van Moolenbroek     i = sysconf(_SC_PAGESIZE);
1313*b89261baSDavid van Moolenbroek     pageshift = 0;
1314*b89261baSDavid van Moolenbroek     while ((i >>= 1) > 0)
1315*b89261baSDavid van Moolenbroek     {
1316*b89261baSDavid van Moolenbroek 	pageshift++;
1317*b89261baSDavid van Moolenbroek     }
1318*b89261baSDavid van Moolenbroek 
1319*b89261baSDavid van Moolenbroek     /* calculate an amount to shift to K values */
1320*b89261baSDavid van Moolenbroek     /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
1321*b89261baSDavid van Moolenbroek     pageshift -= 10;
1322*b89261baSDavid van Moolenbroek 
1323*b89261baSDavid van Moolenbroek     /* now determine which pageshift function is appropriate for the
1324*b89261baSDavid van Moolenbroek        result (have to because x << y is undefined for y < 0) */
1325*b89261baSDavid van Moolenbroek     if (pageshift > 0)
1326*b89261baSDavid van Moolenbroek     {
1327*b89261baSDavid van Moolenbroek 	/* this is the most likely */
1328*b89261baSDavid van Moolenbroek 	p_pagetok = pagetok_left;
1329*b89261baSDavid van Moolenbroek     }
1330*b89261baSDavid van Moolenbroek     else if (pageshift == 0)
1331*b89261baSDavid van Moolenbroek     {
1332*b89261baSDavid van Moolenbroek 	p_pagetok = pagetok_none;
1333*b89261baSDavid van Moolenbroek     }
1334*b89261baSDavid van Moolenbroek     else
1335*b89261baSDavid van Moolenbroek     {
1336*b89261baSDavid van Moolenbroek 	p_pagetok = pagetok_right;
1337*b89261baSDavid van Moolenbroek 	pageshift = -pageshift;
1338*b89261baSDavid van Moolenbroek     }
1339*b89261baSDavid van Moolenbroek 
1340*b89261baSDavid van Moolenbroek     /* we cache open files to improve performance, so we need to up
1341*b89261baSDavid van Moolenbroek        the NOFILE limit */
1342*b89261baSDavid van Moolenbroek     if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
1343*b89261baSDavid van Moolenbroek     {
1344*b89261baSDavid van Moolenbroek 	/* set a new soft limit */
1345*b89261baSDavid van Moolenbroek 	maxfiles = (int)(rlim.rlim_max < MAXFILES ? rlim.rlim_max : MAXFILES);
1346*b89261baSDavid van Moolenbroek 	rlim.rlim_cur = (rlim_t)maxfiles;
1347*b89261baSDavid van Moolenbroek 	(void)setrlimit(RLIMIT_NOFILE, &rlim);
1348*b89261baSDavid van Moolenbroek 
1349*b89261baSDavid van Moolenbroek 	/* now leave some wiggle room above the maximum */
1350*b89261baSDavid van Moolenbroek 	maxfiles -= 20;
1351*b89261baSDavid van Moolenbroek     }
1352*b89261baSDavid van Moolenbroek 
1353*b89261baSDavid van Moolenbroek     /* set up the display indices */
1354*b89261baSDavid van Moolenbroek     ip = proc_display;
1355*b89261baSDavid van Moolenbroek     *ip++ = field_index("PID");
1356*b89261baSDavid van Moolenbroek     *ip++ = field_index("USERNAME");
1357*b89261baSDavid van Moolenbroek     *ip++ = field_index("NLWP");
1358*b89261baSDavid van Moolenbroek     *ip++ = field_index("PRI");
1359*b89261baSDavid van Moolenbroek     *ip++ = field_index("NICE");
1360*b89261baSDavid van Moolenbroek     *ip++ = field_index("SIZE");
1361*b89261baSDavid van Moolenbroek     *ip++ = field_index("RES");
1362*b89261baSDavid van Moolenbroek     *ip++ = field_index("STATE");
1363*b89261baSDavid van Moolenbroek     *ip++ = field_index("TIME");
1364*b89261baSDavid van Moolenbroek     *ip++ = field_index("CPU");
1365*b89261baSDavid van Moolenbroek     *ip++ = field_index("COMMAND");
1366*b89261baSDavid van Moolenbroek     *ip = -1;
1367*b89261baSDavid van Moolenbroek     ip = thr_display;
1368*b89261baSDavid van Moolenbroek     *ip++ = field_index("PID");
1369*b89261baSDavid van Moolenbroek     *ip++ = field_index("LWP");
1370*b89261baSDavid van Moolenbroek     *ip++ = field_index("USERNAME");
1371*b89261baSDavid van Moolenbroek     *ip++ = field_index("PRI");
1372*b89261baSDavid van Moolenbroek     *ip++ = field_index("NICE");
1373*b89261baSDavid van Moolenbroek     *ip++ = field_index("SIZE");
1374*b89261baSDavid van Moolenbroek     *ip++ = field_index("RES");
1375*b89261baSDavid van Moolenbroek     *ip++ = field_index("STATE");
1376*b89261baSDavid van Moolenbroek     *ip++ = field_index("TIME");
1377*b89261baSDavid van Moolenbroek     *ip++ = field_index("CPU");
1378*b89261baSDavid van Moolenbroek     *ip++ = field_index("COMMAND");
1379*b89261baSDavid van Moolenbroek     *ip = -1;
1380*b89261baSDavid van Moolenbroek 
1381*b89261baSDavid van Moolenbroek     if (!(procdir = opendir (PROCFS)))
1382*b89261baSDavid van Moolenbroek     {
1383*b89261baSDavid van Moolenbroek 	(void) fprintf (stderr, "Unable to open %s\n", PROCFS);
1384*b89261baSDavid van Moolenbroek 	return (-1);
1385*b89261baSDavid van Moolenbroek     }
1386*b89261baSDavid van Moolenbroek 
1387*b89261baSDavid van Moolenbroek     if (chdir (PROCFS))
1388*b89261baSDavid van Moolenbroek     {				/* handy for later on when we're reading it */
1389*b89261baSDavid van Moolenbroek 	(void) fprintf (stderr, "Unable to chdir to %s\n", PROCFS);
1390*b89261baSDavid van Moolenbroek 	return (-1);
1391*b89261baSDavid van Moolenbroek     }
1392*b89261baSDavid van Moolenbroek 
1393*b89261baSDavid van Moolenbroek     /* all done! */
1394*b89261baSDavid van Moolenbroek     return (0);
1395*b89261baSDavid van Moolenbroek }
1396*b89261baSDavid van Moolenbroek 
1397*b89261baSDavid van Moolenbroek void
get_system_info(struct system_info * si)1398*b89261baSDavid van Moolenbroek get_system_info (struct system_info *si)
1399*b89261baSDavid van Moolenbroek {
1400*b89261baSDavid van Moolenbroek     int avenrun[3];
1401*b89261baSDavid van Moolenbroek 
1402*b89261baSDavid van Moolenbroek     static long cp_time[CPUSTATES];
1403*b89261baSDavid van Moolenbroek     static long cp_old[CPUSTATES];
1404*b89261baSDavid van Moolenbroek     static long cp_diff[CPUSTATES];
1405*b89261baSDavid van Moolenbroek     static struct cpustats *cpustats = NULL;
1406*b89261baSDavid van Moolenbroek     static struct cpustats sum_current;
1407*b89261baSDavid van Moolenbroek     static struct cpustats sum_old;
1408*b89261baSDavid van Moolenbroek     static int cpus = 0;
1409*b89261baSDavid van Moolenbroek     register int j, i;
1410*b89261baSDavid van Moolenbroek 
1411*b89261baSDavid van Moolenbroek     /* remember the old values and zero out the current */
1412*b89261baSDavid van Moolenbroek     memcpy(&sum_old, &sum_current, sizeof(sum_current));
1413*b89261baSDavid van Moolenbroek     memset(&sum_current, 0, sizeof(sum_current));
1414*b89261baSDavid van Moolenbroek 
1415*b89261baSDavid van Moolenbroek     /* get important information */
1416*b89261baSDavid van Moolenbroek     get_avenrun(avenrun);
1417*b89261baSDavid van Moolenbroek 
1418*b89261baSDavid van Moolenbroek     /* get the cpu statistics arrays */
1419*b89261baSDavid van Moolenbroek     cpustats = get_cpustats(&cpus, cpustats);
1420*b89261baSDavid van Moolenbroek 
1421*b89261baSDavid van Moolenbroek     /* zero the cp_time array */
1422*b89261baSDavid van Moolenbroek     memset(cp_time, 0, sizeof(cp_time));
1423*b89261baSDavid van Moolenbroek 
1424*b89261baSDavid van Moolenbroek     /* sum stats in to a single array and a single structure */
1425*b89261baSDavid van Moolenbroek     for (i = 0; i < cpus; i++)
1426*b89261baSDavid van Moolenbroek     {
1427*b89261baSDavid van Moolenbroek 	for (j = 0; j < CPUSTATES; j++)
1428*b89261baSDavid van Moolenbroek 	{
1429*b89261baSDavid van Moolenbroek 	    cp_time[j] += cpustats[i].states[j];
1430*b89261baSDavid van Moolenbroek 	}
1431*b89261baSDavid van Moolenbroek 	sum_current.pswitch += cpustats[i].pswitch;
1432*b89261baSDavid van Moolenbroek 	sum_current.trap += cpustats[i].trap;
1433*b89261baSDavid van Moolenbroek 	sum_current.intr += cpustats[i].intr;
1434*b89261baSDavid van Moolenbroek 	sum_current.syscall += cpustats[i].syscall;
1435*b89261baSDavid van Moolenbroek 	sum_current.sysfork += cpustats[i].sysfork;
1436*b89261baSDavid van Moolenbroek 	sum_current.sysvfork += cpustats[i].sysvfork;
1437*b89261baSDavid van Moolenbroek 	sum_current.pfault += cpustats[i].pfault;
1438*b89261baSDavid van Moolenbroek 	sum_current.pgin += cpustats[i].pgin;
1439*b89261baSDavid van Moolenbroek 	sum_current.pgout += cpustats[i].pgout;
1440*b89261baSDavid van Moolenbroek     }
1441*b89261baSDavid van Moolenbroek 
1442*b89261baSDavid van Moolenbroek     /* convert cp_time counts to percentages */
1443*b89261baSDavid van Moolenbroek     (void) percentages (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
1444*b89261baSDavid van Moolenbroek 
1445*b89261baSDavid van Moolenbroek     /* get mpid -- process id of last process */
1446*b89261baSDavid van Moolenbroek     if (kd)
1447*b89261baSDavid van Moolenbroek 	(void) getkval(mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid");
1448*b89261baSDavid van Moolenbroek     else
1449*b89261baSDavid van Moolenbroek 	si->last_pid = -1;
1450*b89261baSDavid van Moolenbroek 
1451*b89261baSDavid van Moolenbroek     /* convert load averages to doubles */
1452*b89261baSDavid van Moolenbroek     for (i = 0; i < 3; i++)
1453*b89261baSDavid van Moolenbroek 	si->load_avg[i] = loaddouble (avenrun[i]);
1454*b89261baSDavid van Moolenbroek 
1455*b89261baSDavid van Moolenbroek     /* get physical memory data */
1456*b89261baSDavid van Moolenbroek     if (get_meminfo(&(memory_stats[MEMORY_TOTALMEM]),
1457*b89261baSDavid van Moolenbroek 		    &(memory_stats[MEMORY_FREEMEM])) == -1)
1458*b89261baSDavid van Moolenbroek     {
1459*b89261baSDavid van Moolenbroek 	memory_stats[MEMORY_TOTALMEM] = memory_stats[MEMORY_FREEMEM] = -1;
1460*b89261baSDavid van Moolenbroek     }
1461*b89261baSDavid van Moolenbroek 
1462*b89261baSDavid van Moolenbroek     /* get swap data */
1463*b89261baSDavid van Moolenbroek     if (get_swapinfo(&(memory_stats[MEMORY_TOTALSWAP]),
1464*b89261baSDavid van Moolenbroek 		     &(memory_stats[MEMORY_FREESWAP])) == -1)
1465*b89261baSDavid van Moolenbroek     {
1466*b89261baSDavid van Moolenbroek 	memory_stats[MEMORY_TOTALSWAP] = memory_stats[MEMORY_FREESWAP] = -1;
1467*b89261baSDavid van Moolenbroek     }
1468*b89261baSDavid van Moolenbroek 
1469*b89261baSDavid van Moolenbroek     /* get kernel data */
1470*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_CSWITCH] = diff_per_second(sum_current.pswitch, sum_old.pswitch);
1471*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_TRAP] = diff_per_second(sum_current.trap, sum_old.trap);
1472*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_INTR] = diff_per_second(sum_current.intr, sum_old.intr);
1473*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_SYSCALL] = diff_per_second(sum_current.syscall, sum_old.syscall);
1474*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_FORK] = diff_per_second(sum_current.sysfork + sum_current.sysvfork,
1475*b89261baSDavid van Moolenbroek 						sum_old.sysfork + sum_old.sysvfork);
1476*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_PFAULT] = diff_per_second(sum_current.pfault, sum_old.pfault);
1477*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_PGIN] = pagetok(diff_per_second(sum_current.pgin, sum_old.pgin));
1478*b89261baSDavid van Moolenbroek     kernel_stats[KERNEL_PGOUT] = pagetok(diff_per_second(sum_current.pgout, sum_old.pgout));
1479*b89261baSDavid van Moolenbroek 
1480*b89261baSDavid van Moolenbroek 
1481*b89261baSDavid van Moolenbroek     /* set arrays and strings */
1482*b89261baSDavid van Moolenbroek     si->cpustates = cpu_states;
1483*b89261baSDavid van Moolenbroek     si->memory = memory_stats;
1484*b89261baSDavid van Moolenbroek     si->kernel = kernel_stats;
1485*b89261baSDavid van Moolenbroek 
1486*b89261baSDavid van Moolenbroek     dprintf("get_system_info returns\n");
1487*b89261baSDavid van Moolenbroek }
1488*b89261baSDavid van Moolenbroek 
1489*b89261baSDavid van Moolenbroek static struct handle handle;
1490*b89261baSDavid van Moolenbroek 
1491*b89261baSDavid van Moolenbroek caddr_t
get_process_info(struct system_info * si,struct process_select * sel,int compare_index)1492*b89261baSDavid van Moolenbroek get_process_info (
1493*b89261baSDavid van Moolenbroek 		   struct system_info *si,
1494*b89261baSDavid van Moolenbroek 		   struct process_select *sel,
1495*b89261baSDavid van Moolenbroek 		   int compare_index)
1496*b89261baSDavid van Moolenbroek {
1497*b89261baSDavid van Moolenbroek     register int i;
1498*b89261baSDavid van Moolenbroek     register int total_procs;
1499*b89261baSDavid van Moolenbroek     register int active_procs;
1500*b89261baSDavid van Moolenbroek     register struct prpsinfo **prefp;
1501*b89261baSDavid van Moolenbroek     register struct prpsinfo *pp;
1502*b89261baSDavid van Moolenbroek     int nproc;
1503*b89261baSDavid van Moolenbroek     int state;
1504*b89261baSDavid van Moolenbroek 
1505*b89261baSDavid van Moolenbroek     /* these are copied out of sel for speed */
1506*b89261baSDavid van Moolenbroek     int show_idle;
1507*b89261baSDavid van Moolenbroek     int show_system;
1508*b89261baSDavid van Moolenbroek     int show_uid;
1509*b89261baSDavid van Moolenbroek     char *show_command;
1510*b89261baSDavid van Moolenbroek 
1511*b89261baSDavid van Moolenbroek     /* these persist across calls */
1512*b89261baSDavid van Moolenbroek     static struct prpsinfo **pref = NULL;
1513*b89261baSDavid van Moolenbroek     static int pref_size = 0;
1514*b89261baSDavid van Moolenbroek 
1515*b89261baSDavid van Moolenbroek     /* set up flags which define what we are going to select */
1516*b89261baSDavid van Moolenbroek     show_idle = sel->idle;
1517*b89261baSDavid van Moolenbroek     show_system = sel->system;
1518*b89261baSDavid van Moolenbroek     show_uid = sel->uid != -1;
1519*b89261baSDavid van Moolenbroek     show_fullcmd = sel->fullcmd;
1520*b89261baSDavid van Moolenbroek     show_command = sel->command;
1521*b89261baSDavid van Moolenbroek     show_threads = sel->threads;
1522*b89261baSDavid van Moolenbroek 
1523*b89261baSDavid van Moolenbroek     /* allocate enough space for twice our current needs */
1524*b89261baSDavid van Moolenbroek     nproc = get_nproc();
1525*b89261baSDavid van Moolenbroek     if (nproc > procs_max())
1526*b89261baSDavid van Moolenbroek     {
1527*b89261baSDavid van Moolenbroek 	procs_prealloc(2 * nproc);
1528*b89261baSDavid van Moolenbroek     }
1529*b89261baSDavid van Moolenbroek 
1530*b89261baSDavid van Moolenbroek     /* read all the proc structures */
1531*b89261baSDavid van Moolenbroek     nproc = getptable();
1532*b89261baSDavid van Moolenbroek 
1533*b89261baSDavid van Moolenbroek     /* allocate pref[] */
1534*b89261baSDavid van Moolenbroek     if (pref_size < nproc)
1535*b89261baSDavid van Moolenbroek     {
1536*b89261baSDavid van Moolenbroek 	if (pref != NULL)
1537*b89261baSDavid van Moolenbroek 	{
1538*b89261baSDavid van Moolenbroek 	    free(pref);
1539*b89261baSDavid van Moolenbroek 	}
1540*b89261baSDavid van Moolenbroek 	pref = (struct prpsinfo **)malloc(nproc * sizeof(struct prpsinfo *));
1541*b89261baSDavid van Moolenbroek 	dprintf("get_process_info: allocated %d prinfo pointers at %08x\n",
1542*b89261baSDavid van Moolenbroek 		nproc, pref);
1543*b89261baSDavid van Moolenbroek 	pref_size = nproc;
1544*b89261baSDavid van Moolenbroek     }
1545*b89261baSDavid van Moolenbroek 
1546*b89261baSDavid van Moolenbroek     /* get a pointer to the states summary array */
1547*b89261baSDavid van Moolenbroek     si->procstates = process_states;
1548*b89261baSDavid van Moolenbroek 
1549*b89261baSDavid van Moolenbroek     /* count up process states and get pointers to interesting procs */
1550*b89261baSDavid van Moolenbroek     total_procs = 0;
1551*b89261baSDavid van Moolenbroek     active_procs = 0;
1552*b89261baSDavid van Moolenbroek     (void) memset (process_states, 0, sizeof (process_states));
1553*b89261baSDavid van Moolenbroek     prefp = pref;
1554*b89261baSDavid van Moolenbroek 
1555*b89261baSDavid van Moolenbroek     for (pp = procs_start(), i = 0; i < nproc;
1556*b89261baSDavid van Moolenbroek 	 i++, pp = procs_next())
1557*b89261baSDavid van Moolenbroek     {
1558*b89261baSDavid van Moolenbroek 	dprintf("looking at #%d: %d.%d\n", i,
1559*b89261baSDavid van Moolenbroek 		pp->pr_pid, pp->pr_lwp.pr_lwpid);
1560*b89261baSDavid van Moolenbroek 	/*
1561*b89261baSDavid van Moolenbroek 	 *  Place pointers to each valid proc structure in pref[].
1562*b89261baSDavid van Moolenbroek 	 *  Process slots that are actually in use have a non-zero
1563*b89261baSDavid van Moolenbroek 	 *  status field.  Processes with SSYS set are system
1564*b89261baSDavid van Moolenbroek 	 *  processes---these get ignored unless show_sysprocs is set.
1565*b89261baSDavid van Moolenbroek 	 */
1566*b89261baSDavid van Moolenbroek 	if (pp->px_state != 0 &&
1567*b89261baSDavid van Moolenbroek 	    (show_system || ((pp->pr_flag & SSYS) == 0)))
1568*b89261baSDavid van Moolenbroek 	{
1569*b89261baSDavid van Moolenbroek 	    total_procs++;
1570*b89261baSDavid van Moolenbroek 	    state = (int)pp->px_state;
1571*b89261baSDavid van Moolenbroek 	    if (state > 0 && state < PROCSTATES)
1572*b89261baSDavid van Moolenbroek 	    {
1573*b89261baSDavid van Moolenbroek 		process_states[state]++;
1574*b89261baSDavid van Moolenbroek 	    }
1575*b89261baSDavid van Moolenbroek 	    else
1576*b89261baSDavid van Moolenbroek 	    {
1577*b89261baSDavid van Moolenbroek 		dprintf("process %d.%d: state out of bounds %d\n",
1578*b89261baSDavid van Moolenbroek 			pp->pr_pid, pp->pr_lwp.pr_lwpid, state);
1579*b89261baSDavid van Moolenbroek 	    }
1580*b89261baSDavid van Moolenbroek 
1581*b89261baSDavid van Moolenbroek 	    if ((!ZOMBIE(pp)) &&
1582*b89261baSDavid van Moolenbroek 		(show_idle || percent_cpu (pp) || (pp->px_state == SRUN) || (pp->px_state == SONPROC)) &&
1583*b89261baSDavid van Moolenbroek 		(!show_uid || pp->pr_uid == (uid_t) sel->uid) &&
1584*b89261baSDavid van Moolenbroek 		(show_command == NULL ||
1585*b89261baSDavid van Moolenbroek 		 strstr(pp->pr_fname, show_command) != NULL))
1586*b89261baSDavid van Moolenbroek 	    {
1587*b89261baSDavid van Moolenbroek 		*prefp++ = pp;
1588*b89261baSDavid van Moolenbroek 		active_procs++;
1589*b89261baSDavid van Moolenbroek 	    }
1590*b89261baSDavid van Moolenbroek 	}
1591*b89261baSDavid van Moolenbroek     }
1592*b89261baSDavid van Moolenbroek 
1593*b89261baSDavid van Moolenbroek     dprintf("total_procs %d, active_procs %d\n", total_procs, active_procs);
1594*b89261baSDavid van Moolenbroek 
1595*b89261baSDavid van Moolenbroek     /* if requested, sort the "interesting" processes */
1596*b89261baSDavid van Moolenbroek     qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *),
1597*b89261baSDavid van Moolenbroek 	   proc_compares[compare_index]);
1598*b89261baSDavid van Moolenbroek 
1599*b89261baSDavid van Moolenbroek     /* remember active and total counts */
1600*b89261baSDavid van Moolenbroek     si->p_total = total_procs;
1601*b89261baSDavid van Moolenbroek     si->p_active = active_procs;
1602*b89261baSDavid van Moolenbroek 
1603*b89261baSDavid van Moolenbroek     /* pass back a handle */
1604*b89261baSDavid van Moolenbroek     handle.next_proc = pref;
1605*b89261baSDavid van Moolenbroek     handle.remaining = active_procs;
1606*b89261baSDavid van Moolenbroek     return ((caddr_t) & handle);
1607*b89261baSDavid van Moolenbroek }
1608*b89261baSDavid van Moolenbroek 
1609*b89261baSDavid van Moolenbroek static char p_header[MAX_COLS];
1610*b89261baSDavid van Moolenbroek 
1611*b89261baSDavid van Moolenbroek char *
format_process_header(struct process_select * sel,caddr_t handle,int count)1612*b89261baSDavid van Moolenbroek format_process_header(struct process_select *sel, caddr_t handle, int count)
1613*b89261baSDavid van Moolenbroek 
1614*b89261baSDavid van Moolenbroek {
1615*b89261baSDavid van Moolenbroek     int cols;
1616*b89261baSDavid van Moolenbroek     char *p;
1617*b89261baSDavid van Moolenbroek     int *fi;
1618*b89261baSDavid van Moolenbroek     struct proc_field *fp;
1619*b89261baSDavid van Moolenbroek 
1620*b89261baSDavid van Moolenbroek     /* check for null handle */
1621*b89261baSDavid van Moolenbroek     if (handle == NULL)
1622*b89261baSDavid van Moolenbroek     {
1623*b89261baSDavid van Moolenbroek 	return("");
1624*b89261baSDavid van Moolenbroek     }
1625*b89261baSDavid van Moolenbroek 
1626*b89261baSDavid van Moolenbroek     /* remember how many columns there are on the display */
1627*b89261baSDavid van Moolenbroek     cols = display_columns();
1628*b89261baSDavid van Moolenbroek 
1629*b89261baSDavid van Moolenbroek     /* mode & threads dictate format */
1630*b89261baSDavid van Moolenbroek     fi = display_fields = sel->threads ? thr_display : proc_display;
1631*b89261baSDavid van Moolenbroek 
1632*b89261baSDavid van Moolenbroek     /* set username field correctly */
1633*b89261baSDavid van Moolenbroek     if (!sel->usernames)
1634*b89261baSDavid van Moolenbroek     {
1635*b89261baSDavid van Moolenbroek 	/* display uids */
1636*b89261baSDavid van Moolenbroek 	field_subst(fi, FIELD_USERNAME, FIELD_UID);
1637*b89261baSDavid van Moolenbroek     }
1638*b89261baSDavid van Moolenbroek     else
1639*b89261baSDavid van Moolenbroek     {
1640*b89261baSDavid van Moolenbroek 	/* display usernames */
1641*b89261baSDavid van Moolenbroek 	field_subst(fi, FIELD_UID, FIELD_USERNAME);
1642*b89261baSDavid van Moolenbroek     }
1643*b89261baSDavid van Moolenbroek 
1644*b89261baSDavid van Moolenbroek     /* walk thru fields and construct header */
1645*b89261baSDavid van Moolenbroek     /* are we worried about overflow??? */
1646*b89261baSDavid van Moolenbroek     p = p_header;
1647*b89261baSDavid van Moolenbroek     while (*fi != -1)
1648*b89261baSDavid van Moolenbroek     {
1649*b89261baSDavid van Moolenbroek 	fp = &(proc_field[*fi++]);
1650*b89261baSDavid van Moolenbroek 	if (fp->min_screenwidth <= cols)
1651*b89261baSDavid van Moolenbroek 	{
1652*b89261baSDavid van Moolenbroek 	    p += sprintf(p, fp->rjust ? "%*s" : "%-*s", fp->width, fp->name);
1653*b89261baSDavid van Moolenbroek 	    *p++ = ' ';
1654*b89261baSDavid van Moolenbroek 	}
1655*b89261baSDavid van Moolenbroek     }
1656*b89261baSDavid van Moolenbroek     *--p = '\0';
1657*b89261baSDavid van Moolenbroek 
1658*b89261baSDavid van Moolenbroek     return p_header;
1659*b89261baSDavid van Moolenbroek }
1660*b89261baSDavid van Moolenbroek 
1661*b89261baSDavid van Moolenbroek static char fmt[MAX_COLS];		/* static area where result is built */
1662*b89261baSDavid van Moolenbroek 
1663*b89261baSDavid van Moolenbroek char *
format_next_process(caddr_t handle,char * (* get_userid)(int))1664*b89261baSDavid van Moolenbroek format_next_process(caddr_t handle, char *(*get_userid)(int))
1665*b89261baSDavid van Moolenbroek 
1666*b89261baSDavid van Moolenbroek {
1667*b89261baSDavid van Moolenbroek     struct prpsinfo *pp;
1668*b89261baSDavid van Moolenbroek     struct handle *hp;
1669*b89261baSDavid van Moolenbroek     struct proc_field *fp;
1670*b89261baSDavid van Moolenbroek     int *fi;
1671*b89261baSDavid van Moolenbroek     int i;
1672*b89261baSDavid van Moolenbroek     int cols;
1673*b89261baSDavid van Moolenbroek     char *p;
1674*b89261baSDavid van Moolenbroek     int len;
1675*b89261baSDavid van Moolenbroek     int x;
1676*b89261baSDavid van Moolenbroek 
1677*b89261baSDavid van Moolenbroek     /* find and remember the next proc structure */
1678*b89261baSDavid van Moolenbroek     hp = (struct handle *)handle;
1679*b89261baSDavid van Moolenbroek     pp = *(hp->next_proc++);
1680*b89261baSDavid van Moolenbroek     hp->remaining--;
1681*b89261baSDavid van Moolenbroek 
1682*b89261baSDavid van Moolenbroek     /* grab format descriptor */
1683*b89261baSDavid van Moolenbroek     fi = display_fields;
1684*b89261baSDavid van Moolenbroek 
1685*b89261baSDavid van Moolenbroek     /* screen width is a consideration, too */
1686*b89261baSDavid van Moolenbroek     cols = display_columns();
1687*b89261baSDavid van Moolenbroek 
1688*b89261baSDavid van Moolenbroek     /* build output by field */
1689*b89261baSDavid van Moolenbroek     p = fmt;
1690*b89261baSDavid van Moolenbroek     len = MAX_COLS;
1691*b89261baSDavid van Moolenbroek     while ((i = *fi++) != -1)
1692*b89261baSDavid van Moolenbroek     {
1693*b89261baSDavid van Moolenbroek 	fp = &(proc_field[i]);
1694*b89261baSDavid van Moolenbroek 	if (len > 0 && fp->min_screenwidth <= cols)
1695*b89261baSDavid van Moolenbroek 	{
1696*b89261baSDavid van Moolenbroek 	    x = (*(fp->format))(p, len, pp);
1697*b89261baSDavid van Moolenbroek 	    if (x >= len)
1698*b89261baSDavid van Moolenbroek 	    {
1699*b89261baSDavid van Moolenbroek 		dprintf("format_next_process: formatter overflow: x %d, len %d, p %08x => %08x, fmt %08x - %08x\n",
1700*b89261baSDavid van Moolenbroek 			x, len, p, p + len, fmt, fmt + sizeof(fmt));
1701*b89261baSDavid van Moolenbroek 		p += len;
1702*b89261baSDavid van Moolenbroek 		len = 0;
1703*b89261baSDavid van Moolenbroek 	    }
1704*b89261baSDavid van Moolenbroek 	    else
1705*b89261baSDavid van Moolenbroek 	    {
1706*b89261baSDavid van Moolenbroek 		p += x;
1707*b89261baSDavid van Moolenbroek 		*p++ = ' ';
1708*b89261baSDavid van Moolenbroek 		len -= x + 1;
1709*b89261baSDavid van Moolenbroek 	    }
1710*b89261baSDavid van Moolenbroek 	}
1711*b89261baSDavid van Moolenbroek     }
1712*b89261baSDavid van Moolenbroek     *--p = '\0';
1713*b89261baSDavid van Moolenbroek 
1714*b89261baSDavid van Moolenbroek     /* return the result */
1715*b89261baSDavid van Moolenbroek     return(fmt);
1716*b89261baSDavid van Moolenbroek }
1717*b89261baSDavid van Moolenbroek 
1718*b89261baSDavid van Moolenbroek /* comparison routines for qsort */
1719*b89261baSDavid van Moolenbroek 
1720*b89261baSDavid van Moolenbroek /*
1721*b89261baSDavid van Moolenbroek  * There are currently four possible comparison routines.  main selects
1722*b89261baSDavid van Moolenbroek  * one of these by indexing in to the array proc_compares.
1723*b89261baSDavid van Moolenbroek  *
1724*b89261baSDavid van Moolenbroek  * Possible keys are defined as macros below.  Currently these keys are
1725*b89261baSDavid van Moolenbroek  * defined:  percent cpu, cpu ticks, process state, resident set size,
1726*b89261baSDavid van Moolenbroek  * total virtual memory usage.  The process states are ordered as follows
1727*b89261baSDavid van Moolenbroek  * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
1728*b89261baSDavid van Moolenbroek  * The array declaration below maps a process state index into a number
1729*b89261baSDavid van Moolenbroek  * that reflects this ordering.
1730*b89261baSDavid van Moolenbroek  */
1731*b89261baSDavid van Moolenbroek 
1732*b89261baSDavid van Moolenbroek /* First, the possible comparison keys.  These are defined in such a way
1733*b89261baSDavid van Moolenbroek    that they can be merely listed in the source code to define the actual
1734*b89261baSDavid van Moolenbroek    desired ordering.
1735*b89261baSDavid van Moolenbroek  */
1736*b89261baSDavid van Moolenbroek 
1737*b89261baSDavid van Moolenbroek #define ORDERKEY_PCTCPU  if (dresult = percent_cpu (p2) - percent_cpu (p1),\
1738*b89261baSDavid van Moolenbroek 			     (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
1739*b89261baSDavid van Moolenbroek #define ORDERKEY_CPTICKS if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
1740*b89261baSDavid van Moolenbroek #define ORDERKEY_STATE   if ((result = (long) (sorted_state[(int)p2->px_state] - \
1741*b89261baSDavid van Moolenbroek 			       sorted_state[(int)p1->px_state])) == 0)
1742*b89261baSDavid van Moolenbroek #define ORDERKEY_PRIO    if ((result = p2->px_pri - p1->px_pri) == 0)
1743*b89261baSDavid van Moolenbroek #define ORDERKEY_RSSIZE  if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
1744*b89261baSDavid van Moolenbroek #define ORDERKEY_MEM     if ((result = (p2->pr_size - p1->pr_size)) == 0)
1745*b89261baSDavid van Moolenbroek #define ORDERKEY_LWP     if ((result = (p1->pr_lwp.pr_lwpid - p2->pr_lwp.pr_lwpid)) == 0)
1746*b89261baSDavid van Moolenbroek #define ORDERKEY_PID     if ((result = (p1->pr_pid - p2->pr_pid)) == 0)
1747*b89261baSDavid van Moolenbroek 
1748*b89261baSDavid van Moolenbroek /* Now the array that maps process state to a weight */
1749*b89261baSDavid van Moolenbroek 
1750*b89261baSDavid van Moolenbroek unsigned char sorted_state[] =
1751*b89261baSDavid van Moolenbroek {
1752*b89261baSDavid van Moolenbroek   0,				/* not used		*/
1753*b89261baSDavid van Moolenbroek   3,				/* sleep		*/
1754*b89261baSDavid van Moolenbroek   6,				/* run			*/
1755*b89261baSDavid van Moolenbroek   2,				/* zombie		*/
1756*b89261baSDavid van Moolenbroek   4,				/* stop			*/
1757*b89261baSDavid van Moolenbroek   5,				/* start		*/
1758*b89261baSDavid van Moolenbroek   7,				/* run on a processor   */
1759*b89261baSDavid van Moolenbroek   1				/* being swapped (WAIT)	*/
1760*b89261baSDavid van Moolenbroek };
1761*b89261baSDavid van Moolenbroek 
1762*b89261baSDavid van Moolenbroek 
1763*b89261baSDavid van Moolenbroek /* compare_cpu - the comparison function for sorting by cpu percentage */
1764*b89261baSDavid van Moolenbroek 
1765*b89261baSDavid van Moolenbroek int
compare_cpu(struct prpsinfo ** pp1,struct prpsinfo ** pp2)1766*b89261baSDavid van Moolenbroek compare_cpu (struct prpsinfo **pp1, struct prpsinfo **pp2)
1767*b89261baSDavid van Moolenbroek 
1768*b89261baSDavid van Moolenbroek {
1769*b89261baSDavid van Moolenbroek     register struct prpsinfo *p1;
1770*b89261baSDavid van Moolenbroek     register struct prpsinfo *p2;
1771*b89261baSDavid van Moolenbroek     register long result;
1772*b89261baSDavid van Moolenbroek     double dresult;
1773*b89261baSDavid van Moolenbroek 
1774*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1775*b89261baSDavid van Moolenbroek     p1 = *pp1;
1776*b89261baSDavid van Moolenbroek     p2 = *pp2;
1777*b89261baSDavid van Moolenbroek 
1778*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1779*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1780*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1781*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1782*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1783*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1784*b89261baSDavid van Moolenbroek     ORDERKEY_PID
1785*b89261baSDavid van Moolenbroek     ORDERKEY_LWP
1786*b89261baSDavid van Moolenbroek     ;
1787*b89261baSDavid van Moolenbroek 
1788*b89261baSDavid van Moolenbroek     return (result);
1789*b89261baSDavid van Moolenbroek }
1790*b89261baSDavid van Moolenbroek 
1791*b89261baSDavid van Moolenbroek /* compare_size - the comparison function for sorting by total memory usage */
1792*b89261baSDavid van Moolenbroek 
1793*b89261baSDavid van Moolenbroek int
compare_size(struct prpsinfo ** pp1,struct prpsinfo ** pp2)1794*b89261baSDavid van Moolenbroek compare_size (struct prpsinfo **pp1, struct prpsinfo **pp2)
1795*b89261baSDavid van Moolenbroek 
1796*b89261baSDavid van Moolenbroek {
1797*b89261baSDavid van Moolenbroek     register struct prpsinfo *p1;
1798*b89261baSDavid van Moolenbroek     register struct prpsinfo *p2;
1799*b89261baSDavid van Moolenbroek     register long result;
1800*b89261baSDavid van Moolenbroek     double dresult;
1801*b89261baSDavid van Moolenbroek 
1802*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1803*b89261baSDavid van Moolenbroek     p1 = *pp1;
1804*b89261baSDavid van Moolenbroek     p2 = *pp2;
1805*b89261baSDavid van Moolenbroek 
1806*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1807*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1808*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1809*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1810*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1811*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1812*b89261baSDavid van Moolenbroek     ORDERKEY_PID
1813*b89261baSDavid van Moolenbroek     ORDERKEY_LWP
1814*b89261baSDavid van Moolenbroek     ;
1815*b89261baSDavid van Moolenbroek 
1816*b89261baSDavid van Moolenbroek     return (result);
1817*b89261baSDavid van Moolenbroek }
1818*b89261baSDavid van Moolenbroek 
1819*b89261baSDavid van Moolenbroek /* compare_res - the comparison function for sorting by resident set size */
1820*b89261baSDavid van Moolenbroek 
1821*b89261baSDavid van Moolenbroek int
compare_res(struct prpsinfo ** pp1,struct prpsinfo ** pp2)1822*b89261baSDavid van Moolenbroek compare_res (struct prpsinfo **pp1, struct prpsinfo **pp2)
1823*b89261baSDavid van Moolenbroek 
1824*b89261baSDavid van Moolenbroek {
1825*b89261baSDavid van Moolenbroek     register struct prpsinfo *p1;
1826*b89261baSDavid van Moolenbroek     register struct prpsinfo *p2;
1827*b89261baSDavid van Moolenbroek     register long result;
1828*b89261baSDavid van Moolenbroek     double dresult;
1829*b89261baSDavid van Moolenbroek 
1830*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1831*b89261baSDavid van Moolenbroek     p1 = *pp1;
1832*b89261baSDavid van Moolenbroek     p2 = *pp2;
1833*b89261baSDavid van Moolenbroek 
1834*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1835*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1836*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1837*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1838*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1839*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1840*b89261baSDavid van Moolenbroek     ORDERKEY_PID
1841*b89261baSDavid van Moolenbroek     ORDERKEY_LWP
1842*b89261baSDavid van Moolenbroek     ;
1843*b89261baSDavid van Moolenbroek 
1844*b89261baSDavid van Moolenbroek     return (result);
1845*b89261baSDavid van Moolenbroek }
1846*b89261baSDavid van Moolenbroek 
1847*b89261baSDavid van Moolenbroek /* compare_time - the comparison function for sorting by total cpu time */
1848*b89261baSDavid van Moolenbroek 
1849*b89261baSDavid van Moolenbroek int
compare_time(struct prpsinfo ** pp1,struct prpsinfo ** pp2)1850*b89261baSDavid van Moolenbroek compare_time (struct prpsinfo **pp1, struct prpsinfo **pp2)
1851*b89261baSDavid van Moolenbroek 
1852*b89261baSDavid van Moolenbroek {
1853*b89261baSDavid van Moolenbroek     register struct prpsinfo *p1;
1854*b89261baSDavid van Moolenbroek     register struct prpsinfo *p2;
1855*b89261baSDavid van Moolenbroek     register long result;
1856*b89261baSDavid van Moolenbroek     double dresult;
1857*b89261baSDavid van Moolenbroek 
1858*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1859*b89261baSDavid van Moolenbroek     p1 = *pp1;
1860*b89261baSDavid van Moolenbroek     p2 = *pp2;
1861*b89261baSDavid van Moolenbroek 
1862*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1863*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1864*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1865*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1866*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1867*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1868*b89261baSDavid van Moolenbroek     ORDERKEY_PID
1869*b89261baSDavid van Moolenbroek     ORDERKEY_LWP
1870*b89261baSDavid van Moolenbroek     ;
1871*b89261baSDavid van Moolenbroek 
1872*b89261baSDavid van Moolenbroek     return (result);
1873*b89261baSDavid van Moolenbroek }
1874*b89261baSDavid van Moolenbroek 
1875*b89261baSDavid van Moolenbroek /* compare_pid - the comparison function for sorting by process id */
1876*b89261baSDavid van Moolenbroek 
1877*b89261baSDavid van Moolenbroek int
compare_pid(struct prpsinfo ** pp1,struct prpsinfo ** pp2)1878*b89261baSDavid van Moolenbroek compare_pid (struct prpsinfo **pp1, struct prpsinfo **pp2)
1879*b89261baSDavid van Moolenbroek 
1880*b89261baSDavid van Moolenbroek {
1881*b89261baSDavid van Moolenbroek     register struct prpsinfo *p1;
1882*b89261baSDavid van Moolenbroek     register struct prpsinfo *p2;
1883*b89261baSDavid van Moolenbroek     register long result;
1884*b89261baSDavid van Moolenbroek 
1885*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1886*b89261baSDavid van Moolenbroek     p1 = *pp1;
1887*b89261baSDavid van Moolenbroek     p2 = *pp2;
1888*b89261baSDavid van Moolenbroek 
1889*b89261baSDavid van Moolenbroek     ORDERKEY_PID
1890*b89261baSDavid van Moolenbroek     ORDERKEY_LWP
1891*b89261baSDavid van Moolenbroek     ;
1892*b89261baSDavid van Moolenbroek 
1893*b89261baSDavid van Moolenbroek     return (result);
1894*b89261baSDavid van Moolenbroek }
1895*b89261baSDavid van Moolenbroek 
1896*b89261baSDavid van Moolenbroek /* get process table */
1897*b89261baSDavid van Moolenbroek int
getptable(struct prpsinfo * baseptr)1898*b89261baSDavid van Moolenbroek getptable (struct prpsinfo *baseptr)
1899*b89261baSDavid van Moolenbroek {
1900*b89261baSDavid van Moolenbroek     struct prpsinfo *currproc;	/* pointer to current proc structure	*/
1901*b89261baSDavid van Moolenbroek #ifndef USE_NEW_PROC
1902*b89261baSDavid van Moolenbroek     struct prstatus prstatus;     /* for additional information */
1903*b89261baSDavid van Moolenbroek #endif
1904*b89261baSDavid van Moolenbroek     int numprocs = 0;
1905*b89261baSDavid van Moolenbroek     struct dirent *direntp;
1906*b89261baSDavid van Moolenbroek     struct oldproc *op;
1907*b89261baSDavid van Moolenbroek     hash_pos pos;
1908*b89261baSDavid van Moolenbroek     hash_item_pid *hi;
1909*b89261baSDavid van Moolenbroek     hash_item_pidthr *hip;
1910*b89261baSDavid van Moolenbroek     prheader_t *prp;
1911*b89261baSDavid van Moolenbroek     lwpsinfo_t *lwpp;
1912*b89261baSDavid van Moolenbroek     pidthr_t pidthr;
1913*b89261baSDavid van Moolenbroek     static struct timeval lasttime =
1914*b89261baSDavid van Moolenbroek 	{0, 0};
1915*b89261baSDavid van Moolenbroek     struct timeval thistime;
1916*b89261baSDavid van Moolenbroek     struct stat st;
1917*b89261baSDavid van Moolenbroek     double timediff;
1918*b89261baSDavid van Moolenbroek 
1919*b89261baSDavid van Moolenbroek     gettimeofday (&thistime, NULL);
1920*b89261baSDavid van Moolenbroek     /*
1921*b89261baSDavid van Moolenbroek      * To avoid divides, we keep times in nanoseconds.  This is
1922*b89261baSDavid van Moolenbroek      * scaled by 1e7 rather than 1e9 so that when we divide we
1923*b89261baSDavid van Moolenbroek      * get percent.
1924*b89261baSDavid van Moolenbroek      */
1925*b89261baSDavid van Moolenbroek     if (lasttime.tv_sec)
1926*b89261baSDavid van Moolenbroek 	timediff = ((double) thistime.tv_sec * 1.0e7 +
1927*b89261baSDavid van Moolenbroek 		    ((double) thistime.tv_usec * 10.0)) -
1928*b89261baSDavid van Moolenbroek 	    ((double) lasttime.tv_sec * 1.0e7 +
1929*b89261baSDavid van Moolenbroek 	     ((double) lasttime.tv_usec * 10.0));
1930*b89261baSDavid van Moolenbroek     else
1931*b89261baSDavid van Moolenbroek 	timediff = 1.0e7;
1932*b89261baSDavid van Moolenbroek 
1933*b89261baSDavid van Moolenbroek     /* get our first procs pointer */
1934*b89261baSDavid van Moolenbroek     currproc = procs_start();
1935*b89261baSDavid van Moolenbroek 
1936*b89261baSDavid van Moolenbroek     /* before reading /proc files, turn on root privs */
1937*b89261baSDavid van Moolenbroek     /* (we don't care if this fails since it will be caught later) */
1938*b89261baSDavid van Moolenbroek #ifndef USE_NEW_PROC
1939*b89261baSDavid van Moolenbroek     seteuid(0);
1940*b89261baSDavid van Moolenbroek #endif
1941*b89261baSDavid van Moolenbroek 
1942*b89261baSDavid van Moolenbroek     for (rewinddir (procdir); (direntp = readdir (procdir));)
1943*b89261baSDavid van Moolenbroek     {
1944*b89261baSDavid van Moolenbroek 	int fd;
1945*b89261baSDavid van Moolenbroek 	int pid;
1946*b89261baSDavid van Moolenbroek 	char buf[40];
1947*b89261baSDavid van Moolenbroek 
1948*b89261baSDavid van Moolenbroek 	/* skip dot files */
1949*b89261baSDavid van Moolenbroek 	if (direntp->d_name[0] == '.')
1950*b89261baSDavid van Moolenbroek 	    continue;
1951*b89261baSDavid van Moolenbroek 
1952*b89261baSDavid van Moolenbroek 	/* convert pid to a number (and make sure its valid) */
1953*b89261baSDavid van Moolenbroek 	pid = atoi(direntp->d_name);
1954*b89261baSDavid van Moolenbroek 	if (pid <= 0)
1955*b89261baSDavid van Moolenbroek 	    continue;
1956*b89261baSDavid van Moolenbroek 
1957*b89261baSDavid van Moolenbroek 	/* fetch the old proc data */
1958*b89261baSDavid van Moolenbroek 	op = (struct oldproc *)hash_lookup_pid(prochash, pid);
1959*b89261baSDavid van Moolenbroek 	if (op == NULL)
1960*b89261baSDavid van Moolenbroek 	{
1961*b89261baSDavid van Moolenbroek 	    /* new proc: create an entry for it */
1962*b89261baSDavid van Moolenbroek 	    op = (struct oldproc *)malloc(sizeof(struct oldproc));
1963*b89261baSDavid van Moolenbroek 	    hash_add_pid(prochash, pid, (void *)op);
1964*b89261baSDavid van Moolenbroek 	    op->pid = pid;
1965*b89261baSDavid van Moolenbroek 	    op->fd_psinfo = -1;
1966*b89261baSDavid van Moolenbroek 	    op->fd_lpsinfo = -1;
1967*b89261baSDavid van Moolenbroek 	    op->oldtime = 0.0;
1968*b89261baSDavid van Moolenbroek 	}
1969*b89261baSDavid van Moolenbroek 
1970*b89261baSDavid van Moolenbroek 	/* do we have a cached file? */
1971*b89261baSDavid van Moolenbroek 	fd = op->fd_psinfo;
1972*b89261baSDavid van Moolenbroek 	if (fd == -1)
1973*b89261baSDavid van Moolenbroek 	{
1974*b89261baSDavid van Moolenbroek 	    /* no: open the psinfo file */
1975*b89261baSDavid van Moolenbroek 	    snprintf(buf, sizeof(buf), "%s/psinfo", direntp->d_name);
1976*b89261baSDavid van Moolenbroek 	    if ((fd = open(buf, O_RDONLY)) < 0)
1977*b89261baSDavid van Moolenbroek 	    {
1978*b89261baSDavid van Moolenbroek 		/* cleanup??? */
1979*b89261baSDavid van Moolenbroek 		continue;
1980*b89261baSDavid van Moolenbroek 	    }
1981*b89261baSDavid van Moolenbroek 	}
1982*b89261baSDavid van Moolenbroek 
1983*b89261baSDavid van Moolenbroek 	/* read data from the file */
1984*b89261baSDavid van Moolenbroek #ifdef USE_NEW_PROC
1985*b89261baSDavid van Moolenbroek 	if (pread(fd, currproc, sizeof(psinfo_t), 0) != sizeof(psinfo_t))
1986*b89261baSDavid van Moolenbroek 	{
1987*b89261baSDavid van Moolenbroek 	    (void) close (fd);
1988*b89261baSDavid van Moolenbroek 	    op->fd_psinfo = -1;
1989*b89261baSDavid van Moolenbroek 	    continue;
1990*b89261baSDavid van Moolenbroek 	}
1991*b89261baSDavid van Moolenbroek #else
1992*b89261baSDavid van Moolenbroek 	if (ioctl(fd, PIOCPSINFO, currproc) < 0)
1993*b89261baSDavid van Moolenbroek 	{
1994*b89261baSDavid van Moolenbroek 	    (void) close(fd);
1995*b89261baSDavid van Moolenbroek 	    op->fd_psinfo = -1;
1996*b89261baSDavid van Moolenbroek 	    continue;
1997*b89261baSDavid van Moolenbroek 	}
1998*b89261baSDavid van Moolenbroek 
1999*b89261baSDavid van Moolenbroek 	if (ioctl(fd, PIOCSTATUS, &prstatus) < 0)
2000*b89261baSDavid van Moolenbroek 	{
2001*b89261baSDavid van Moolenbroek 	    /* not a show stopper -- just fill in the needed values */
2002*b89261baSDavid van Moolenbroek 	    currproc->pr_fill = 0;
2003*b89261baSDavid van Moolenbroek 	    currproc->px_onpro = 0;
2004*b89261baSDavid van Moolenbroek 	}
2005*b89261baSDavid van Moolenbroek 	else
2006*b89261baSDavid van Moolenbroek 	{
2007*b89261baSDavid van Moolenbroek 	    /* copy over the values we need from prstatus */
2008*b89261baSDavid van Moolenbroek 	    currproc->pr_fill = (short)prstatus.pr_nlwp;
2009*b89261baSDavid van Moolenbroek 	    currproc->px_onpro = prstatus.pr_processor;
2010*b89261baSDavid van Moolenbroek 	}
2011*b89261baSDavid van Moolenbroek #endif
2012*b89261baSDavid van Moolenbroek 
2013*b89261baSDavid van Moolenbroek 	/*
2014*b89261baSDavid van Moolenbroek 	 * We track our own cpu% usage.
2015*b89261baSDavid van Moolenbroek 	 * We compute it based on CPU since the last update by calculating
2016*b89261baSDavid van Moolenbroek 	 * the difference in cumulative cpu time and dividing by the amount
2017*b89261baSDavid van Moolenbroek 	 * of time we measured between updates (timediff).
2018*b89261baSDavid van Moolenbroek 	 * NOTE:  Solaris 2.4 and higher do maintain CPU% in psinfo,
2019*b89261baSDavid van Moolenbroek 	 * but it does not produce the kind of results we really want,
2020*b89261baSDavid van Moolenbroek 	 * so we don't use it even though its there.
2021*b89261baSDavid van Moolenbroek 	 */
2022*b89261baSDavid van Moolenbroek 	if (lasttime.tv_sec > 0)
2023*b89261baSDavid van Moolenbroek 	{
2024*b89261baSDavid van Moolenbroek 	    percent_cpu(currproc) =
2025*b89261baSDavid van Moolenbroek 		(TIMESPEC_TO_DOUBLE(currproc->pr_time) - op->oldtime) / timediff;
2026*b89261baSDavid van Moolenbroek 	}
2027*b89261baSDavid van Moolenbroek 	else
2028*b89261baSDavid van Moolenbroek 	{
2029*b89261baSDavid van Moolenbroek 	    /* first screen -- no difference is possible */
2030*b89261baSDavid van Moolenbroek 	    percent_cpu(currproc) = 0.0;
2031*b89261baSDavid van Moolenbroek 	}
2032*b89261baSDavid van Moolenbroek 
2033*b89261baSDavid van Moolenbroek 	/* save data for next time */
2034*b89261baSDavid van Moolenbroek 	op->pid = currproc->pr_pid;
2035*b89261baSDavid van Moolenbroek 	op->oldtime = TIMESPEC_TO_DOUBLE(currproc->pr_time);
2036*b89261baSDavid van Moolenbroek 	op->owner_uid = currproc->pr_uid;
2037*b89261baSDavid van Moolenbroek 	op->seen = 1;
2038*b89261baSDavid van Moolenbroek 
2039*b89261baSDavid van Moolenbroek 	/* cache the file descriptor if we can */
2040*b89261baSDavid van Moolenbroek 	if (fd < maxfiles)
2041*b89261baSDavid van Moolenbroek 	{
2042*b89261baSDavid van Moolenbroek 	    op->fd_psinfo = fd;
2043*b89261baSDavid van Moolenbroek 	}
2044*b89261baSDavid van Moolenbroek 	else
2045*b89261baSDavid van Moolenbroek 	{
2046*b89261baSDavid van Moolenbroek 	    (void) close(fd);
2047*b89261baSDavid van Moolenbroek 	}
2048*b89261baSDavid van Moolenbroek 
2049*b89261baSDavid van Moolenbroek #ifdef USE_NEW_PROC
2050*b89261baSDavid van Moolenbroek 	/* collect up the threads */
2051*b89261baSDavid van Moolenbroek 	/* use cached lps file if it's there */
2052*b89261baSDavid van Moolenbroek 	fd = op->fd_lpsinfo;
2053*b89261baSDavid van Moolenbroek 	if (fd == -1)
2054*b89261baSDavid van Moolenbroek 	{
2055*b89261baSDavid van Moolenbroek 	    snprintf(buf, sizeof(buf), "%s/lpsinfo", direntp->d_name);
2056*b89261baSDavid van Moolenbroek 	    fd = open(buf, O_RDONLY);
2057*b89261baSDavid van Moolenbroek 	}
2058*b89261baSDavid van Moolenbroek 
2059*b89261baSDavid van Moolenbroek 	/* make sure we have a valid descriptor and the file's current size */
2060*b89261baSDavid van Moolenbroek 	if (fd >= 0 && fstat(fd, &st) != -1)
2061*b89261baSDavid van Moolenbroek 	{
2062*b89261baSDavid van Moolenbroek 	    char *p;
2063*b89261baSDavid van Moolenbroek 	    int i;
2064*b89261baSDavid van Moolenbroek 
2065*b89261baSDavid van Moolenbroek 	    /* read the whole file */
2066*b89261baSDavid van Moolenbroek 	    p = malloc(st.st_size);
2067*b89261baSDavid van Moolenbroek 	    (void)pread(fd, p, st.st_size, 0);
2068*b89261baSDavid van Moolenbroek 
2069*b89261baSDavid van Moolenbroek 	    /* cache the file descriptor if we can */
2070*b89261baSDavid van Moolenbroek 	    if (fd < maxfiles)
2071*b89261baSDavid van Moolenbroek 	    {
2072*b89261baSDavid van Moolenbroek 		op->fd_lpsinfo = fd;
2073*b89261baSDavid van Moolenbroek 	    }
2074*b89261baSDavid van Moolenbroek 	    else
2075*b89261baSDavid van Moolenbroek 	    {
2076*b89261baSDavid van Moolenbroek 		(void)close(fd);
2077*b89261baSDavid van Moolenbroek 	    }
2078*b89261baSDavid van Moolenbroek 
2079*b89261baSDavid van Moolenbroek 	    /* the file starts with a struct prheader */
2080*b89261baSDavid van Moolenbroek 	    prp = (prheader_t *)p;
2081*b89261baSDavid van Moolenbroek 	    p += sizeof(prheader_t);
2082*b89261baSDavid van Moolenbroek 
2083*b89261baSDavid van Moolenbroek 	    /* there are prp->pr_nent entries in the file */
2084*b89261baSDavid van Moolenbroek 	    for (i = 0; i < prp->pr_nent; i++)
2085*b89261baSDavid van Moolenbroek 	    {
2086*b89261baSDavid van Moolenbroek 		/* process this entry */
2087*b89261baSDavid van Moolenbroek 		lwpp = (lwpsinfo_t *)p;
2088*b89261baSDavid van Moolenbroek 		p += prp->pr_entsize;
2089*b89261baSDavid van Moolenbroek 
2090*b89261baSDavid van Moolenbroek 		/* fetch the old thread data */
2091*b89261baSDavid van Moolenbroek 		/* this hash is indexed by both pid and lwpid */
2092*b89261baSDavid van Moolenbroek 		pidthr.k_pid = currproc->pr_pid;
2093*b89261baSDavid van Moolenbroek 		pidthr.k_thr = lwpp->pr_lwpid;
2094*b89261baSDavid van Moolenbroek 		dprintf("getptable: processing %d.%d\n",
2095*b89261baSDavid van Moolenbroek 			pidthr.k_pid, pidthr.k_thr);
2096*b89261baSDavid van Moolenbroek 		op = (struct oldproc *)hash_lookup_pidthr(threadhash, pidthr);
2097*b89261baSDavid van Moolenbroek 		if (op == NULL)
2098*b89261baSDavid van Moolenbroek 		{
2099*b89261baSDavid van Moolenbroek 		    /* new thread: create an entry for it */
2100*b89261baSDavid van Moolenbroek 		    op = (struct oldproc *)malloc(sizeof(struct oldproc));
2101*b89261baSDavid van Moolenbroek 		    hash_add_pidthr(threadhash, pidthr, (void *)op);
2102*b89261baSDavid van Moolenbroek 		    op->pid = pid;
2103*b89261baSDavid van Moolenbroek 		    op->lwpid = lwpp->pr_lwpid;
2104*b89261baSDavid van Moolenbroek 		    op->oldtime = 0.0;
2105*b89261baSDavid van Moolenbroek 		    dprintf("getptable: %d.%d: new thread\n",
2106*b89261baSDavid van Moolenbroek 			    pidthr.k_pid, pidthr.k_thr);
2107*b89261baSDavid van Moolenbroek 		}
2108*b89261baSDavid van Moolenbroek 
2109*b89261baSDavid van Moolenbroek 		/* are we showing individual threads? */
2110*b89261baSDavid van Moolenbroek 		if (show_threads)
2111*b89261baSDavid van Moolenbroek 		{
2112*b89261baSDavid van Moolenbroek 		    /* yes: if this is the first thread we reuse the proc
2113*b89261baSDavid van Moolenbroek 		       entry we have, otherwise we create a new one by
2114*b89261baSDavid van Moolenbroek 		       duping the current one */
2115*b89261baSDavid van Moolenbroek 		    if (i > 0)
2116*b89261baSDavid van Moolenbroek 		    {
2117*b89261baSDavid van Moolenbroek 			currproc = procs_dup(currproc);
2118*b89261baSDavid van Moolenbroek 			numprocs++;
2119*b89261baSDavid van Moolenbroek 		    }
2120*b89261baSDavid van Moolenbroek 
2121*b89261baSDavid van Moolenbroek 		    /* yes: copy over thread-specific data */
2122*b89261baSDavid van Moolenbroek 		    currproc->pr_time = lwpp->pr_time;
2123*b89261baSDavid van Moolenbroek 		    currproc->px_state = lwpp->pr_state;
2124*b89261baSDavid van Moolenbroek 		    currproc->px_pri = lwpp->pr_pri;
2125*b89261baSDavid van Moolenbroek 		    currproc->px_onpro = lwpp->pr_onpro;
2126*b89261baSDavid van Moolenbroek 		    currproc->pr_lwp.pr_lwpid = lwpp->pr_lwpid;
2127*b89261baSDavid van Moolenbroek 
2128*b89261baSDavid van Moolenbroek 		    /* calculate percent cpu for just this thread */
2129*b89261baSDavid van Moolenbroek 		    if (lasttime.tv_sec > 0)
2130*b89261baSDavid van Moolenbroek 		    {
2131*b89261baSDavid van Moolenbroek 			percent_cpu(currproc) =
2132*b89261baSDavid van Moolenbroek 			    (TIMESPEC_TO_DOUBLE(lwpp->pr_time) - op->oldtime) /
2133*b89261baSDavid van Moolenbroek 			    timediff;
2134*b89261baSDavid van Moolenbroek 		    }
2135*b89261baSDavid van Moolenbroek 		    else
2136*b89261baSDavid van Moolenbroek 		    {
2137*b89261baSDavid van Moolenbroek 			/* first screen -- no difference is possible */
2138*b89261baSDavid van Moolenbroek 			percent_cpu(currproc) = 0.0;
2139*b89261baSDavid van Moolenbroek 		    }
2140*b89261baSDavid van Moolenbroek 
2141*b89261baSDavid van Moolenbroek 		    dprintf("getptable: %d.%d: time %.0f, state %d, pctcpu %.2f\n",
2142*b89261baSDavid van Moolenbroek 			    currproc->pr_pid, lwpp->pr_lwpid,
2143*b89261baSDavid van Moolenbroek 			    TIMESPEC_TO_DOUBLE(currproc->pr_time),
2144*b89261baSDavid van Moolenbroek 			    currproc->px_state, percent_cpu(currproc));
2145*b89261baSDavid van Moolenbroek 		}
2146*b89261baSDavid van Moolenbroek 
2147*b89261baSDavid van Moolenbroek 		/* save data for next time */
2148*b89261baSDavid van Moolenbroek 		op->oldtime = TIMESPEC_TO_DOUBLE(lwpp->pr_time);
2149*b89261baSDavid van Moolenbroek 		op->seen = 1;
2150*b89261baSDavid van Moolenbroek 	    }
2151*b89261baSDavid van Moolenbroek 	    free(p);
2152*b89261baSDavid van Moolenbroek 	}
2153*b89261baSDavid van Moolenbroek #endif
2154*b89261baSDavid van Moolenbroek 
2155*b89261baSDavid van Moolenbroek 	/* move to next */
2156*b89261baSDavid van Moolenbroek 	numprocs++;
2157*b89261baSDavid van Moolenbroek 	currproc = procs_next();
2158*b89261baSDavid van Moolenbroek     }
2159*b89261baSDavid van Moolenbroek 
2160*b89261baSDavid van Moolenbroek #ifndef USE_NEW_PROC
2161*b89261baSDavid van Moolenbroek     /* turn off root privs */
2162*b89261baSDavid van Moolenbroek     seteuid(getuid());
2163*b89261baSDavid van Moolenbroek #endif
2164*b89261baSDavid van Moolenbroek 
2165*b89261baSDavid van Moolenbroek     dprintf("getptable saw %d procs\n", numprocs);
2166*b89261baSDavid van Moolenbroek 
2167*b89261baSDavid van Moolenbroek     /* scan the hash tables and remove dead entries */
2168*b89261baSDavid van Moolenbroek     hi = hash_first_pid(prochash, &pos);
2169*b89261baSDavid van Moolenbroek     while (hi != NULL)
2170*b89261baSDavid van Moolenbroek     {
2171*b89261baSDavid van Moolenbroek 	op = (struct oldproc *)(hi->value);
2172*b89261baSDavid van Moolenbroek 	if (op->seen)
2173*b89261baSDavid van Moolenbroek 	{
2174*b89261baSDavid van Moolenbroek 	    op->seen = 0;
2175*b89261baSDavid van Moolenbroek 	}
2176*b89261baSDavid van Moolenbroek 	else
2177*b89261baSDavid van Moolenbroek 	{
2178*b89261baSDavid van Moolenbroek 	    dprintf("removing %d from prochash\n", op->pid);
2179*b89261baSDavid van Moolenbroek 	    if (op->fd_psinfo >= 0)
2180*b89261baSDavid van Moolenbroek 	    {
2181*b89261baSDavid van Moolenbroek 		(void)close(op->fd_psinfo);
2182*b89261baSDavid van Moolenbroek 	    }
2183*b89261baSDavid van Moolenbroek 	    if (op->fd_lpsinfo >= 0)
2184*b89261baSDavid van Moolenbroek 	    {
2185*b89261baSDavid van Moolenbroek 		(void)close(op->fd_lpsinfo);
2186*b89261baSDavid van Moolenbroek 	    }
2187*b89261baSDavid van Moolenbroek 	    hash_remove_pos_pid(&pos);
2188*b89261baSDavid van Moolenbroek 	    free(op);
2189*b89261baSDavid van Moolenbroek 	}
2190*b89261baSDavid van Moolenbroek 	hi = hash_next_pid(&pos);
2191*b89261baSDavid van Moolenbroek     }
2192*b89261baSDavid van Moolenbroek 
2193*b89261baSDavid van Moolenbroek     hip = hash_first_pidthr(threadhash, &pos);
2194*b89261baSDavid van Moolenbroek     while (hip != NULL)
2195*b89261baSDavid van Moolenbroek     {
2196*b89261baSDavid van Moolenbroek 	op = (struct oldproc *)(hip->value);
2197*b89261baSDavid van Moolenbroek 	if (op->seen)
2198*b89261baSDavid van Moolenbroek 	{
2199*b89261baSDavid van Moolenbroek 	    op->seen = 0;
2200*b89261baSDavid van Moolenbroek 	}
2201*b89261baSDavid van Moolenbroek 	else
2202*b89261baSDavid van Moolenbroek 	{
2203*b89261baSDavid van Moolenbroek 	    dprintf("removing %d from threadhash\n", op->pid);
2204*b89261baSDavid van Moolenbroek 	    hash_remove_pos_pidthr(&pos);
2205*b89261baSDavid van Moolenbroek 	    free(op);
2206*b89261baSDavid van Moolenbroek 	}
2207*b89261baSDavid van Moolenbroek 	hip = hash_next_pidthr(&pos);
2208*b89261baSDavid van Moolenbroek     }
2209*b89261baSDavid van Moolenbroek 
2210*b89261baSDavid van Moolenbroek     lasttime = thistime;
2211*b89261baSDavid van Moolenbroek 
2212*b89261baSDavid van Moolenbroek     return numprocs;
2213*b89261baSDavid van Moolenbroek }
2214*b89261baSDavid van Moolenbroek 
2215*b89261baSDavid van Moolenbroek /*
2216*b89261baSDavid van Moolenbroek  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
2217*b89261baSDavid van Moolenbroek  *              the process does not exist.
2218*b89261baSDavid van Moolenbroek  *              It is EXTREMLY IMPORTANT that this function work correctly.
2219*b89261baSDavid van Moolenbroek  *              If top runs setuid root (as in SVR4), then this function
2220*b89261baSDavid van Moolenbroek  *              is the only thing that stands in the way of a serious
2221*b89261baSDavid van Moolenbroek  *              security problem.  It validates requests for the "kill"
2222*b89261baSDavid van Moolenbroek  *              and "renice" commands.
2223*b89261baSDavid van Moolenbroek  */
2224*b89261baSDavid van Moolenbroek int
proc_owner(int pid)2225*b89261baSDavid van Moolenbroek proc_owner (int pid)
2226*b89261baSDavid van Moolenbroek {
2227*b89261baSDavid van Moolenbroek     struct oldproc *op;
2228*b89261baSDavid van Moolenbroek 
2229*b89261baSDavid van Moolenbroek     /* we keep this information in the hash table */
2230*b89261baSDavid van Moolenbroek     op = (struct oldproc *)hash_lookup_pid(prochash, (pid_t)pid);
2231*b89261baSDavid van Moolenbroek     if (op != NULL)
2232*b89261baSDavid van Moolenbroek     {
2233*b89261baSDavid van Moolenbroek 	return((int)(op->owner_uid));
2234*b89261baSDavid van Moolenbroek     }
2235*b89261baSDavid van Moolenbroek     return(-1);
2236*b89261baSDavid van Moolenbroek }
2237*b89261baSDavid van Moolenbroek 
2238*b89261baSDavid van Moolenbroek /* older revisions don't supply a setpriority */
2239*b89261baSDavid van Moolenbroek #if (OSREV < 55)
2240*b89261baSDavid van Moolenbroek int
setpriority(int dummy,int who,int niceval)2241*b89261baSDavid van Moolenbroek setpriority (int dummy, int who, int niceval)
2242*b89261baSDavid van Moolenbroek {
2243*b89261baSDavid van Moolenbroek     int scale;
2244*b89261baSDavid van Moolenbroek     int prio;
2245*b89261baSDavid van Moolenbroek     pcinfo_t pcinfo;
2246*b89261baSDavid van Moolenbroek     pcparms_t pcparms;
2247*b89261baSDavid van Moolenbroek     tsparms_t *tsparms;
2248*b89261baSDavid van Moolenbroek 
2249*b89261baSDavid van Moolenbroek     strcpy (pcinfo.pc_clname, "TS");
2250*b89261baSDavid van Moolenbroek     if (priocntl (0, 0, PC_GETCID, (caddr_t) & pcinfo) == -1)
2251*b89261baSDavid van Moolenbroek 	return (-1);
2252*b89261baSDavid van Moolenbroek 
2253*b89261baSDavid van Moolenbroek     prio = niceval;
2254*b89261baSDavid van Moolenbroek     if (prio > PRIO_MAX)
2255*b89261baSDavid van Moolenbroek 	prio = PRIO_MAX;
2256*b89261baSDavid van Moolenbroek     else if (prio < PRIO_MIN)
2257*b89261baSDavid van Moolenbroek 	prio = PRIO_MIN;
2258*b89261baSDavid van Moolenbroek 
2259*b89261baSDavid van Moolenbroek     tsparms = (tsparms_t *) pcparms.pc_clparms;
2260*b89261baSDavid van Moolenbroek     scale = ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri;
2261*b89261baSDavid van Moolenbroek     tsparms->ts_uprilim = tsparms->ts_upri = -(scale * prio) / 20;
2262*b89261baSDavid van Moolenbroek     pcparms.pc_cid = pcinfo.pc_cid;
2263*b89261baSDavid van Moolenbroek 
2264*b89261baSDavid van Moolenbroek     if (priocntl (P_PID, who, PC_SETPARMS, (caddr_t) & pcparms) == -1)
2265*b89261baSDavid van Moolenbroek 	return (-1);
2266*b89261baSDavid van Moolenbroek 
2267*b89261baSDavid van Moolenbroek     return (0);
2268*b89261baSDavid van Moolenbroek }
2269*b89261baSDavid van Moolenbroek #endif
2270*b89261baSDavid van Moolenbroek 
2271