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