1*b89261baSDavid van Moolenbroek /*
2*b89261baSDavid van Moolenbroek * Copyright (c) 1984 through 2008, William LeFebvre
3*b89261baSDavid van Moolenbroek * All rights reserved.
4*b89261baSDavid van Moolenbroek *
5*b89261baSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*b89261baSDavid van Moolenbroek * modification, are permitted provided that the following conditions are met:
7*b89261baSDavid van Moolenbroek *
8*b89261baSDavid van Moolenbroek * * Redistributions of source code must retain the above copyright
9*b89261baSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
10*b89261baSDavid van Moolenbroek *
11*b89261baSDavid van Moolenbroek * * Redistributions in binary form must reproduce the above
12*b89261baSDavid van Moolenbroek * copyright notice, this list of conditions and the following disclaimer
13*b89261baSDavid van Moolenbroek * in the documentation and/or other materials provided with the
14*b89261baSDavid van Moolenbroek * distribution.
15*b89261baSDavid van Moolenbroek *
16*b89261baSDavid van Moolenbroek * * Neither the name of William LeFebvre nor the names of other
17*b89261baSDavid van Moolenbroek * contributors may be used to endorse or promote products derived from
18*b89261baSDavid van Moolenbroek * this software without specific prior written permission.
19*b89261baSDavid van Moolenbroek *
20*b89261baSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*b89261baSDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*b89261baSDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*b89261baSDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*b89261baSDavid van Moolenbroek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*b89261baSDavid van Moolenbroek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*b89261baSDavid van Moolenbroek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*b89261baSDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*b89261baSDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*b89261baSDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*b89261baSDavid van Moolenbroek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*b89261baSDavid van Moolenbroek */
32*b89261baSDavid van Moolenbroek
33*b89261baSDavid van Moolenbroek /*
34*b89261baSDavid van Moolenbroek * top - a top users display for Unix
35*b89261baSDavid van Moolenbroek *
36*b89261baSDavid van Moolenbroek * SYNOPSIS: any hp9000 running hpux version 8 (may work with 9)
37*b89261baSDavid van Moolenbroek *
38*b89261baSDavid van Moolenbroek * DESCRIPTION:
39*b89261baSDavid van Moolenbroek * This is the machine-dependent module for HPUX 8 and is rumored to work
40*b89261baSDavid van Moolenbroek * for version 9 as well. This makes top work on (at least) the
41*b89261baSDavid van Moolenbroek * following systems:
42*b89261baSDavid van Moolenbroek * hp9000s300
43*b89261baSDavid van Moolenbroek * hp9000s700
44*b89261baSDavid van Moolenbroek * hp9000s800
45*b89261baSDavid van Moolenbroek *
46*b89261baSDavid van Moolenbroek * LIBS:
47*b89261baSDavid van Moolenbroek *
48*b89261baSDavid van Moolenbroek * AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
49*b89261baSDavid van Moolenbroek */
50*b89261baSDavid van Moolenbroek
51*b89261baSDavid van Moolenbroek #include "config.h"
52*b89261baSDavid van Moolenbroek #include <sys/types.h>
53*b89261baSDavid van Moolenbroek #include <sys/signal.h>
54*b89261baSDavid van Moolenbroek #include <sys/param.h>
55*b89261baSDavid van Moolenbroek
56*b89261baSDavid van Moolenbroek #include <stdio.h>
57*b89261baSDavid van Moolenbroek #include <nlist.h>
58*b89261baSDavid van Moolenbroek #include <math.h>
59*b89261baSDavid van Moolenbroek #include <sys/dir.h>
60*b89261baSDavid van Moolenbroek #include <sys/user.h>
61*b89261baSDavid van Moolenbroek #include <sys/proc.h>
62*b89261baSDavid van Moolenbroek #include <sys/dk.h>
63*b89261baSDavid van Moolenbroek #include <sys/vm.h>
64*b89261baSDavid van Moolenbroek #include <sys/file.h>
65*b89261baSDavid van Moolenbroek #include <sys/time.h>
66*b89261baSDavid van Moolenbroek #ifndef hpux
67*b89261baSDavid van Moolenbroek # define P_RSSIZE(p) (p)->p_rssize
68*b89261baSDavid van Moolenbroek # define P_TSIZE(p) (p)->p_tsize
69*b89261baSDavid van Moolenbroek # define P_DSIZE(p) (p)->p_dsize
70*b89261baSDavid van Moolenbroek # define P_SSIZE(p) (p)->p_ssize
71*b89261baSDavid van Moolenbroek #else
72*b89261baSDavid van Moolenbroek # include <sys/pstat.h>
73*b89261baSDavid van Moolenbroek # define __PST2P(p, field) \
74*b89261baSDavid van Moolenbroek ((p)->p_upreg ? ((struct pst_status *) (p)->p_upreg)->field : 0)
75*b89261baSDavid van Moolenbroek # define P_RSSIZE(p) __PST2P(p, pst_rssize)
76*b89261baSDavid van Moolenbroek # define P_TSIZE(p) __PST2P(p, pst_tsize)
77*b89261baSDavid van Moolenbroek # define P_DSIZE(p) __PST2P(p, pst_dsize)
78*b89261baSDavid van Moolenbroek # define P_SSIZE(p) __PST2P(p, pst_ssize)
79*b89261baSDavid van Moolenbroek #endif
80*b89261baSDavid van Moolenbroek
81*b89261baSDavid van Moolenbroek #include "top.h"
82*b89261baSDavid van Moolenbroek #include "machine.h"
83*b89261baSDavid van Moolenbroek #include "utils.h"
84*b89261baSDavid van Moolenbroek
85*b89261baSDavid van Moolenbroek #define VMUNIX "/hp-ux"
86*b89261baSDavid van Moolenbroek #define KMEM "/dev/kmem"
87*b89261baSDavid van Moolenbroek #define MEM "/dev/mem"
88*b89261baSDavid van Moolenbroek #ifdef DOSWAP
89*b89261baSDavid van Moolenbroek #define SWAP "/dev/dmem"
90*b89261baSDavid van Moolenbroek #endif
91*b89261baSDavid van Moolenbroek
92*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle. This is what it looks like: */
93*b89261baSDavid van Moolenbroek
94*b89261baSDavid van Moolenbroek struct handle
95*b89261baSDavid van Moolenbroek {
96*b89261baSDavid van Moolenbroek struct proc **next_proc; /* points to next valid proc pointer */
97*b89261baSDavid van Moolenbroek int remaining; /* number of pointers remaining */
98*b89261baSDavid van Moolenbroek };
99*b89261baSDavid van Moolenbroek
100*b89261baSDavid van Moolenbroek /* declarations for load_avg */
101*b89261baSDavid van Moolenbroek #include "loadavg.h"
102*b89261baSDavid van Moolenbroek
103*b89261baSDavid van Moolenbroek /* define what weighted cpu is. */
104*b89261baSDavid van Moolenbroek #define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
105*b89261baSDavid van Moolenbroek ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
106*b89261baSDavid van Moolenbroek
107*b89261baSDavid van Moolenbroek /* what we consider to be process size: */
108*b89261baSDavid van Moolenbroek #define PROCSIZE(pp) (P_TSIZE(pp) + P_DSIZE(pp) + P_SSIZE(pp))
109*b89261baSDavid van Moolenbroek
110*b89261baSDavid van Moolenbroek /* definitions for indices in the nlist array */
111*b89261baSDavid van Moolenbroek #define X_AVENRUN 0
112*b89261baSDavid van Moolenbroek #define X_CCPU 1
113*b89261baSDavid van Moolenbroek #define X_NPROC 2
114*b89261baSDavid van Moolenbroek #define X_PROC 3
115*b89261baSDavid van Moolenbroek #define X_TOTAL 4
116*b89261baSDavid van Moolenbroek #define X_CP_TIME 5
117*b89261baSDavid van Moolenbroek #define X_MPID 6
118*b89261baSDavid van Moolenbroek
119*b89261baSDavid van Moolenbroek /*
120*b89261baSDavid van Moolenbroek * Steinar Haug from University of Trondheim, NORWAY pointed out that
121*b89261baSDavid van Moolenbroek * the HP 9000 system 800 doesn't have _hz defined in the kernel. He
122*b89261baSDavid van Moolenbroek * provided a patch to work around this. We've improved on this patch
123*b89261baSDavid van Moolenbroek * here and set the constant X_HZ only when _hz is available in the
124*b89261baSDavid van Moolenbroek * kernel. Code in this module that uses X_HZ is surrounded with
125*b89261baSDavid van Moolenbroek * appropriate ifdefs.
126*b89261baSDavid van Moolenbroek */
127*b89261baSDavid van Moolenbroek
128*b89261baSDavid van Moolenbroek #ifndef hp9000s300
129*b89261baSDavid van Moolenbroek #define X_HZ 7
130*b89261baSDavid van Moolenbroek #endif
131*b89261baSDavid van Moolenbroek
132*b89261baSDavid van Moolenbroek
133*b89261baSDavid van Moolenbroek static struct nlist nlst[] = {
134*b89261baSDavid van Moolenbroek { "_avenrun" }, /* 0 */
135*b89261baSDavid van Moolenbroek { "_ccpu" }, /* 1 */
136*b89261baSDavid van Moolenbroek { "_nproc" }, /* 2 */
137*b89261baSDavid van Moolenbroek { "_proc" }, /* 3 */
138*b89261baSDavid van Moolenbroek { "_total" }, /* 4 */
139*b89261baSDavid van Moolenbroek { "_cp_time" }, /* 5 */
140*b89261baSDavid van Moolenbroek { "_mpid" }, /* 6 */
141*b89261baSDavid van Moolenbroek #ifdef X_HZ
142*b89261baSDavid van Moolenbroek { "_hz" }, /* 7 */
143*b89261baSDavid van Moolenbroek #endif
144*b89261baSDavid van Moolenbroek { 0 }
145*b89261baSDavid van Moolenbroek };
146*b89261baSDavid van Moolenbroek
147*b89261baSDavid van Moolenbroek /*
148*b89261baSDavid van Moolenbroek * These definitions control the format of the per-process area
149*b89261baSDavid van Moolenbroek */
150*b89261baSDavid van Moolenbroek
151*b89261baSDavid van Moolenbroek static char header[] =
152*b89261baSDavid van Moolenbroek " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
153*b89261baSDavid van Moolenbroek /* 0123456 -- field to fill in starts at header+6 */
154*b89261baSDavid van Moolenbroek #define UNAME_START 6
155*b89261baSDavid van Moolenbroek
156*b89261baSDavid van Moolenbroek #define Proc_format \
157*b89261baSDavid van Moolenbroek "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"
158*b89261baSDavid van Moolenbroek
159*b89261baSDavid van Moolenbroek
160*b89261baSDavid van Moolenbroek /* process state names for the "STATE" column of the display */
161*b89261baSDavid van Moolenbroek /* the extra nulls in the string "run" are for adding a slash and
162*b89261baSDavid van Moolenbroek the processor number when needed */
163*b89261baSDavid van Moolenbroek
164*b89261baSDavid van Moolenbroek char *state_abbrev[] =
165*b89261baSDavid van Moolenbroek {
166*b89261baSDavid van Moolenbroek "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
167*b89261baSDavid van Moolenbroek };
168*b89261baSDavid van Moolenbroek
169*b89261baSDavid van Moolenbroek
170*b89261baSDavid van Moolenbroek static int kmem;
171*b89261baSDavid van Moolenbroek
172*b89261baSDavid van Moolenbroek /* values that we stash away in _init and use in later routines */
173*b89261baSDavid van Moolenbroek
174*b89261baSDavid van Moolenbroek static double logcpu;
175*b89261baSDavid van Moolenbroek
176*b89261baSDavid van Moolenbroek /* these are retrieved from the kernel in _init */
177*b89261baSDavid van Moolenbroek
178*b89261baSDavid van Moolenbroek static unsigned long proc;
179*b89261baSDavid van Moolenbroek static int nproc;
180*b89261baSDavid van Moolenbroek static long hz;
181*b89261baSDavid van Moolenbroek static load_avg ccpu;
182*b89261baSDavid van Moolenbroek static int ncpu = 0;
183*b89261baSDavid van Moolenbroek
184*b89261baSDavid van Moolenbroek /* these are offsets obtained via nlist and used in the get_ functions */
185*b89261baSDavid van Moolenbroek static unsigned long mpid_offset;
186*b89261baSDavid van Moolenbroek static unsigned long avenrun_offset;
187*b89261baSDavid van Moolenbroek static unsigned long total_offset;
188*b89261baSDavid van Moolenbroek static unsigned long cp_time_offset;
189*b89261baSDavid van Moolenbroek
190*b89261baSDavid van Moolenbroek /* these are for calculating cpu state percentages */
191*b89261baSDavid van Moolenbroek
192*b89261baSDavid van Moolenbroek static long cp_time[CPUSTATES];
193*b89261baSDavid van Moolenbroek static long cp_old[CPUSTATES];
194*b89261baSDavid van Moolenbroek static long cp_diff[CPUSTATES];
195*b89261baSDavid van Moolenbroek
196*b89261baSDavid van Moolenbroek /* these are for detailing the process states */
197*b89261baSDavid van Moolenbroek
198*b89261baSDavid van Moolenbroek int process_states[7];
199*b89261baSDavid van Moolenbroek char *procstatenames[] = {
200*b89261baSDavid van Moolenbroek "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
201*b89261baSDavid van Moolenbroek " zombie, ", " stopped, ",
202*b89261baSDavid van Moolenbroek NULL
203*b89261baSDavid van Moolenbroek };
204*b89261baSDavid van Moolenbroek
205*b89261baSDavid van Moolenbroek /* these are for detailing the cpu states */
206*b89261baSDavid van Moolenbroek
207*b89261baSDavid van Moolenbroek int cpu_states[9];
208*b89261baSDavid van Moolenbroek char *cpustatenames[] = {
209*b89261baSDavid van Moolenbroek "usr", "nice", "sys", "idle", "", "", "", "intr", "ker",
210*b89261baSDavid van Moolenbroek NULL
211*b89261baSDavid van Moolenbroek };
212*b89261baSDavid van Moolenbroek
213*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
214*b89261baSDavid van Moolenbroek
215*b89261baSDavid van Moolenbroek long memory_stats[8];
216*b89261baSDavid van Moolenbroek char *memorynames[] = {
217*b89261baSDavid van Moolenbroek "Real: ", "K act, ", "K tot ", "Virtual: ", "K act, ",
218*b89261baSDavid van Moolenbroek "K tot, ", "K free", NULL
219*b89261baSDavid van Moolenbroek };
220*b89261baSDavid van Moolenbroek
221*b89261baSDavid van Moolenbroek /* these are for keeping track of the proc array */
222*b89261baSDavid van Moolenbroek
223*b89261baSDavid van Moolenbroek static int bytes;
224*b89261baSDavid van Moolenbroek static int pref_len;
225*b89261baSDavid van Moolenbroek static struct proc *pbase;
226*b89261baSDavid van Moolenbroek static struct proc **pref;
227*b89261baSDavid van Moolenbroek static struct pst_status *pst;
228*b89261baSDavid van Moolenbroek
229*b89261baSDavid van Moolenbroek /* these are for getting the memory statistics */
230*b89261baSDavid van Moolenbroek
231*b89261baSDavid van Moolenbroek static int pageshift; /* log base 2 of the pagesize */
232*b89261baSDavid van Moolenbroek
233*b89261baSDavid van Moolenbroek /* define pagetok in terms of pageshift */
234*b89261baSDavid van Moolenbroek
235*b89261baSDavid van Moolenbroek #define pagetok(size) ((size) << pageshift)
236*b89261baSDavid van Moolenbroek
237*b89261baSDavid van Moolenbroek /* useful externals */
238*b89261baSDavid van Moolenbroek extern int errno;
239*b89261baSDavid van Moolenbroek extern char *sys_errlist[];
240*b89261baSDavid van Moolenbroek
241*b89261baSDavid van Moolenbroek long lseek();
242*b89261baSDavid van Moolenbroek long time();
243*b89261baSDavid van Moolenbroek
244*b89261baSDavid van Moolenbroek machine_init(statics)
245*b89261baSDavid van Moolenbroek
246*b89261baSDavid van Moolenbroek struct statics *statics;
247*b89261baSDavid van Moolenbroek
248*b89261baSDavid van Moolenbroek {
249*b89261baSDavid van Moolenbroek register int i = 0;
250*b89261baSDavid van Moolenbroek register int pagesize;
251*b89261baSDavid van Moolenbroek
252*b89261baSDavid van Moolenbroek if ((kmem = open(KMEM, O_RDONLY)) == -1) {
253*b89261baSDavid van Moolenbroek perror(KMEM);
254*b89261baSDavid van Moolenbroek return(-1);
255*b89261baSDavid van Moolenbroek }
256*b89261baSDavid van Moolenbroek #ifdef hp9000s800
257*b89261baSDavid van Moolenbroek /* 800 names don't have leading underscores */
258*b89261baSDavid van Moolenbroek for (i = 0; nlst[i].n_name; nlst[i++].n_name++)
259*b89261baSDavid van Moolenbroek continue;
260*b89261baSDavid van Moolenbroek #endif
261*b89261baSDavid van Moolenbroek
262*b89261baSDavid van Moolenbroek /* get the list of symbols we want to access in the kernel */
263*b89261baSDavid van Moolenbroek (void) nlist(VMUNIX, nlst);
264*b89261baSDavid van Moolenbroek if (nlst[0].n_type == 0)
265*b89261baSDavid van Moolenbroek {
266*b89261baSDavid van Moolenbroek fprintf(stderr, "top: nlist failed\n");
267*b89261baSDavid van Moolenbroek return(-1);
268*b89261baSDavid van Moolenbroek }
269*b89261baSDavid van Moolenbroek
270*b89261baSDavid van Moolenbroek /* make sure they were all found */
271*b89261baSDavid van Moolenbroek if (check_nlist(nlst) > 0)
272*b89261baSDavid van Moolenbroek {
273*b89261baSDavid van Moolenbroek return(-1);
274*b89261baSDavid van Moolenbroek }
275*b89261baSDavid van Moolenbroek
276*b89261baSDavid van Moolenbroek /* get the symbol values out of kmem */
277*b89261baSDavid van Moolenbroek (void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
278*b89261baSDavid van Moolenbroek nlst[X_PROC].n_name);
279*b89261baSDavid van Moolenbroek (void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
280*b89261baSDavid van Moolenbroek nlst[X_NPROC].n_name);
281*b89261baSDavid van Moolenbroek (void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
282*b89261baSDavid van Moolenbroek nlst[X_CCPU].n_name);
283*b89261baSDavid van Moolenbroek #ifdef X_HZ
284*b89261baSDavid van Moolenbroek (void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
285*b89261baSDavid van Moolenbroek nlst[X_HZ].n_name);
286*b89261baSDavid van Moolenbroek #else
287*b89261baSDavid van Moolenbroek hz = HZ;
288*b89261baSDavid van Moolenbroek #endif
289*b89261baSDavid van Moolenbroek
290*b89261baSDavid van Moolenbroek /* stash away certain offsets for later use */
291*b89261baSDavid van Moolenbroek mpid_offset = nlst[X_MPID].n_value;
292*b89261baSDavid van Moolenbroek avenrun_offset = nlst[X_AVENRUN].n_value;
293*b89261baSDavid van Moolenbroek total_offset = nlst[X_TOTAL].n_value;
294*b89261baSDavid van Moolenbroek cp_time_offset = nlst[X_CP_TIME].n_value;
295*b89261baSDavid van Moolenbroek
296*b89261baSDavid van Moolenbroek /* this is used in calculating WCPU -- calculate it ahead of time */
297*b89261baSDavid van Moolenbroek logcpu = log(loaddouble(ccpu));
298*b89261baSDavid van Moolenbroek
299*b89261baSDavid van Moolenbroek /* allocate space for proc structure array and array of pointers */
300*b89261baSDavid van Moolenbroek bytes = nproc * sizeof(struct proc);
301*b89261baSDavid van Moolenbroek pbase = (struct proc *)malloc(bytes);
302*b89261baSDavid van Moolenbroek pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
303*b89261baSDavid van Moolenbroek pst = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
304*b89261baSDavid van Moolenbroek
305*b89261baSDavid van Moolenbroek /* Just in case ... */
306*b89261baSDavid van Moolenbroek if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
307*b89261baSDavid van Moolenbroek {
308*b89261baSDavid van Moolenbroek fprintf(stderr, "top: can't allocate sufficient memory\n");
309*b89261baSDavid van Moolenbroek return(-1);
310*b89261baSDavid van Moolenbroek }
311*b89261baSDavid van Moolenbroek
312*b89261baSDavid van Moolenbroek /* get the page size with "getpagesize" and calculate pageshift from it */
313*b89261baSDavid van Moolenbroek pagesize = getpagesize();
314*b89261baSDavid van Moolenbroek pageshift = 0;
315*b89261baSDavid van Moolenbroek while (pagesize > 1)
316*b89261baSDavid van Moolenbroek {
317*b89261baSDavid van Moolenbroek pageshift++;
318*b89261baSDavid van Moolenbroek pagesize >>= 1;
319*b89261baSDavid van Moolenbroek }
320*b89261baSDavid van Moolenbroek
321*b89261baSDavid van Moolenbroek /* we only need the amount of log(2)1024 for our conversion */
322*b89261baSDavid van Moolenbroek pageshift -= LOG1024;
323*b89261baSDavid van Moolenbroek
324*b89261baSDavid van Moolenbroek /* fill in the statics information */
325*b89261baSDavid van Moolenbroek statics->procstate_names = procstatenames;
326*b89261baSDavid van Moolenbroek statics->cpustate_names = cpustatenames;
327*b89261baSDavid van Moolenbroek statics->memory_names = memorynames;
328*b89261baSDavid van Moolenbroek
329*b89261baSDavid van Moolenbroek /* all done! */
330*b89261baSDavid van Moolenbroek return(0);
331*b89261baSDavid van Moolenbroek }
332*b89261baSDavid van Moolenbroek
format_header(uname_field)333*b89261baSDavid van Moolenbroek char *format_header(uname_field)
334*b89261baSDavid van Moolenbroek
335*b89261baSDavid van Moolenbroek register char *uname_field;
336*b89261baSDavid van Moolenbroek
337*b89261baSDavid van Moolenbroek {
338*b89261baSDavid van Moolenbroek register char *ptr;
339*b89261baSDavid van Moolenbroek
340*b89261baSDavid van Moolenbroek ptr = header + UNAME_START;
341*b89261baSDavid van Moolenbroek while (*uname_field != '\0')
342*b89261baSDavid van Moolenbroek {
343*b89261baSDavid van Moolenbroek *ptr++ = *uname_field++;
344*b89261baSDavid van Moolenbroek }
345*b89261baSDavid van Moolenbroek
346*b89261baSDavid van Moolenbroek return(header);
347*b89261baSDavid van Moolenbroek }
348*b89261baSDavid van Moolenbroek
349*b89261baSDavid van Moolenbroek void
get_system_info(si)350*b89261baSDavid van Moolenbroek get_system_info(si)
351*b89261baSDavid van Moolenbroek
352*b89261baSDavid van Moolenbroek struct system_info *si;
353*b89261baSDavid van Moolenbroek
354*b89261baSDavid van Moolenbroek {
355*b89261baSDavid van Moolenbroek load_avg avenrun[3];
356*b89261baSDavid van Moolenbroek long total;
357*b89261baSDavid van Moolenbroek
358*b89261baSDavid van Moolenbroek /* get the cp_time array */
359*b89261baSDavid van Moolenbroek (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
360*b89261baSDavid van Moolenbroek "_cp_time");
361*b89261baSDavid van Moolenbroek
362*b89261baSDavid van Moolenbroek /* get load average array */
363*b89261baSDavid van Moolenbroek (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
364*b89261baSDavid van Moolenbroek "_avenrun");
365*b89261baSDavid van Moolenbroek
366*b89261baSDavid van Moolenbroek /* get mpid -- process id of last process */
367*b89261baSDavid van Moolenbroek (void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
368*b89261baSDavid van Moolenbroek "_mpid");
369*b89261baSDavid van Moolenbroek
370*b89261baSDavid van Moolenbroek /* convert load averages to doubles */
371*b89261baSDavid van Moolenbroek {
372*b89261baSDavid van Moolenbroek register int i;
373*b89261baSDavid van Moolenbroek register double *infoloadp;
374*b89261baSDavid van Moolenbroek register load_avg *sysloadp;
375*b89261baSDavid van Moolenbroek
376*b89261baSDavid van Moolenbroek infoloadp = si->load_avg;
377*b89261baSDavid van Moolenbroek sysloadp = avenrun;
378*b89261baSDavid van Moolenbroek for (i = 0; i < 3; i++)
379*b89261baSDavid van Moolenbroek {
380*b89261baSDavid van Moolenbroek *infoloadp++ = loaddouble(*sysloadp++);
381*b89261baSDavid van Moolenbroek }
382*b89261baSDavid van Moolenbroek }
383*b89261baSDavid van Moolenbroek
384*b89261baSDavid van Moolenbroek /* convert cp_time counts to percentages */
385*b89261baSDavid van Moolenbroek total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
386*b89261baSDavid van Moolenbroek
387*b89261baSDavid van Moolenbroek /* sum memory statistics */
388*b89261baSDavid van Moolenbroek {
389*b89261baSDavid van Moolenbroek struct vmtotal total;
390*b89261baSDavid van Moolenbroek
391*b89261baSDavid van Moolenbroek /* get total -- systemwide main memory usage structure */
392*b89261baSDavid van Moolenbroek (void) getkval(total_offset, (int *)(&total), sizeof(total),
393*b89261baSDavid van Moolenbroek "_total");
394*b89261baSDavid van Moolenbroek /* convert memory stats to Kbytes */
395*b89261baSDavid van Moolenbroek memory_stats[0] = -1;
396*b89261baSDavid van Moolenbroek memory_stats[1] = pagetok(total.t_arm);
397*b89261baSDavid van Moolenbroek memory_stats[2] = pagetok(total.t_rm);
398*b89261baSDavid van Moolenbroek memory_stats[3] = -1;
399*b89261baSDavid van Moolenbroek memory_stats[4] = pagetok(total.t_avm);
400*b89261baSDavid van Moolenbroek memory_stats[5] = pagetok(total.t_vm);
401*b89261baSDavid van Moolenbroek memory_stats[6] = pagetok(total.t_free);
402*b89261baSDavid van Moolenbroek }
403*b89261baSDavid van Moolenbroek
404*b89261baSDavid van Moolenbroek /* set arrays and strings */
405*b89261baSDavid van Moolenbroek si->cpustates = cpu_states;
406*b89261baSDavid van Moolenbroek si->memory = memory_stats;
407*b89261baSDavid van Moolenbroek }
408*b89261baSDavid van Moolenbroek
409*b89261baSDavid van Moolenbroek static struct handle handle;
410*b89261baSDavid van Moolenbroek
get_process_info(si,sel,i)411*b89261baSDavid van Moolenbroek caddr_t get_process_info(si, sel, i)
412*b89261baSDavid van Moolenbroek
413*b89261baSDavid van Moolenbroek struct system_info *si;
414*b89261baSDavid van Moolenbroek struct process_select *sel;
415*b89261baSDavid van Moolenbroek int i;
416*b89261baSDavid van Moolenbroek
417*b89261baSDavid van Moolenbroek {
418*b89261baSDavid van Moolenbroek register int i;
419*b89261baSDavid van Moolenbroek register int total_procs;
420*b89261baSDavid van Moolenbroek register int active_procs;
421*b89261baSDavid van Moolenbroek register struct proc **prefp;
422*b89261baSDavid van Moolenbroek register struct proc *pp;
423*b89261baSDavid van Moolenbroek
424*b89261baSDavid van Moolenbroek /* these are copied out of sel for speed */
425*b89261baSDavid van Moolenbroek int show_idle;
426*b89261baSDavid van Moolenbroek int show_system;
427*b89261baSDavid van Moolenbroek int show_uid;
428*b89261baSDavid van Moolenbroek int show_command;
429*b89261baSDavid van Moolenbroek
430*b89261baSDavid van Moolenbroek /* read all the proc structures in one fell swoop */
431*b89261baSDavid van Moolenbroek (void) getkval(proc, (int *)pbase, bytes, "proc array");
432*b89261baSDavid van Moolenbroek for (i = 0; i < nproc; ++i) {
433*b89261baSDavid van Moolenbroek if (pstat(PSTAT_PROC, &pst[i], sizeof(pst[i]), 0, pbase[i].p_pid) != 1)
434*b89261baSDavid van Moolenbroek pbase[i].p_upreg = (preg_t *) 0;
435*b89261baSDavid van Moolenbroek else
436*b89261baSDavid van Moolenbroek pbase[i].p_upreg = (preg_t *) &pst[i];
437*b89261baSDavid van Moolenbroek pbase[i].p_nice = pst[i].pst_nice;
438*b89261baSDavid van Moolenbroek pbase[i].p_cpticks = pst[i].pst_cpticks;
439*b89261baSDavid van Moolenbroek }
440*b89261baSDavid van Moolenbroek
441*b89261baSDavid van Moolenbroek
442*b89261baSDavid van Moolenbroek /* get a pointer to the states summary array */
443*b89261baSDavid van Moolenbroek si->procstates = process_states;
444*b89261baSDavid van Moolenbroek
445*b89261baSDavid van Moolenbroek /* set up flags which define what we are going to select */
446*b89261baSDavid van Moolenbroek show_idle = sel->idle;
447*b89261baSDavid van Moolenbroek show_system = sel->system;
448*b89261baSDavid van Moolenbroek show_uid = sel->uid != -1;
449*b89261baSDavid van Moolenbroek show_command = sel->command != NULL;
450*b89261baSDavid van Moolenbroek
451*b89261baSDavid van Moolenbroek /* count up process states and get pointers to interesting procs */
452*b89261baSDavid van Moolenbroek total_procs = 0;
453*b89261baSDavid van Moolenbroek active_procs = 0;
454*b89261baSDavid van Moolenbroek memset((char *)process_states, 0, sizeof(process_states));
455*b89261baSDavid van Moolenbroek prefp = pref;
456*b89261baSDavid van Moolenbroek for (pp = pbase, i = 0; i < nproc; pp++, i++)
457*b89261baSDavid van Moolenbroek {
458*b89261baSDavid van Moolenbroek /*
459*b89261baSDavid van Moolenbroek * Place pointers to each valid proc structure in pref[].
460*b89261baSDavid van Moolenbroek * Process slots that are actually in use have a non-zero
461*b89261baSDavid van Moolenbroek * status field. Processes with SSYS set are system
462*b89261baSDavid van Moolenbroek * processes---these get ignored unless show_sysprocs is set.
463*b89261baSDavid van Moolenbroek */
464*b89261baSDavid van Moolenbroek if (pp->p_stat != 0 &&
465*b89261baSDavid van Moolenbroek (show_system || ((pp->p_flag & SSYS) == 0)))
466*b89261baSDavid van Moolenbroek {
467*b89261baSDavid van Moolenbroek total_procs++;
468*b89261baSDavid van Moolenbroek process_states[pp->p_stat]++;
469*b89261baSDavid van Moolenbroek if ((pp->p_stat != SZOMB) &&
470*b89261baSDavid van Moolenbroek (show_idle || (pp->p_pctcpu != 0) || (pp->p_stat == SRUN)) &&
471*b89261baSDavid van Moolenbroek (!show_uid || pp->p_uid == (uid_t)sel->uid))
472*b89261baSDavid van Moolenbroek {
473*b89261baSDavid van Moolenbroek *prefp++ = pp;
474*b89261baSDavid van Moolenbroek active_procs++;
475*b89261baSDavid van Moolenbroek }
476*b89261baSDavid van Moolenbroek }
477*b89261baSDavid van Moolenbroek }
478*b89261baSDavid van Moolenbroek
479*b89261baSDavid van Moolenbroek /* if requested, sort the "interesting" processes */
480*b89261baSDavid van Moolenbroek if (compare != NULL)
481*b89261baSDavid van Moolenbroek {
482*b89261baSDavid van Moolenbroek qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compare);
483*b89261baSDavid van Moolenbroek }
484*b89261baSDavid van Moolenbroek
485*b89261baSDavid van Moolenbroek /* remember active and total counts */
486*b89261baSDavid van Moolenbroek si->p_total = total_procs;
487*b89261baSDavid van Moolenbroek si->p_active = pref_len = active_procs;
488*b89261baSDavid van Moolenbroek
489*b89261baSDavid van Moolenbroek /* pass back a handle */
490*b89261baSDavid van Moolenbroek handle.next_proc = pref;
491*b89261baSDavid van Moolenbroek handle.remaining = active_procs;
492*b89261baSDavid van Moolenbroek return((caddr_t)&handle);
493*b89261baSDavid van Moolenbroek }
494*b89261baSDavid van Moolenbroek
495*b89261baSDavid van Moolenbroek char fmt[MAX_COLS]; /* static area where result is built */
496*b89261baSDavid van Moolenbroek
format_next_process(handle,get_userid)497*b89261baSDavid van Moolenbroek char *format_next_process(handle, get_userid)
498*b89261baSDavid van Moolenbroek
499*b89261baSDavid van Moolenbroek caddr_t handle;
500*b89261baSDavid van Moolenbroek char *(*get_userid)();
501*b89261baSDavid van Moolenbroek
502*b89261baSDavid van Moolenbroek {
503*b89261baSDavid van Moolenbroek register struct proc *pp;
504*b89261baSDavid van Moolenbroek register long cputime;
505*b89261baSDavid van Moolenbroek register double pct;
506*b89261baSDavid van Moolenbroek int where;
507*b89261baSDavid van Moolenbroek struct user u;
508*b89261baSDavid van Moolenbroek struct handle *hp;
509*b89261baSDavid van Moolenbroek
510*b89261baSDavid van Moolenbroek /* find and remember the next proc structure */
511*b89261baSDavid van Moolenbroek hp = (struct handle *)handle;
512*b89261baSDavid van Moolenbroek pp = *(hp->next_proc++);
513*b89261baSDavid van Moolenbroek hp->remaining--;
514*b89261baSDavid van Moolenbroek
515*b89261baSDavid van Moolenbroek
516*b89261baSDavid van Moolenbroek /* get the process's user struct and set cputime */
517*b89261baSDavid van Moolenbroek where = getu(pp, &u);
518*b89261baSDavid van Moolenbroek if (where == -1)
519*b89261baSDavid van Moolenbroek {
520*b89261baSDavid van Moolenbroek (void) strcpy(u.u_comm, "<swapped>");
521*b89261baSDavid van Moolenbroek cputime = 0;
522*b89261baSDavid van Moolenbroek }
523*b89261baSDavid van Moolenbroek else
524*b89261baSDavid van Moolenbroek {
525*b89261baSDavid van Moolenbroek
526*b89261baSDavid van Moolenbroek
527*b89261baSDavid van Moolenbroek /* set u_comm for system processes */
528*b89261baSDavid van Moolenbroek if (u.u_comm[0] == '\0')
529*b89261baSDavid van Moolenbroek {
530*b89261baSDavid van Moolenbroek if (pp->p_pid == 0)
531*b89261baSDavid van Moolenbroek {
532*b89261baSDavid van Moolenbroek (void) strcpy(u.u_comm, "Swapper");
533*b89261baSDavid van Moolenbroek }
534*b89261baSDavid van Moolenbroek else if (pp->p_pid == 2)
535*b89261baSDavid van Moolenbroek {
536*b89261baSDavid van Moolenbroek (void) strcpy(u.u_comm, "Pager");
537*b89261baSDavid van Moolenbroek }
538*b89261baSDavid van Moolenbroek }
539*b89261baSDavid van Moolenbroek if (where == 1) {
540*b89261baSDavid van Moolenbroek /*
541*b89261baSDavid van Moolenbroek * Print swapped processes as <pname>
542*b89261baSDavid van Moolenbroek */
543*b89261baSDavid van Moolenbroek char buf[sizeof(u.u_comm)];
544*b89261baSDavid van Moolenbroek (void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
545*b89261baSDavid van Moolenbroek u.u_comm[0] = '<';
546*b89261baSDavid van Moolenbroek (void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
547*b89261baSDavid van Moolenbroek u.u_comm[sizeof(u.u_comm) - 2] = '\0';
548*b89261baSDavid van Moolenbroek (void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
549*b89261baSDavid van Moolenbroek u.u_comm[sizeof(u.u_comm) - 1] = '\0';
550*b89261baSDavid van Moolenbroek }
551*b89261baSDavid van Moolenbroek
552*b89261baSDavid van Moolenbroek cputime = __PST2P(pp, pst_cptickstotal) / hz;
553*b89261baSDavid van Moolenbroek }
554*b89261baSDavid van Moolenbroek
555*b89261baSDavid van Moolenbroek /* calculate the base for cpu percentages */
556*b89261baSDavid van Moolenbroek pct = pctdouble(pp->p_pctcpu);
557*b89261baSDavid van Moolenbroek
558*b89261baSDavid van Moolenbroek /* format this entry */
559*b89261baSDavid van Moolenbroek sprintf(fmt,
560*b89261baSDavid van Moolenbroek Proc_format,
561*b89261baSDavid van Moolenbroek pp->p_pid,
562*b89261baSDavid van Moolenbroek (*get_userid)(pp->p_uid),
563*b89261baSDavid van Moolenbroek pp->p_pri - PZERO,
564*b89261baSDavid van Moolenbroek pp->p_nice - NZERO,
565*b89261baSDavid van Moolenbroek format_k(pagetok(PROCSIZE(pp))),
566*b89261baSDavid van Moolenbroek format_k(pagetok(P_RSSIZE(pp))),
567*b89261baSDavid van Moolenbroek state_abbrev[pp->p_stat],
568*b89261baSDavid van Moolenbroek format_time(cputime),
569*b89261baSDavid van Moolenbroek 100.0 * weighted_cpu(pct, pp),
570*b89261baSDavid van Moolenbroek 100.0 * pct,
571*b89261baSDavid van Moolenbroek printable(u.u_comm));
572*b89261baSDavid van Moolenbroek
573*b89261baSDavid van Moolenbroek /* return the result */
574*b89261baSDavid van Moolenbroek return(fmt);
575*b89261baSDavid van Moolenbroek }
576*b89261baSDavid van Moolenbroek
577*b89261baSDavid van Moolenbroek /*
578*b89261baSDavid van Moolenbroek * getu(p, u) - get the user structure for the process whose proc structure
579*b89261baSDavid van Moolenbroek * is pointed to by p. The user structure is put in the buffer pointed
580*b89261baSDavid van Moolenbroek * to by u. Return 0 if successful, -1 on failure (such as the process
581*b89261baSDavid van Moolenbroek * being swapped out).
582*b89261baSDavid van Moolenbroek */
583*b89261baSDavid van Moolenbroek
584*b89261baSDavid van Moolenbroek
getu(p,u)585*b89261baSDavid van Moolenbroek getu(p, u)
586*b89261baSDavid van Moolenbroek
587*b89261baSDavid van Moolenbroek register struct proc *p;
588*b89261baSDavid van Moolenbroek struct user *u;
589*b89261baSDavid van Moolenbroek
590*b89261baSDavid van Moolenbroek {
591*b89261baSDavid van Moolenbroek struct pst_status *ps;
592*b89261baSDavid van Moolenbroek char *s, *c;
593*b89261baSDavid van Moolenbroek int i;
594*b89261baSDavid van Moolenbroek
595*b89261baSDavid van Moolenbroek if ((ps = (struct pst_status *) p->p_upreg) == NULL)
596*b89261baSDavid van Moolenbroek return -1;
597*b89261baSDavid van Moolenbroek
598*b89261baSDavid van Moolenbroek memset(u, 0, sizeof(struct user));
599*b89261baSDavid van Moolenbroek c = ps->pst_cmd;
600*b89261baSDavid van Moolenbroek ps->pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */
601*b89261baSDavid van Moolenbroek s = strtok(ps->pst_cmd, "\t \n");
602*b89261baSDavid van Moolenbroek
603*b89261baSDavid van Moolenbroek if (c = strrchr(s, '/'))
604*b89261baSDavid van Moolenbroek c++;
605*b89261baSDavid van Moolenbroek else
606*b89261baSDavid van Moolenbroek c = s;
607*b89261baSDavid van Moolenbroek if (*c == '-')
608*b89261baSDavid van Moolenbroek c++;
609*b89261baSDavid van Moolenbroek i = 0;
610*b89261baSDavid van Moolenbroek for (; i < MAXCOMLEN; i++) {
611*b89261baSDavid van Moolenbroek if (*c == '\0' || *c == ' ' || *c == '/')
612*b89261baSDavid van Moolenbroek break;
613*b89261baSDavid van Moolenbroek u->u_comm[i] = *c++;
614*b89261baSDavid van Moolenbroek }
615*b89261baSDavid van Moolenbroek #ifndef DOSWAP
616*b89261baSDavid van Moolenbroek return ((p->p_flag & SLOAD) == 0 ? 1 : 0);
617*b89261baSDavid van Moolenbroek #endif
618*b89261baSDavid van Moolenbroek return(0);
619*b89261baSDavid van Moolenbroek }
620*b89261baSDavid van Moolenbroek
621*b89261baSDavid van Moolenbroek /*
622*b89261baSDavid van Moolenbroek * check_nlist(nlst) - checks the nlist to see if any symbols were not
623*b89261baSDavid van Moolenbroek * found. For every symbol that was not found, a one-line
624*b89261baSDavid van Moolenbroek * message is printed to stderr. The routine returns the
625*b89261baSDavid van Moolenbroek * number of symbols NOT found.
626*b89261baSDavid van Moolenbroek */
627*b89261baSDavid van Moolenbroek
check_nlist(nlst)628*b89261baSDavid van Moolenbroek int check_nlist(nlst)
629*b89261baSDavid van Moolenbroek
630*b89261baSDavid van Moolenbroek register struct nlist *nlst;
631*b89261baSDavid van Moolenbroek
632*b89261baSDavid van Moolenbroek {
633*b89261baSDavid van Moolenbroek register int i;
634*b89261baSDavid van Moolenbroek
635*b89261baSDavid van Moolenbroek /* check to see if we got ALL the symbols we requested */
636*b89261baSDavid van Moolenbroek /* this will write one line to stderr for every symbol not found */
637*b89261baSDavid van Moolenbroek
638*b89261baSDavid van Moolenbroek i = 0;
639*b89261baSDavid van Moolenbroek while (nlst->n_name != NULL)
640*b89261baSDavid van Moolenbroek {
641*b89261baSDavid van Moolenbroek if (nlst->n_type == 0)
642*b89261baSDavid van Moolenbroek {
643*b89261baSDavid van Moolenbroek /* this one wasn't found */
644*b89261baSDavid van Moolenbroek fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
645*b89261baSDavid van Moolenbroek i = 1;
646*b89261baSDavid van Moolenbroek }
647*b89261baSDavid van Moolenbroek nlst++;
648*b89261baSDavid van Moolenbroek }
649*b89261baSDavid van Moolenbroek
650*b89261baSDavid van Moolenbroek return(i);
651*b89261baSDavid van Moolenbroek }
652*b89261baSDavid van Moolenbroek
653*b89261baSDavid van Moolenbroek
654*b89261baSDavid van Moolenbroek /*
655*b89261baSDavid van Moolenbroek * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
656*b89261baSDavid van Moolenbroek * "offset" is the byte offset into the kernel for the desired value,
657*b89261baSDavid van Moolenbroek * "ptr" points to a buffer into which the value is retrieved,
658*b89261baSDavid van Moolenbroek * "size" is the size of the buffer (and the object to retrieve),
659*b89261baSDavid van Moolenbroek * "refstr" is a reference string used when printing error meessages,
660*b89261baSDavid van Moolenbroek * if "refstr" starts with a '!', then a failure on read will not
661*b89261baSDavid van Moolenbroek * be fatal (this may seem like a silly way to do things, but I
662*b89261baSDavid van Moolenbroek * really didn't want the overhead of another argument).
663*b89261baSDavid van Moolenbroek *
664*b89261baSDavid van Moolenbroek */
665*b89261baSDavid van Moolenbroek
getkval(offset,ptr,size,refstr)666*b89261baSDavid van Moolenbroek getkval(offset, ptr, size, refstr)
667*b89261baSDavid van Moolenbroek
668*b89261baSDavid van Moolenbroek unsigned long offset;
669*b89261baSDavid van Moolenbroek int *ptr;
670*b89261baSDavid van Moolenbroek int size;
671*b89261baSDavid van Moolenbroek char *refstr;
672*b89261baSDavid van Moolenbroek
673*b89261baSDavid van Moolenbroek {
674*b89261baSDavid van Moolenbroek if (lseek(kmem, (long)offset, L_SET) == -1) {
675*b89261baSDavid van Moolenbroek if (*refstr == '!')
676*b89261baSDavid van Moolenbroek refstr++;
677*b89261baSDavid van Moolenbroek (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
678*b89261baSDavid van Moolenbroek refstr, strerror(errno));
679*b89261baSDavid van Moolenbroek quit(23);
680*b89261baSDavid van Moolenbroek }
681*b89261baSDavid van Moolenbroek if (read(kmem, (char *) ptr, size) == -1) {
682*b89261baSDavid van Moolenbroek if (*refstr == '!')
683*b89261baSDavid van Moolenbroek return(0);
684*b89261baSDavid van Moolenbroek else {
685*b89261baSDavid van Moolenbroek (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
686*b89261baSDavid van Moolenbroek refstr, strerror(errno));
687*b89261baSDavid van Moolenbroek quit(23);
688*b89261baSDavid van Moolenbroek }
689*b89261baSDavid van Moolenbroek }
690*b89261baSDavid van Moolenbroek return(1);
691*b89261baSDavid van Moolenbroek }
692*b89261baSDavid van Moolenbroek
693*b89261baSDavid van Moolenbroek /* comparison routine for qsort */
694*b89261baSDavid van Moolenbroek
695*b89261baSDavid van Moolenbroek /*
696*b89261baSDavid van Moolenbroek * proc_compare - comparison function for "qsort"
697*b89261baSDavid van Moolenbroek * Compares the resource consumption of two processes using five
698*b89261baSDavid van Moolenbroek * distinct keys. The keys (in descending order of importance) are:
699*b89261baSDavid van Moolenbroek * percent cpu, cpu ticks, state, resident set size, total virtual
700*b89261baSDavid van Moolenbroek * memory usage. The process states are ordered as follows (from least
701*b89261baSDavid van Moolenbroek * to most important): WAIT, zombie, sleep, stop, start, run. The
702*b89261baSDavid van Moolenbroek * array declaration below maps a process state index into a number
703*b89261baSDavid van Moolenbroek * that reflects this ordering.
704*b89261baSDavid van Moolenbroek */
705*b89261baSDavid van Moolenbroek
706*b89261baSDavid van Moolenbroek static unsigned char sorted_state[] =
707*b89261baSDavid van Moolenbroek {
708*b89261baSDavid van Moolenbroek 0, /* not used */
709*b89261baSDavid van Moolenbroek 3, /* sleep */
710*b89261baSDavid van Moolenbroek 1, /* ABANDONED (WAIT) */
711*b89261baSDavid van Moolenbroek 6, /* run */
712*b89261baSDavid van Moolenbroek 5, /* start */
713*b89261baSDavid van Moolenbroek 2, /* zombie */
714*b89261baSDavid van Moolenbroek 4 /* stop */
715*b89261baSDavid van Moolenbroek };
716*b89261baSDavid van Moolenbroek
717*b89261baSDavid van Moolenbroek proc_compare(pp1, pp2)
718*b89261baSDavid van Moolenbroek
719*b89261baSDavid van Moolenbroek struct proc **pp1;
720*b89261baSDavid van Moolenbroek struct proc **pp2;
721*b89261baSDavid van Moolenbroek
722*b89261baSDavid van Moolenbroek {
723*b89261baSDavid van Moolenbroek register struct proc *p1;
724*b89261baSDavid van Moolenbroek register struct proc *p2;
725*b89261baSDavid van Moolenbroek register int result;
726*b89261baSDavid van Moolenbroek register pctcpu lresult;
727*b89261baSDavid van Moolenbroek
728*b89261baSDavid van Moolenbroek /* remove one level of indirection */
729*b89261baSDavid van Moolenbroek p1 = *pp1;
730*b89261baSDavid van Moolenbroek p2 = *pp2;
731*b89261baSDavid van Moolenbroek
732*b89261baSDavid van Moolenbroek /* compare percent cpu (pctcpu) */
733*b89261baSDavid van Moolenbroek if ((lresult = p2->p_pctcpu - p1->p_pctcpu) == 0)
734*b89261baSDavid van Moolenbroek {
735*b89261baSDavid van Moolenbroek /* use cpticks to break the tie */
736*b89261baSDavid van Moolenbroek if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
737*b89261baSDavid van Moolenbroek {
738*b89261baSDavid van Moolenbroek /* use process state to break the tie */
739*b89261baSDavid van Moolenbroek if ((result = sorted_state[p2->p_stat] -
740*b89261baSDavid van Moolenbroek sorted_state[p1->p_stat]) == 0)
741*b89261baSDavid van Moolenbroek {
742*b89261baSDavid van Moolenbroek /* use priority to break the tie */
743*b89261baSDavid van Moolenbroek if ((result = p2->p_pri - p1->p_pri) == 0)
744*b89261baSDavid van Moolenbroek {
745*b89261baSDavid van Moolenbroek /* use resident set size (rssize) to break the tie */
746*b89261baSDavid van Moolenbroek if ((result = P_RSSIZE(p2) - P_RSSIZE(p1)) == 0)
747*b89261baSDavid van Moolenbroek {
748*b89261baSDavid van Moolenbroek /* use total memory to break the tie */
749*b89261baSDavid van Moolenbroek result = PROCSIZE(p2) - PROCSIZE(p1);
750*b89261baSDavid van Moolenbroek }
751*b89261baSDavid van Moolenbroek }
752*b89261baSDavid van Moolenbroek }
753*b89261baSDavid van Moolenbroek }
754*b89261baSDavid van Moolenbroek }
755*b89261baSDavid van Moolenbroek else
756*b89261baSDavid van Moolenbroek {
757*b89261baSDavid van Moolenbroek result = lresult < 0 ? -1 : 1;
758*b89261baSDavid van Moolenbroek }
759*b89261baSDavid van Moolenbroek
760*b89261baSDavid van Moolenbroek return(result);
761*b89261baSDavid van Moolenbroek }
762*b89261baSDavid van Moolenbroek
763*b89261baSDavid van Moolenbroek
764*b89261baSDavid van Moolenbroek void (*signal(sig, func))()
765*b89261baSDavid van Moolenbroek int sig;
766*b89261baSDavid van Moolenbroek void (*func)();
767*b89261baSDavid van Moolenbroek {
768*b89261baSDavid van Moolenbroek struct sigvec osv, sv;
769*b89261baSDavid van Moolenbroek
770*b89261baSDavid van Moolenbroek /*
771*b89261baSDavid van Moolenbroek * XXX: we should block the signal we are playing with,
772*b89261baSDavid van Moolenbroek * in case we get interrupted in here.
773*b89261baSDavid van Moolenbroek */
774*b89261baSDavid van Moolenbroek if (sigvector(sig, NULL, &osv) == -1)
775*b89261baSDavid van Moolenbroek return BADSIG;
776*b89261baSDavid van Moolenbroek sv = osv;
777*b89261baSDavid van Moolenbroek sv.sv_handler = func;
778*b89261baSDavid van Moolenbroek #ifdef SV_BSDSIG
779*b89261baSDavid van Moolenbroek sv.sv_flags |= SV_BSDSIG;
780*b89261baSDavid van Moolenbroek #endif
781*b89261baSDavid van Moolenbroek if (sigvector(sig, &sv, NULL) == -1)
782*b89261baSDavid van Moolenbroek return BADSIG;
783*b89261baSDavid van Moolenbroek return osv.sv_handler;
784*b89261baSDavid van Moolenbroek }
785*b89261baSDavid van Moolenbroek
getpagesize()786*b89261baSDavid van Moolenbroek int getpagesize() { return 1 << PGSHIFT; }
787*b89261baSDavid van Moolenbroek
setpriority(a,b,c)788*b89261baSDavid van Moolenbroek int setpriority(a, b, c) { errno = ENOSYS; return -1; }
789*b89261baSDavid van Moolenbroek
790*b89261baSDavid van Moolenbroek /*
791*b89261baSDavid van Moolenbroek * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
792*b89261baSDavid van Moolenbroek * the process does not exist.
793*b89261baSDavid van Moolenbroek * It is EXTREMLY IMPORTANT that this function work correctly.
794*b89261baSDavid van Moolenbroek * If top runs setuid root (as in SVR4), then this function
795*b89261baSDavid van Moolenbroek * is the only thing that stands in the way of a serious
796*b89261baSDavid van Moolenbroek * security problem. It validates requests for the "kill"
797*b89261baSDavid van Moolenbroek * and "renice" commands.
798*b89261baSDavid van Moolenbroek */
799*b89261baSDavid van Moolenbroek
proc_owner(pid)800*b89261baSDavid van Moolenbroek int proc_owner(pid)
801*b89261baSDavid van Moolenbroek
802*b89261baSDavid van Moolenbroek int pid;
803*b89261baSDavid van Moolenbroek
804*b89261baSDavid van Moolenbroek {
805*b89261baSDavid van Moolenbroek register int cnt;
806*b89261baSDavid van Moolenbroek register struct proc **prefp;
807*b89261baSDavid van Moolenbroek register struct proc *pp;
808*b89261baSDavid van Moolenbroek
809*b89261baSDavid van Moolenbroek prefp = pref;
810*b89261baSDavid van Moolenbroek cnt = pref_len;
811*b89261baSDavid van Moolenbroek while (--cnt >= 0)
812*b89261baSDavid van Moolenbroek {
813*b89261baSDavid van Moolenbroek if ((pp = *prefp++)->p_pid == (pid_t)pid)
814*b89261baSDavid van Moolenbroek {
815*b89261baSDavid van Moolenbroek return((int)pp->p_uid);
816*b89261baSDavid van Moolenbroek }
817*b89261baSDavid van Moolenbroek }
818*b89261baSDavid van Moolenbroek return(-1);
819*b89261baSDavid van Moolenbroek }
820