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