xref: /minix3/external/bsd/top/dist/machine/m_linuxthr.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:  2.x with thread eliding
37*b89261baSDavid van Moolenbroek  *
38*b89261baSDavid van Moolenbroek  * DESCRIPTION:
39*b89261baSDavid van Moolenbroek  * This is the machine-dependent module for Linux 2.x that elides threads
40*b89261baSDavid van Moolenbroek  * from the output.
41*b89261baSDavid van Moolenbroek  *
42*b89261baSDavid van Moolenbroek  * CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
43*b89261baSDavid van Moolenbroek  *
44*b89261baSDavid van Moolenbroek  * TERMCAP: -lcurses
45*b89261baSDavid van Moolenbroek  *
46*b89261baSDavid van Moolenbroek  * AUTHOR: Richard Henderson <rth@tamu.edu>
47*b89261baSDavid van Moolenbroek  * Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru>
48*b89261baSDavid van Moolenbroek  * Ported to 2.4 by William LeFebvre
49*b89261baSDavid van Moolenbroek  * Thread eliding by William LeFebvre
50*b89261baSDavid van Moolenbroek  */
51*b89261baSDavid van Moolenbroek 
52*b89261baSDavid van Moolenbroek #include "config.h"
53*b89261baSDavid van Moolenbroek 
54*b89261baSDavid van Moolenbroek #include <sys/types.h>
55*b89261baSDavid van Moolenbroek #include <stdio.h>
56*b89261baSDavid van Moolenbroek #include <fcntl.h>
57*b89261baSDavid van Moolenbroek #include <unistd.h>
58*b89261baSDavid van Moolenbroek #include <stdlib.h>
59*b89261baSDavid van Moolenbroek #include <errno.h>
60*b89261baSDavid van Moolenbroek #include <dirent.h>
61*b89261baSDavid van Moolenbroek #include <string.h>
62*b89261baSDavid van Moolenbroek #include <math.h>
63*b89261baSDavid van Moolenbroek #include <ctype.h>
64*b89261baSDavid van Moolenbroek #include <sys/time.h>
65*b89261baSDavid van Moolenbroek #include <sys/stat.h>
66*b89261baSDavid van Moolenbroek #include <sys/vfs.h>
67*b89261baSDavid van Moolenbroek 
68*b89261baSDavid van Moolenbroek #include <sys/param.h>		/* for HZ */
69*b89261baSDavid van Moolenbroek #include <asm/page.h>		/* for PAGE_SHIFT */
70*b89261baSDavid van Moolenbroek 
71*b89261baSDavid van Moolenbroek #if 0
72*b89261baSDavid van Moolenbroek #include <linux/proc_fs.h>	/* for PROC_SUPER_MAGIC */
73*b89261baSDavid van Moolenbroek #else
74*b89261baSDavid van Moolenbroek #define PROC_SUPER_MAGIC 0x9fa0
75*b89261baSDavid van Moolenbroek #endif
76*b89261baSDavid van Moolenbroek 
77*b89261baSDavid van Moolenbroek #include "top.h"
78*b89261baSDavid van Moolenbroek #include "machine.h"
79*b89261baSDavid van Moolenbroek #include "utils.h"
80*b89261baSDavid van Moolenbroek 
81*b89261baSDavid van Moolenbroek #define PROCFS "/proc"
82*b89261baSDavid van Moolenbroek extern char *myname;
83*b89261baSDavid van Moolenbroek 
84*b89261baSDavid van Moolenbroek /*=PROCESS INFORMATION==================================================*/
85*b89261baSDavid van Moolenbroek 
86*b89261baSDavid van Moolenbroek struct top_proc
87*b89261baSDavid van Moolenbroek {
88*b89261baSDavid van Moolenbroek     pid_t pid;
89*b89261baSDavid van Moolenbroek     pid_t ppid;
90*b89261baSDavid van Moolenbroek     uid_t uid;
91*b89261baSDavid van Moolenbroek     char *name;
92*b89261baSDavid van Moolenbroek     int pri, nice;
93*b89261baSDavid van Moolenbroek     unsigned long size, rss;	/* in k */
94*b89261baSDavid van Moolenbroek     int state;
95*b89261baSDavid van Moolenbroek     unsigned long time;
96*b89261baSDavid van Moolenbroek     unsigned long start_time;
97*b89261baSDavid van Moolenbroek     unsigned long otime;
98*b89261baSDavid van Moolenbroek     unsigned long start_code;
99*b89261baSDavid van Moolenbroek     unsigned long end_code;
100*b89261baSDavid van Moolenbroek     unsigned long start_stack;
101*b89261baSDavid van Moolenbroek     unsigned int threads;
102*b89261baSDavid van Moolenbroek     double pcpu, wcpu;
103*b89261baSDavid van Moolenbroek     struct top_proc *next;
104*b89261baSDavid van Moolenbroek };
105*b89261baSDavid van Moolenbroek 
106*b89261baSDavid van Moolenbroek 
107*b89261baSDavid van Moolenbroek /*=STATE IDENT STRINGS==================================================*/
108*b89261baSDavid van Moolenbroek 
109*b89261baSDavid van Moolenbroek #define NPROCSTATES 7
110*b89261baSDavid van Moolenbroek static char *state_abbrev[NPROCSTATES+1] =
111*b89261baSDavid van Moolenbroek {
112*b89261baSDavid van Moolenbroek     "", "run", "sleep", "disk", "zomb", "stop", "swap",
113*b89261baSDavid van Moolenbroek     NULL
114*b89261baSDavid van Moolenbroek };
115*b89261baSDavid van Moolenbroek 
116*b89261baSDavid van Moolenbroek static char *procstatenames[NPROCSTATES+1] =
117*b89261baSDavid van Moolenbroek {
118*b89261baSDavid van Moolenbroek     "", " running, ", " sleeping, ", " uninterruptable, ",
119*b89261baSDavid van Moolenbroek     " zombie, ", " stopped, ", " swapping, ",
120*b89261baSDavid van Moolenbroek     NULL
121*b89261baSDavid van Moolenbroek };
122*b89261baSDavid van Moolenbroek 
123*b89261baSDavid van Moolenbroek #define NCPUSTATES 4
124*b89261baSDavid van Moolenbroek static char *cpustatenames[NCPUSTATES+1] =
125*b89261baSDavid van Moolenbroek {
126*b89261baSDavid van Moolenbroek     "user", "nice", "system", "idle",
127*b89261baSDavid van Moolenbroek     NULL
128*b89261baSDavid van Moolenbroek };
129*b89261baSDavid van Moolenbroek 
130*b89261baSDavid van Moolenbroek #define MEMUSED    0
131*b89261baSDavid van Moolenbroek #define MEMFREE    1
132*b89261baSDavid van Moolenbroek #define MEMSHARED  2
133*b89261baSDavid van Moolenbroek #define MEMBUFFERS 3
134*b89261baSDavid van Moolenbroek #define MEMCACHED  4
135*b89261baSDavid van Moolenbroek #define NMEMSTATS  5
136*b89261baSDavid van Moolenbroek static char *memorynames[NMEMSTATS+1] =
137*b89261baSDavid van Moolenbroek {
138*b89261baSDavid van Moolenbroek     "K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",
139*b89261baSDavid van Moolenbroek     NULL
140*b89261baSDavid van Moolenbroek };
141*b89261baSDavid van Moolenbroek 
142*b89261baSDavid van Moolenbroek #define SWAPUSED   0
143*b89261baSDavid van Moolenbroek #define SWAPFREE   1
144*b89261baSDavid van Moolenbroek #define SWAPCACHED 2
145*b89261baSDavid van Moolenbroek #define NSWAPSTATS 3
146*b89261baSDavid van Moolenbroek static char *swapnames[NSWAPSTATS+1] =
147*b89261baSDavid van Moolenbroek {
148*b89261baSDavid van Moolenbroek     "K used, ", "K free, ", "K cached",
149*b89261baSDavid van Moolenbroek     NULL
150*b89261baSDavid van Moolenbroek };
151*b89261baSDavid van Moolenbroek 
152*b89261baSDavid van Moolenbroek static char fmt_header[] =
153*b89261baSDavid van Moolenbroek "  PID X        THR PRI NICE  SIZE   RES STATE   TIME    CPU COMMAND";
154*b89261baSDavid van Moolenbroek 
155*b89261baSDavid van Moolenbroek /* these are names given to allowed sorting orders -- first is default */
156*b89261baSDavid van Moolenbroek char *ordernames[] =
157*b89261baSDavid van Moolenbroek {"cpu", "size", "res", "time", "command", NULL};
158*b89261baSDavid van Moolenbroek 
159*b89261baSDavid van Moolenbroek /* forward definitions for comparison functions */
160*b89261baSDavid van Moolenbroek int compare_cpu();
161*b89261baSDavid van Moolenbroek int compare_size();
162*b89261baSDavid van Moolenbroek int compare_res();
163*b89261baSDavid van Moolenbroek int compare_time();
164*b89261baSDavid van Moolenbroek int compare_cmd();
165*b89261baSDavid van Moolenbroek 
166*b89261baSDavid van Moolenbroek int (*proc_compares[])() = {
167*b89261baSDavid van Moolenbroek     compare_cpu,
168*b89261baSDavid van Moolenbroek     compare_size,
169*b89261baSDavid van Moolenbroek     compare_res,
170*b89261baSDavid van Moolenbroek     compare_time,
171*b89261baSDavid van Moolenbroek     compare_cmd,
172*b89261baSDavid van Moolenbroek     NULL };
173*b89261baSDavid van Moolenbroek 
174*b89261baSDavid van Moolenbroek /*=SYSTEM STATE INFO====================================================*/
175*b89261baSDavid van Moolenbroek 
176*b89261baSDavid van Moolenbroek /* these are for calculating cpu state percentages */
177*b89261baSDavid van Moolenbroek 
178*b89261baSDavid van Moolenbroek static long cp_time[NCPUSTATES];
179*b89261baSDavid van Moolenbroek static long cp_old[NCPUSTATES];
180*b89261baSDavid van Moolenbroek static long cp_diff[NCPUSTATES];
181*b89261baSDavid van Moolenbroek 
182*b89261baSDavid van Moolenbroek /* for calculating the exponential average */
183*b89261baSDavid van Moolenbroek 
184*b89261baSDavid van Moolenbroek static struct timeval lasttime;
185*b89261baSDavid van Moolenbroek 
186*b89261baSDavid van Moolenbroek /* these are for keeping track of processes */
187*b89261baSDavid van Moolenbroek 
188*b89261baSDavid van Moolenbroek #define HASH_SIZE	     (1003)
189*b89261baSDavid van Moolenbroek #define INITIAL_ACTIVE_SIZE  (256)
190*b89261baSDavid van Moolenbroek #define PROCBLOCK_SIZE       (32)
191*b89261baSDavid van Moolenbroek static struct top_proc *ptable[HASH_SIZE];
192*b89261baSDavid van Moolenbroek static struct top_proc **pactive;
193*b89261baSDavid van Moolenbroek static struct top_proc **nextactive;
194*b89261baSDavid van Moolenbroek static unsigned int activesize = 0;
195*b89261baSDavid van Moolenbroek static time_t boottime = -1;
196*b89261baSDavid van Moolenbroek 
197*b89261baSDavid van Moolenbroek /* these are for passing data back to the machine independant portion */
198*b89261baSDavid van Moolenbroek 
199*b89261baSDavid van Moolenbroek static int cpu_states[NCPUSTATES];
200*b89261baSDavid van Moolenbroek static int process_states[NPROCSTATES];
201*b89261baSDavid van Moolenbroek static long memory_stats[NMEMSTATS];
202*b89261baSDavid van Moolenbroek static long swap_stats[NSWAPSTATS];
203*b89261baSDavid van Moolenbroek 
204*b89261baSDavid van Moolenbroek /* usefull macros */
205*b89261baSDavid van Moolenbroek #define bytetok(x)	(((x) + 512) >> 10)
206*b89261baSDavid van Moolenbroek #define pagetok(x)	((x) << (PAGE_SHIFT - 10))
207*b89261baSDavid van Moolenbroek #define HASH(x)		(((x) * 1686629713U) % HASH_SIZE)
208*b89261baSDavid van Moolenbroek 
209*b89261baSDavid van Moolenbroek /*======================================================================*/
210*b89261baSDavid van Moolenbroek 
211*b89261baSDavid van Moolenbroek static inline char *
skip_ws(const char * p)212*b89261baSDavid van Moolenbroek skip_ws(const char *p)
213*b89261baSDavid van Moolenbroek {
214*b89261baSDavid van Moolenbroek     while (isspace(*p)) p++;
215*b89261baSDavid van Moolenbroek     return (char *)p;
216*b89261baSDavid van Moolenbroek }
217*b89261baSDavid van Moolenbroek 
218*b89261baSDavid van Moolenbroek static inline char *
skip_token(const char * p)219*b89261baSDavid van Moolenbroek skip_token(const char *p)
220*b89261baSDavid van Moolenbroek {
221*b89261baSDavid van Moolenbroek     while (isspace(*p)) p++;
222*b89261baSDavid van Moolenbroek     while (*p && !isspace(*p)) p++;
223*b89261baSDavid van Moolenbroek     return (char *)p;
224*b89261baSDavid van Moolenbroek }
225*b89261baSDavid van Moolenbroek 
226*b89261baSDavid van Moolenbroek static void
xfrm_cmdline(char * p,int len)227*b89261baSDavid van Moolenbroek xfrm_cmdline(char *p, int len)
228*b89261baSDavid van Moolenbroek {
229*b89261baSDavid van Moolenbroek     while (--len > 0)
230*b89261baSDavid van Moolenbroek     {
231*b89261baSDavid van Moolenbroek 	if (*p == '\0')
232*b89261baSDavid van Moolenbroek 	{
233*b89261baSDavid van Moolenbroek 	    *p = ' ';
234*b89261baSDavid van Moolenbroek 	}
235*b89261baSDavid van Moolenbroek 	p++;
236*b89261baSDavid van Moolenbroek     }
237*b89261baSDavid van Moolenbroek }
238*b89261baSDavid van Moolenbroek 
239*b89261baSDavid van Moolenbroek static void
update_procname(struct top_proc * proc,char * cmd)240*b89261baSDavid van Moolenbroek update_procname(struct top_proc *proc, char *cmd)
241*b89261baSDavid van Moolenbroek 
242*b89261baSDavid van Moolenbroek {
243*b89261baSDavid van Moolenbroek     printable(cmd);
244*b89261baSDavid van Moolenbroek 
245*b89261baSDavid van Moolenbroek     if (proc->name == NULL)
246*b89261baSDavid van Moolenbroek     {
247*b89261baSDavid van Moolenbroek 	proc->name = strdup(cmd);
248*b89261baSDavid van Moolenbroek     }
249*b89261baSDavid van Moolenbroek     else if (strcmp(proc->name, cmd) != 0)
250*b89261baSDavid van Moolenbroek     {
251*b89261baSDavid van Moolenbroek 	free(proc->name);
252*b89261baSDavid van Moolenbroek 	proc->name = strdup(cmd);
253*b89261baSDavid van Moolenbroek     }
254*b89261baSDavid van Moolenbroek }
255*b89261baSDavid van Moolenbroek 
256*b89261baSDavid van Moolenbroek 
257*b89261baSDavid van Moolenbroek 
258*b89261baSDavid van Moolenbroek 
259*b89261baSDavid van Moolenbroek /*
260*b89261baSDavid van Moolenbroek  * Process structures are allocated and freed as needed.  Here we
261*b89261baSDavid van Moolenbroek  * keep big pools of them, adding more pool as needed.  When a
262*b89261baSDavid van Moolenbroek  * top_proc structure is freed, it is added to a freelist and reused.
263*b89261baSDavid van Moolenbroek  */
264*b89261baSDavid van Moolenbroek 
265*b89261baSDavid van Moolenbroek static struct top_proc *freelist = NULL;
266*b89261baSDavid van Moolenbroek static struct top_proc *procblock = NULL;
267*b89261baSDavid van Moolenbroek static struct top_proc *procmax = NULL;
268*b89261baSDavid van Moolenbroek 
269*b89261baSDavid van Moolenbroek static struct top_proc *
new_proc()270*b89261baSDavid van Moolenbroek new_proc()
271*b89261baSDavid van Moolenbroek {
272*b89261baSDavid van Moolenbroek     struct top_proc *p;
273*b89261baSDavid van Moolenbroek 
274*b89261baSDavid van Moolenbroek     if (freelist)
275*b89261baSDavid van Moolenbroek     {
276*b89261baSDavid van Moolenbroek 	p = freelist;
277*b89261baSDavid van Moolenbroek 	freelist = freelist->next;
278*b89261baSDavid van Moolenbroek     }
279*b89261baSDavid van Moolenbroek     else if (procblock)
280*b89261baSDavid van Moolenbroek     {
281*b89261baSDavid van Moolenbroek 	p = procblock;
282*b89261baSDavid van Moolenbroek 	if (++procblock >= procmax)
283*b89261baSDavid van Moolenbroek 	{
284*b89261baSDavid van Moolenbroek 	    procblock = NULL;
285*b89261baSDavid van Moolenbroek 	}
286*b89261baSDavid van Moolenbroek     }
287*b89261baSDavid van Moolenbroek     else
288*b89261baSDavid van Moolenbroek     {
289*b89261baSDavid van Moolenbroek 	p = procblock = (struct top_proc *)calloc(PROCBLOCK_SIZE,
290*b89261baSDavid van Moolenbroek 						  sizeof(struct top_proc));
291*b89261baSDavid van Moolenbroek 	procmax = procblock++ + PROCBLOCK_SIZE;
292*b89261baSDavid van Moolenbroek     }
293*b89261baSDavid van Moolenbroek 
294*b89261baSDavid van Moolenbroek     /* initialization */
295*b89261baSDavid van Moolenbroek     if (p->name != NULL)
296*b89261baSDavid van Moolenbroek     {
297*b89261baSDavid van Moolenbroek 	free(p->name);
298*b89261baSDavid van Moolenbroek 	p->name = NULL;
299*b89261baSDavid van Moolenbroek     }
300*b89261baSDavid van Moolenbroek 
301*b89261baSDavid van Moolenbroek     return p;
302*b89261baSDavid van Moolenbroek }
303*b89261baSDavid van Moolenbroek 
304*b89261baSDavid van Moolenbroek static void
free_proc(struct top_proc * proc)305*b89261baSDavid van Moolenbroek free_proc(struct top_proc *proc)
306*b89261baSDavid van Moolenbroek {
307*b89261baSDavid van Moolenbroek     proc->next = freelist;
308*b89261baSDavid van Moolenbroek     freelist = proc;
309*b89261baSDavid van Moolenbroek }
310*b89261baSDavid van Moolenbroek 
311*b89261baSDavid van Moolenbroek 
312*b89261baSDavid van Moolenbroek int
machine_init(struct statics * statics)313*b89261baSDavid van Moolenbroek machine_init(struct statics *statics)
314*b89261baSDavid van Moolenbroek 
315*b89261baSDavid van Moolenbroek {
316*b89261baSDavid van Moolenbroek     /* make sure the proc filesystem is mounted */
317*b89261baSDavid van Moolenbroek     {
318*b89261baSDavid van Moolenbroek 	struct statfs sb;
319*b89261baSDavid van Moolenbroek 	if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
320*b89261baSDavid van Moolenbroek 	{
321*b89261baSDavid van Moolenbroek 	    fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n",
322*b89261baSDavid van Moolenbroek 		    myname);
323*b89261baSDavid van Moolenbroek 	    return -1;
324*b89261baSDavid van Moolenbroek 	}
325*b89261baSDavid van Moolenbroek     }
326*b89261baSDavid van Moolenbroek 
327*b89261baSDavid van Moolenbroek     /* chdir to the proc filesystem to make things easier */
328*b89261baSDavid van Moolenbroek     chdir(PROCFS);
329*b89261baSDavid van Moolenbroek 
330*b89261baSDavid van Moolenbroek     /* get a boottime */
331*b89261baSDavid van Moolenbroek     {
332*b89261baSDavid van Moolenbroek 	int fd;
333*b89261baSDavid van Moolenbroek 	char buff[64];
334*b89261baSDavid van Moolenbroek 	char *p;
335*b89261baSDavid van Moolenbroek 	unsigned long uptime;
336*b89261baSDavid van Moolenbroek 	struct timeval tv;
337*b89261baSDavid van Moolenbroek 
338*b89261baSDavid van Moolenbroek 	if ((fd = open("uptime", 0)) != -1)
339*b89261baSDavid van Moolenbroek 	{
340*b89261baSDavid van Moolenbroek 	    if (read(fd, buff, sizeof(buff)) > 0)
341*b89261baSDavid van Moolenbroek 	    {
342*b89261baSDavid van Moolenbroek 		uptime = strtoul(buff, &p, 10);
343*b89261baSDavid van Moolenbroek 		gettimeofday(&tv, 0);
344*b89261baSDavid van Moolenbroek 		boottime = tv.tv_sec - uptime;
345*b89261baSDavid van Moolenbroek 	    }
346*b89261baSDavid van Moolenbroek 	    close(fd);
347*b89261baSDavid van Moolenbroek 	}
348*b89261baSDavid van Moolenbroek     }
349*b89261baSDavid van Moolenbroek 
350*b89261baSDavid van Moolenbroek     /* fill in the statics information */
351*b89261baSDavid van Moolenbroek     statics->procstate_names = procstatenames;
352*b89261baSDavid van Moolenbroek     statics->cpustate_names = cpustatenames;
353*b89261baSDavid van Moolenbroek     statics->memory_names = memorynames;
354*b89261baSDavid van Moolenbroek     statics->swap_names = swapnames;
355*b89261baSDavid van Moolenbroek     statics->order_names = ordernames;
356*b89261baSDavid van Moolenbroek     statics->boottime = boottime;
357*b89261baSDavid van Moolenbroek     statics->flags.fullcmds = 1;
358*b89261baSDavid van Moolenbroek     statics->flags.warmup = 1;
359*b89261baSDavid van Moolenbroek 
360*b89261baSDavid van Moolenbroek     /* allocate needed space */
361*b89261baSDavid van Moolenbroek     pactive = (struct top_proc **)malloc(sizeof(struct top_proc *) * INITIAL_ACTIVE_SIZE);
362*b89261baSDavid van Moolenbroek     activesize = INITIAL_ACTIVE_SIZE;
363*b89261baSDavid van Moolenbroek 
364*b89261baSDavid van Moolenbroek     /* make sure the hash table is empty */
365*b89261baSDavid van Moolenbroek     memset(ptable, 0, HASH_SIZE * sizeof(struct top_proc *));
366*b89261baSDavid van Moolenbroek 
367*b89261baSDavid van Moolenbroek     /* all done! */
368*b89261baSDavid van Moolenbroek     return 0;
369*b89261baSDavid van Moolenbroek }
370*b89261baSDavid van Moolenbroek 
371*b89261baSDavid van Moolenbroek 
372*b89261baSDavid van Moolenbroek void
get_system_info(struct system_info * info)373*b89261baSDavid van Moolenbroek get_system_info(struct system_info *info)
374*b89261baSDavid van Moolenbroek 
375*b89261baSDavid van Moolenbroek {
376*b89261baSDavid van Moolenbroek     char buffer[4096+1];
377*b89261baSDavid van Moolenbroek     int fd, len;
378*b89261baSDavid van Moolenbroek     char *p;
379*b89261baSDavid van Moolenbroek 
380*b89261baSDavid van Moolenbroek     /* get load averages */
381*b89261baSDavid van Moolenbroek 
382*b89261baSDavid van Moolenbroek     if ((fd = open("loadavg", O_RDONLY)) != -1)
383*b89261baSDavid van Moolenbroek     {
384*b89261baSDavid van Moolenbroek 	if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
385*b89261baSDavid van Moolenbroek 	{
386*b89261baSDavid van Moolenbroek 	    buffer[len] = '\0';
387*b89261baSDavid van Moolenbroek 
388*b89261baSDavid van Moolenbroek 	    info->load_avg[0] = strtod(buffer, &p);
389*b89261baSDavid van Moolenbroek 	    info->load_avg[1] = strtod(p, &p);
390*b89261baSDavid van Moolenbroek 	    info->load_avg[2] = strtod(p, &p);
391*b89261baSDavid van Moolenbroek 	    p = skip_token(p);			/* skip running/tasks */
392*b89261baSDavid van Moolenbroek 	    p = skip_ws(p);
393*b89261baSDavid van Moolenbroek 	    if (*p)
394*b89261baSDavid van Moolenbroek 	    {
395*b89261baSDavid van Moolenbroek 		info->last_pid = atoi(p);
396*b89261baSDavid van Moolenbroek 	    }
397*b89261baSDavid van Moolenbroek 	    else
398*b89261baSDavid van Moolenbroek 	    {
399*b89261baSDavid van Moolenbroek 		info->last_pid = -1;
400*b89261baSDavid van Moolenbroek 	    }
401*b89261baSDavid van Moolenbroek 	}
402*b89261baSDavid van Moolenbroek 	close(fd);
403*b89261baSDavid van Moolenbroek     }
404*b89261baSDavid van Moolenbroek 
405*b89261baSDavid van Moolenbroek     /* get the cpu time info */
406*b89261baSDavid van Moolenbroek     if ((fd = open("stat", O_RDONLY)) != -1)
407*b89261baSDavid van Moolenbroek     {
408*b89261baSDavid van Moolenbroek 	if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
409*b89261baSDavid van Moolenbroek 	{
410*b89261baSDavid van Moolenbroek 	    buffer[len] = '\0';
411*b89261baSDavid van Moolenbroek 	    p = skip_token(buffer);			/* "cpu" */
412*b89261baSDavid van Moolenbroek 	    cp_time[0] = strtoul(p, &p, 0);
413*b89261baSDavid van Moolenbroek 	    cp_time[1] = strtoul(p, &p, 0);
414*b89261baSDavid van Moolenbroek 	    cp_time[2] = strtoul(p, &p, 0);
415*b89261baSDavid van Moolenbroek 	    cp_time[3] = strtoul(p, &p, 0);
416*b89261baSDavid van Moolenbroek 
417*b89261baSDavid van Moolenbroek 	    /* convert cp_time counts to percentages */
418*b89261baSDavid van Moolenbroek 	    percentages(4, cpu_states, cp_time, cp_old, cp_diff);
419*b89261baSDavid van Moolenbroek 	}
420*b89261baSDavid van Moolenbroek 	close(fd);
421*b89261baSDavid van Moolenbroek     }
422*b89261baSDavid van Moolenbroek 
423*b89261baSDavid van Moolenbroek     /* get system wide memory usage */
424*b89261baSDavid van Moolenbroek     if ((fd = open("meminfo", O_RDONLY)) != -1)
425*b89261baSDavid van Moolenbroek     {
426*b89261baSDavid van Moolenbroek 	char *p;
427*b89261baSDavid van Moolenbroek 	int mem = 0;
428*b89261baSDavid van Moolenbroek 	int swap = 0;
429*b89261baSDavid van Moolenbroek 	unsigned long memtotal = 0;
430*b89261baSDavid van Moolenbroek 	unsigned long memfree = 0;
431*b89261baSDavid van Moolenbroek 	unsigned long swaptotal = 0;
432*b89261baSDavid van Moolenbroek 
433*b89261baSDavid van Moolenbroek 	if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
434*b89261baSDavid van Moolenbroek 	{
435*b89261baSDavid van Moolenbroek 	    buffer[len] = '\0';
436*b89261baSDavid van Moolenbroek 	    p = buffer-1;
437*b89261baSDavid van Moolenbroek 
438*b89261baSDavid van Moolenbroek 	    /* iterate thru the lines */
439*b89261baSDavid van Moolenbroek 	    while (p != NULL)
440*b89261baSDavid van Moolenbroek 	    {
441*b89261baSDavid van Moolenbroek 		p++;
442*b89261baSDavid van Moolenbroek 		if (p[0] == ' ' || p[0] == '\t')
443*b89261baSDavid van Moolenbroek 		{
444*b89261baSDavid van Moolenbroek 		    /* skip */
445*b89261baSDavid van Moolenbroek 		}
446*b89261baSDavid van Moolenbroek 		else if (strncmp(p, "Mem:", 4) == 0)
447*b89261baSDavid van Moolenbroek 		{
448*b89261baSDavid van Moolenbroek 		    p = skip_token(p);			/* "Mem:" */
449*b89261baSDavid van Moolenbroek 		    p = skip_token(p);			/* total memory */
450*b89261baSDavid van Moolenbroek 		    memory_stats[MEMUSED] = strtoul(p, &p, 10);
451*b89261baSDavid van Moolenbroek 		    memory_stats[MEMFREE] = strtoul(p, &p, 10);
452*b89261baSDavid van Moolenbroek 		    memory_stats[MEMSHARED] = strtoul(p, &p, 10);
453*b89261baSDavid van Moolenbroek 		    memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
454*b89261baSDavid van Moolenbroek 		    memory_stats[MEMCACHED] = strtoul(p, &p, 10);
455*b89261baSDavid van Moolenbroek 		    memory_stats[MEMUSED] = bytetok(memory_stats[MEMUSED]);
456*b89261baSDavid van Moolenbroek 		    memory_stats[MEMFREE] = bytetok(memory_stats[MEMFREE]);
457*b89261baSDavid van Moolenbroek 		    memory_stats[MEMSHARED] = bytetok(memory_stats[MEMSHARED]);
458*b89261baSDavid van Moolenbroek 		    memory_stats[MEMBUFFERS] = bytetok(memory_stats[MEMBUFFERS]);
459*b89261baSDavid van Moolenbroek 		    memory_stats[MEMCACHED] = bytetok(memory_stats[MEMCACHED]);
460*b89261baSDavid van Moolenbroek 		    mem = 1;
461*b89261baSDavid van Moolenbroek 		}
462*b89261baSDavid van Moolenbroek 		else if (strncmp(p, "Swap:", 5) == 0)
463*b89261baSDavid van Moolenbroek 		{
464*b89261baSDavid van Moolenbroek 		    p = skip_token(p);			/* "Swap:" */
465*b89261baSDavid van Moolenbroek 		    p = skip_token(p);			/* total swap */
466*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPUSED] = strtoul(p, &p, 10);
467*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPFREE] = strtoul(p, &p, 10);
468*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPUSED] = bytetok(swap_stats[SWAPUSED]);
469*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPFREE] = bytetok(swap_stats[SWAPFREE]);
470*b89261baSDavid van Moolenbroek 		    swap = 1;
471*b89261baSDavid van Moolenbroek 		}
472*b89261baSDavid van Moolenbroek 		else if (!mem && strncmp(p, "MemTotal:", 9) == 0)
473*b89261baSDavid van Moolenbroek 		{
474*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
475*b89261baSDavid van Moolenbroek 		    memtotal = strtoul(p, &p, 10);
476*b89261baSDavid van Moolenbroek 		}
477*b89261baSDavid van Moolenbroek 		else if (!mem && memtotal > 0 && strncmp(p, "MemFree:", 8) == 0)
478*b89261baSDavid van Moolenbroek 		{
479*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
480*b89261baSDavid van Moolenbroek 		    memfree = strtoul(p, &p, 10);
481*b89261baSDavid van Moolenbroek 		    memory_stats[MEMUSED] = memtotal - memfree;
482*b89261baSDavid van Moolenbroek 		    memory_stats[MEMFREE] = memfree;
483*b89261baSDavid van Moolenbroek 		}
484*b89261baSDavid van Moolenbroek 		else if (!mem && strncmp(p, "MemShared:", 10) == 0)
485*b89261baSDavid van Moolenbroek 		{
486*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
487*b89261baSDavid van Moolenbroek 		    memory_stats[MEMSHARED] = strtoul(p, &p, 10);
488*b89261baSDavid van Moolenbroek 		}
489*b89261baSDavid van Moolenbroek 		else if (!mem && strncmp(p, "Buffers:", 8) == 0)
490*b89261baSDavid van Moolenbroek 		{
491*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
492*b89261baSDavid van Moolenbroek 		    memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
493*b89261baSDavid van Moolenbroek 		}
494*b89261baSDavid van Moolenbroek 		else if (!mem && strncmp(p, "Cached:", 7) == 0)
495*b89261baSDavid van Moolenbroek 		{
496*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
497*b89261baSDavid van Moolenbroek 		    memory_stats[MEMCACHED] = strtoul(p, &p, 10);
498*b89261baSDavid van Moolenbroek 		}
499*b89261baSDavid van Moolenbroek 		else if (!swap && strncmp(p, "SwapTotal:", 10) == 0)
500*b89261baSDavid van Moolenbroek 		{
501*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
502*b89261baSDavid van Moolenbroek 		    swaptotal = strtoul(p, &p, 10);
503*b89261baSDavid van Moolenbroek 		}
504*b89261baSDavid van Moolenbroek 		else if (!swap && swaptotal > 0 && strncmp(p, "SwapFree:", 9) == 0)
505*b89261baSDavid van Moolenbroek 		{
506*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
507*b89261baSDavid van Moolenbroek 		    memfree = strtoul(p, &p, 10);
508*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPUSED] = swaptotal - memfree;
509*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPFREE] = memfree;
510*b89261baSDavid van Moolenbroek 		}
511*b89261baSDavid van Moolenbroek 		else if (!mem && strncmp(p, "SwapCached:", 11) == 0)
512*b89261baSDavid van Moolenbroek 		{
513*b89261baSDavid van Moolenbroek 		    p = skip_token(p);
514*b89261baSDavid van Moolenbroek 		    swap_stats[SWAPCACHED] = strtoul(p, &p, 10);
515*b89261baSDavid van Moolenbroek 		}
516*b89261baSDavid van Moolenbroek 
517*b89261baSDavid van Moolenbroek 		/* move to the next line */
518*b89261baSDavid van Moolenbroek 		p = strchr(p, '\n');
519*b89261baSDavid van Moolenbroek 	    }
520*b89261baSDavid van Moolenbroek 	}
521*b89261baSDavid van Moolenbroek 	close(fd);
522*b89261baSDavid van Moolenbroek     }
523*b89261baSDavid van Moolenbroek 
524*b89261baSDavid van Moolenbroek     /* set arrays and strings */
525*b89261baSDavid van Moolenbroek     info->cpustates = cpu_states;
526*b89261baSDavid van Moolenbroek     info->memory = memory_stats;
527*b89261baSDavid van Moolenbroek     info->swap = swap_stats;
528*b89261baSDavid van Moolenbroek }
529*b89261baSDavid van Moolenbroek 
530*b89261baSDavid van Moolenbroek 
531*b89261baSDavid van Moolenbroek static void
read_one_proc_stat(pid_t pid,struct top_proc * proc,struct process_select * sel)532*b89261baSDavid van Moolenbroek read_one_proc_stat(pid_t pid, struct top_proc *proc, struct process_select *sel)
533*b89261baSDavid van Moolenbroek {
534*b89261baSDavid van Moolenbroek     char buffer[4096], *p, *q;
535*b89261baSDavid van Moolenbroek     int fd, len;
536*b89261baSDavid van Moolenbroek     int fullcmd;
537*b89261baSDavid van Moolenbroek 
538*b89261baSDavid van Moolenbroek     /* if anything goes wrong, we return with proc->state == 0 */
539*b89261baSDavid van Moolenbroek     proc->state = 0;
540*b89261baSDavid van Moolenbroek 
541*b89261baSDavid van Moolenbroek     /* full cmd handling */
542*b89261baSDavid van Moolenbroek     fullcmd = sel->fullcmd;
543*b89261baSDavid van Moolenbroek     if (fullcmd)
544*b89261baSDavid van Moolenbroek     {
545*b89261baSDavid van Moolenbroek 	sprintf(buffer, "%d/cmdline", pid);
546*b89261baSDavid van Moolenbroek 	if ((fd = open(buffer, O_RDONLY)) != -1)
547*b89261baSDavid van Moolenbroek 	{
548*b89261baSDavid van Moolenbroek 	    /* read command line data */
549*b89261baSDavid van Moolenbroek 	    /* (theres no sense in reading more than we can fit) */
550*b89261baSDavid van Moolenbroek 	    if ((len = read(fd, buffer, MAX_COLS)) > 1)
551*b89261baSDavid van Moolenbroek 	    {
552*b89261baSDavid van Moolenbroek 		buffer[len] = '\0';
553*b89261baSDavid van Moolenbroek 		xfrm_cmdline(buffer, len);
554*b89261baSDavid van Moolenbroek 		update_procname(proc, buffer);
555*b89261baSDavid van Moolenbroek 	    }
556*b89261baSDavid van Moolenbroek 	    else
557*b89261baSDavid van Moolenbroek 	    {
558*b89261baSDavid van Moolenbroek 		fullcmd = 0;
559*b89261baSDavid van Moolenbroek 	    }
560*b89261baSDavid van Moolenbroek 	    close(fd);
561*b89261baSDavid van Moolenbroek 	}
562*b89261baSDavid van Moolenbroek 	else
563*b89261baSDavid van Moolenbroek 	{
564*b89261baSDavid van Moolenbroek 	    fullcmd = 0;
565*b89261baSDavid van Moolenbroek 	}
566*b89261baSDavid van Moolenbroek     }
567*b89261baSDavid van Moolenbroek 
568*b89261baSDavid van Moolenbroek     /* grab the proc stat info in one go */
569*b89261baSDavid van Moolenbroek     sprintf(buffer, "%d/stat", pid);
570*b89261baSDavid van Moolenbroek 
571*b89261baSDavid van Moolenbroek     fd = open(buffer, O_RDONLY);
572*b89261baSDavid van Moolenbroek     len = read(fd, buffer, sizeof(buffer)-1);
573*b89261baSDavid van Moolenbroek     close(fd);
574*b89261baSDavid van Moolenbroek 
575*b89261baSDavid van Moolenbroek     buffer[len] = '\0';
576*b89261baSDavid van Moolenbroek 
577*b89261baSDavid van Moolenbroek     proc->uid = (uid_t)proc_owner((int)pid);
578*b89261baSDavid van Moolenbroek 
579*b89261baSDavid van Moolenbroek     /* parse out the status */
580*b89261baSDavid van Moolenbroek 
581*b89261baSDavid van Moolenbroek     /* skip pid and locate command, which is in parentheses */
582*b89261baSDavid van Moolenbroek     if ((p = strchr(buffer, '(')) == NULL)
583*b89261baSDavid van Moolenbroek     {
584*b89261baSDavid van Moolenbroek 	return;
585*b89261baSDavid van Moolenbroek     }
586*b89261baSDavid van Moolenbroek     if ((q = strrchr(++p, ')')) == NULL)
587*b89261baSDavid van Moolenbroek     {
588*b89261baSDavid van Moolenbroek 	return;
589*b89261baSDavid van Moolenbroek     }
590*b89261baSDavid van Moolenbroek 
591*b89261baSDavid van Moolenbroek     /* set the procname */
592*b89261baSDavid van Moolenbroek     *q = '\0';
593*b89261baSDavid van Moolenbroek     if (!fullcmd)
594*b89261baSDavid van Moolenbroek     {
595*b89261baSDavid van Moolenbroek 	update_procname(proc, p);
596*b89261baSDavid van Moolenbroek     }
597*b89261baSDavid van Moolenbroek 
598*b89261baSDavid van Moolenbroek     /* scan the rest of the line */
599*b89261baSDavid van Moolenbroek     p = q+1;
600*b89261baSDavid van Moolenbroek     p = skip_ws(p);
601*b89261baSDavid van Moolenbroek     switch (*p++)				/* state */
602*b89261baSDavid van Moolenbroek     {
603*b89261baSDavid van Moolenbroek     case 'R': proc->state = 1; break;
604*b89261baSDavid van Moolenbroek     case 'S': proc->state = 2; break;
605*b89261baSDavid van Moolenbroek     case 'D': proc->state = 3; break;
606*b89261baSDavid van Moolenbroek     case 'Z': proc->state = 4; break;
607*b89261baSDavid van Moolenbroek     case 'T': proc->state = 5; break;
608*b89261baSDavid van Moolenbroek     case 'W': proc->state = 6; break;
609*b89261baSDavid van Moolenbroek     case '\0': return;
610*b89261baSDavid van Moolenbroek     }
611*b89261baSDavid van Moolenbroek 
612*b89261baSDavid van Moolenbroek     proc->ppid = strtoul(p, &p, 10);		/* ppid */
613*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip pgrp */
614*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip session */
615*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip tty */
616*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip tty pgrp */
617*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip flags */
618*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip min flt */
619*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip cmin flt */
620*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip maj flt */
621*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip cmaj flt */
622*b89261baSDavid van Moolenbroek 
623*b89261baSDavid van Moolenbroek     proc->time = strtoul(p, &p, 10);		/* utime */
624*b89261baSDavid van Moolenbroek     proc->time += strtoul(p, &p, 10);		/* stime */
625*b89261baSDavid van Moolenbroek 
626*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip cutime */
627*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip cstime */
628*b89261baSDavid van Moolenbroek 
629*b89261baSDavid van Moolenbroek     proc->pri = strtol(p, &p, 10);		/* priority */
630*b89261baSDavid van Moolenbroek     proc->nice = strtol(p, &p, 10);		/* nice */
631*b89261baSDavid van Moolenbroek 
632*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip timeout */
633*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip it_real_val */
634*b89261baSDavid van Moolenbroek     proc->start_time = strtoul(p, &p, 10);	/* start_time */
635*b89261baSDavid van Moolenbroek 
636*b89261baSDavid van Moolenbroek     proc->size = bytetok(strtoul(p, &p, 10));	/* vsize */
637*b89261baSDavid van Moolenbroek     proc->rss = pagetok(strtoul(p, &p, 10));	/* rss */
638*b89261baSDavid van Moolenbroek 
639*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip rlim */
640*b89261baSDavid van Moolenbroek     proc->start_code = strtoul(p, &p, 10);	/* start_code */
641*b89261baSDavid van Moolenbroek     proc->end_code = strtoul(p, &p, 10);	/* end_code */
642*b89261baSDavid van Moolenbroek     proc->start_stack = strtoul(p, &p, 10);	/* start_stack */
643*b89261baSDavid van Moolenbroek 
644*b89261baSDavid van Moolenbroek     /* for the record, here are the rest of the fields */
645*b89261baSDavid van Moolenbroek #if 0
646*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip sp */
647*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip pc */
648*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip signal */
649*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip sigblocked */
650*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip sigignore */
651*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip sigcatch */
652*b89261baSDavid van Moolenbroek     p = skip_token(p);				/* skip wchan */
653*b89261baSDavid van Moolenbroek #endif
654*b89261baSDavid van Moolenbroek }
655*b89261baSDavid van Moolenbroek 
656*b89261baSDavid van Moolenbroek 
657*b89261baSDavid van Moolenbroek caddr_t
get_process_info(struct system_info * si,struct process_select * sel,int compare_index)658*b89261baSDavid van Moolenbroek get_process_info(struct system_info *si,
659*b89261baSDavid van Moolenbroek 		 struct process_select *sel,
660*b89261baSDavid van Moolenbroek 		 int compare_index)
661*b89261baSDavid van Moolenbroek {
662*b89261baSDavid van Moolenbroek     struct timeval thistime;
663*b89261baSDavid van Moolenbroek     double timediff, alpha, beta;
664*b89261baSDavid van Moolenbroek     struct top_proc *proc;
665*b89261baSDavid van Moolenbroek     pid_t pid;
666*b89261baSDavid van Moolenbroek     unsigned long now;
667*b89261baSDavid van Moolenbroek     unsigned long elapsed;
668*b89261baSDavid van Moolenbroek     int i;
669*b89261baSDavid van Moolenbroek 
670*b89261baSDavid van Moolenbroek     /* calculate the time difference since our last check */
671*b89261baSDavid van Moolenbroek     gettimeofday(&thistime, 0);
672*b89261baSDavid van Moolenbroek     if (lasttime.tv_sec)
673*b89261baSDavid van Moolenbroek     {
674*b89261baSDavid van Moolenbroek 	timediff = ((thistime.tv_sec - lasttime.tv_sec) +
675*b89261baSDavid van Moolenbroek 		    (thistime.tv_usec - lasttime.tv_usec) * 1e-6);
676*b89261baSDavid van Moolenbroek     }
677*b89261baSDavid van Moolenbroek     else
678*b89261baSDavid van Moolenbroek     {
679*b89261baSDavid van Moolenbroek 	timediff = 0;
680*b89261baSDavid van Moolenbroek     }
681*b89261baSDavid van Moolenbroek     lasttime = thistime;
682*b89261baSDavid van Moolenbroek 
683*b89261baSDavid van Moolenbroek     /* round current time to a second */
684*b89261baSDavid van Moolenbroek     now = (unsigned long)thistime.tv_sec;
685*b89261baSDavid van Moolenbroek     if (thistime.tv_usec >= 500000)
686*b89261baSDavid van Moolenbroek     {
687*b89261baSDavid van Moolenbroek 	now++;
688*b89261baSDavid van Moolenbroek     }
689*b89261baSDavid van Moolenbroek 
690*b89261baSDavid van Moolenbroek     /* calculate constants for the exponental average */
691*b89261baSDavid van Moolenbroek     if (timediff > 0.0 && timediff < 30.0)
692*b89261baSDavid van Moolenbroek     {
693*b89261baSDavid van Moolenbroek 	alpha = 0.5 * (timediff / 30.0);
694*b89261baSDavid van Moolenbroek 	beta = 1.0 - alpha;
695*b89261baSDavid van Moolenbroek     }
696*b89261baSDavid van Moolenbroek     else
697*b89261baSDavid van Moolenbroek 	alpha = beta = 0.5;
698*b89261baSDavid van Moolenbroek     timediff *= HZ;  /* convert to ticks */
699*b89261baSDavid van Moolenbroek 
700*b89261baSDavid van Moolenbroek     /* mark all hash table entries as not seen */
701*b89261baSDavid van Moolenbroek     for (i = 0; i < HASH_SIZE; ++i)
702*b89261baSDavid van Moolenbroek     {
703*b89261baSDavid van Moolenbroek 	for (proc = ptable[i]; proc; proc = proc->next)
704*b89261baSDavid van Moolenbroek 	{
705*b89261baSDavid van Moolenbroek 	    proc->state = 0;
706*b89261baSDavid van Moolenbroek 	}
707*b89261baSDavid van Moolenbroek     }
708*b89261baSDavid van Moolenbroek 
709*b89261baSDavid van Moolenbroek     /* read the process information */
710*b89261baSDavid van Moolenbroek     {
711*b89261baSDavid van Moolenbroek 	DIR *dir = opendir(".");
712*b89261baSDavid van Moolenbroek 	struct dirent *ent;
713*b89261baSDavid van Moolenbroek 	int total_procs = 0;
714*b89261baSDavid van Moolenbroek 	struct top_proc **active;
715*b89261baSDavid van Moolenbroek 
716*b89261baSDavid van Moolenbroek 	int show_idle = sel->idle;
717*b89261baSDavid van Moolenbroek 	int show_uid = sel->uid != -1;
718*b89261baSDavid van Moolenbroek 
719*b89261baSDavid van Moolenbroek 	memset(process_states, 0, sizeof(process_states));
720*b89261baSDavid van Moolenbroek 
721*b89261baSDavid van Moolenbroek 	while ((ent = readdir(dir)) != NULL)
722*b89261baSDavid van Moolenbroek 	{
723*b89261baSDavid van Moolenbroek 	    struct top_proc *pp;
724*b89261baSDavid van Moolenbroek 
725*b89261baSDavid van Moolenbroek 	    if (!isdigit(ent->d_name[0]))
726*b89261baSDavid van Moolenbroek 		continue;
727*b89261baSDavid van Moolenbroek 
728*b89261baSDavid van Moolenbroek 	    pid = atoi(ent->d_name);
729*b89261baSDavid van Moolenbroek 
730*b89261baSDavid van Moolenbroek 	    /* look up hash table entry */
731*b89261baSDavid van Moolenbroek 	    proc = pp = ptable[HASH(pid)];
732*b89261baSDavid van Moolenbroek 	    while (proc && proc->pid != pid)
733*b89261baSDavid van Moolenbroek 	    {
734*b89261baSDavid van Moolenbroek 		proc = proc->next;
735*b89261baSDavid van Moolenbroek 	    }
736*b89261baSDavid van Moolenbroek 
737*b89261baSDavid van Moolenbroek 	    /* if we came up empty, create a new entry */
738*b89261baSDavid van Moolenbroek 	    if (proc == NULL)
739*b89261baSDavid van Moolenbroek 	    {
740*b89261baSDavid van Moolenbroek 		proc = new_proc();
741*b89261baSDavid van Moolenbroek 		proc->pid = pid;
742*b89261baSDavid van Moolenbroek 		proc->next = pp;
743*b89261baSDavid van Moolenbroek 		ptable[HASH(pid)] = proc;
744*b89261baSDavid van Moolenbroek 		proc->time = proc->otime = 0;
745*b89261baSDavid van Moolenbroek 	    }
746*b89261baSDavid van Moolenbroek 
747*b89261baSDavid van Moolenbroek 	    read_one_proc_stat(pid, proc, sel);
748*b89261baSDavid van Moolenbroek 	    proc->threads = 1;
749*b89261baSDavid van Moolenbroek 
750*b89261baSDavid van Moolenbroek 	    if (proc->state == 0)
751*b89261baSDavid van Moolenbroek 		continue;
752*b89261baSDavid van Moolenbroek 
753*b89261baSDavid van Moolenbroek 	    total_procs++;
754*b89261baSDavid van Moolenbroek 	    process_states[proc->state]++;
755*b89261baSDavid van Moolenbroek 
756*b89261baSDavid van Moolenbroek 	    /* calculate cpu percentage */
757*b89261baSDavid van Moolenbroek 	    if (timediff > 0.0)
758*b89261baSDavid van Moolenbroek 	    {
759*b89261baSDavid van Moolenbroek 		if ((proc->pcpu = (proc->time - proc->otime) / timediff) < 0.0001)
760*b89261baSDavid van Moolenbroek 		{
761*b89261baSDavid van Moolenbroek 		    proc->pcpu = 0;
762*b89261baSDavid van Moolenbroek 		}
763*b89261baSDavid van Moolenbroek 	    }
764*b89261baSDavid van Moolenbroek 	    else if ((elapsed = (now - boottime)*HZ - proc->start_time) > 0)
765*b89261baSDavid van Moolenbroek 	    {
766*b89261baSDavid van Moolenbroek 		if ((proc->pcpu = (double)proc->time / (double)elapsed) < 0.0001)
767*b89261baSDavid van Moolenbroek 		{
768*b89261baSDavid van Moolenbroek 		    proc->pcpu;
769*b89261baSDavid van Moolenbroek 		}
770*b89261baSDavid van Moolenbroek 	    }
771*b89261baSDavid van Moolenbroek 	    else
772*b89261baSDavid van Moolenbroek 	    {
773*b89261baSDavid van Moolenbroek 		proc->pcpu = 0.0;
774*b89261baSDavid van Moolenbroek 	    }
775*b89261baSDavid van Moolenbroek 
776*b89261baSDavid van Moolenbroek 	    /* remember time for next time */
777*b89261baSDavid van Moolenbroek 	    proc->otime = proc->time;
778*b89261baSDavid van Moolenbroek 	}
779*b89261baSDavid van Moolenbroek 	closedir(dir);
780*b89261baSDavid van Moolenbroek 
781*b89261baSDavid van Moolenbroek 	/* make sure we have enough slots for the active procs */
782*b89261baSDavid van Moolenbroek 	if (activesize < total_procs)
783*b89261baSDavid van Moolenbroek 	{
784*b89261baSDavid van Moolenbroek 	    pactive = (struct top_proc **)realloc(pactive,
785*b89261baSDavid van Moolenbroek 			  sizeof(struct top_proc *) * total_procs);
786*b89261baSDavid van Moolenbroek 	    activesize = total_procs;
787*b89261baSDavid van Moolenbroek 	}
788*b89261baSDavid van Moolenbroek 
789*b89261baSDavid van Moolenbroek 	/* set up the active procs and flush dead entries */
790*b89261baSDavid van Moolenbroek 	/* also coalesce threads */
791*b89261baSDavid van Moolenbroek 	active = pactive;
792*b89261baSDavid van Moolenbroek 	for (i = 0; i < HASH_SIZE; i++)
793*b89261baSDavid van Moolenbroek 	{
794*b89261baSDavid van Moolenbroek 	    struct top_proc *last;
795*b89261baSDavid van Moolenbroek 	    struct top_proc *ptmp;
796*b89261baSDavid van Moolenbroek 	    struct top_proc *parent;
797*b89261baSDavid van Moolenbroek 
798*b89261baSDavid van Moolenbroek 	    last = NULL;
799*b89261baSDavid van Moolenbroek 	    proc = ptable[i];
800*b89261baSDavid van Moolenbroek 	    while (proc != NULL)
801*b89261baSDavid van Moolenbroek 	    {
802*b89261baSDavid van Moolenbroek 		if (proc->state == 0)
803*b89261baSDavid van Moolenbroek 		{
804*b89261baSDavid van Moolenbroek 		    ptmp = proc;
805*b89261baSDavid van Moolenbroek 		    if (last)
806*b89261baSDavid van Moolenbroek 		    {
807*b89261baSDavid van Moolenbroek 			proc = last->next = proc->next;
808*b89261baSDavid van Moolenbroek 		    }
809*b89261baSDavid van Moolenbroek 		    else
810*b89261baSDavid van Moolenbroek 		    {
811*b89261baSDavid van Moolenbroek 			proc = ptable[i] = proc->next;
812*b89261baSDavid van Moolenbroek 		    }
813*b89261baSDavid van Moolenbroek 		    free_proc(ptmp);
814*b89261baSDavid van Moolenbroek 		}
815*b89261baSDavid van Moolenbroek 		else
816*b89261baSDavid van Moolenbroek 		{
817*b89261baSDavid van Moolenbroek 		    /* look up hash table entry for parent */
818*b89261baSDavid van Moolenbroek 		    parent = proc;
819*b89261baSDavid van Moolenbroek 		    do {
820*b89261baSDavid van Moolenbroek 			pid = parent->ppid;
821*b89261baSDavid van Moolenbroek 			parent = ptable[HASH(pid)];
822*b89261baSDavid van Moolenbroek 			while (parent && parent->pid != pid)
823*b89261baSDavid van Moolenbroek 			{
824*b89261baSDavid van Moolenbroek 			    parent = parent->next;
825*b89261baSDavid van Moolenbroek 			}
826*b89261baSDavid van Moolenbroek 		    } while (parent && parent->state == 0);
827*b89261baSDavid van Moolenbroek 
828*b89261baSDavid van Moolenbroek 		    /* does this look like a thread of its parent? */
829*b89261baSDavid van Moolenbroek 		    if (parent && proc->size == parent->size &&
830*b89261baSDavid van Moolenbroek 			proc->rss == parent->rss &&
831*b89261baSDavid van Moolenbroek 			proc->start_code == parent->start_code &&
832*b89261baSDavid van Moolenbroek 			proc->end_code == parent->end_code &&
833*b89261baSDavid van Moolenbroek 			proc->start_stack == parent->start_stack)
834*b89261baSDavid van Moolenbroek 		    {
835*b89261baSDavid van Moolenbroek 			/* yes it does: roll up the cumulative numbers */
836*b89261baSDavid van Moolenbroek 			parent->threads += proc->threads;
837*b89261baSDavid van Moolenbroek 			parent->time += proc->time;
838*b89261baSDavid van Moolenbroek 			parent->pcpu += proc->pcpu;
839*b89261baSDavid van Moolenbroek 
840*b89261baSDavid van Moolenbroek 			/* mark this process as dead (undisplayable) */
841*b89261baSDavid van Moolenbroek 			proc->state = 0;
842*b89261baSDavid van Moolenbroek 		    }
843*b89261baSDavid van Moolenbroek 		    else if ((show_idle || proc->state == 1 || proc->pcpu) &&
844*b89261baSDavid van Moolenbroek 			     (!show_uid || proc->uid == sel->uid))
845*b89261baSDavid van Moolenbroek 		    {
846*b89261baSDavid van Moolenbroek 			*active++ = proc;
847*b89261baSDavid van Moolenbroek 			last = proc;
848*b89261baSDavid van Moolenbroek 		    }
849*b89261baSDavid van Moolenbroek 		    proc = proc->next;
850*b89261baSDavid van Moolenbroek 		}
851*b89261baSDavid van Moolenbroek 	    }
852*b89261baSDavid van Moolenbroek 	}
853*b89261baSDavid van Moolenbroek 
854*b89261baSDavid van Moolenbroek 	si->p_active = active - pactive;
855*b89261baSDavid van Moolenbroek 	si->p_total = total_procs;
856*b89261baSDavid van Moolenbroek 	si->procstates = process_states;
857*b89261baSDavid van Moolenbroek     }
858*b89261baSDavid van Moolenbroek 
859*b89261baSDavid van Moolenbroek     /* if requested, sort the "active" procs */
860*b89261baSDavid van Moolenbroek     if (si->p_active)
861*b89261baSDavid van Moolenbroek 	qsort(pactive, si->p_active, sizeof(struct top_proc *),
862*b89261baSDavid van Moolenbroek 	      proc_compares[compare_index]);
863*b89261baSDavid van Moolenbroek 
864*b89261baSDavid van Moolenbroek     /* don't even pretend that the return value thing here isn't bogus */
865*b89261baSDavid van Moolenbroek     nextactive = pactive;
866*b89261baSDavid van Moolenbroek     return (caddr_t)0;
867*b89261baSDavid van Moolenbroek }
868*b89261baSDavid van Moolenbroek 
869*b89261baSDavid van Moolenbroek 
870*b89261baSDavid van Moolenbroek char *
format_header(char * uname_field)871*b89261baSDavid van Moolenbroek format_header(char *uname_field)
872*b89261baSDavid van Moolenbroek 
873*b89261baSDavid van Moolenbroek {
874*b89261baSDavid van Moolenbroek     int uname_len = strlen(uname_field);
875*b89261baSDavid van Moolenbroek     if (uname_len > 8)
876*b89261baSDavid van Moolenbroek 	uname_len = 8;
877*b89261baSDavid van Moolenbroek 
878*b89261baSDavid van Moolenbroek     memcpy(strchr(fmt_header, 'X'), uname_field, uname_len);
879*b89261baSDavid van Moolenbroek 
880*b89261baSDavid van Moolenbroek     return fmt_header;
881*b89261baSDavid van Moolenbroek }
882*b89261baSDavid van Moolenbroek 
883*b89261baSDavid van Moolenbroek 
884*b89261baSDavid van Moolenbroek char *
format_next_process(caddr_t handle,char * (* get_userid)(int))885*b89261baSDavid van Moolenbroek format_next_process(caddr_t handle, char *(*get_userid)(int))
886*b89261baSDavid van Moolenbroek 
887*b89261baSDavid van Moolenbroek {
888*b89261baSDavid van Moolenbroek     static char fmt[MAX_COLS];	/* static area where result is built */
889*b89261baSDavid van Moolenbroek     struct top_proc *p = *nextactive++;
890*b89261baSDavid van Moolenbroek 
891*b89261baSDavid van Moolenbroek     snprintf(fmt, sizeof(fmt),
892*b89261baSDavid van Moolenbroek 	    "%5d %-8.8s %3d %3d %4d %5s %5s %-5s %6s %5.2f%% %s",
893*b89261baSDavid van Moolenbroek 	    p->pid,
894*b89261baSDavid van Moolenbroek 	    (*get_userid)(p->uid),
895*b89261baSDavid van Moolenbroek 	    p->threads,
896*b89261baSDavid van Moolenbroek 	    p->pri < -99 ? -99 : p->pri,
897*b89261baSDavid van Moolenbroek 	    p->nice,
898*b89261baSDavid van Moolenbroek 	    format_k(p->size),
899*b89261baSDavid van Moolenbroek 	    format_k(p->rss),
900*b89261baSDavid van Moolenbroek 	    state_abbrev[p->state],
901*b89261baSDavid van Moolenbroek 	    format_time(p->time / HZ),
902*b89261baSDavid van Moolenbroek 	    p->pcpu * 100.0,
903*b89261baSDavid van Moolenbroek 	    p->name);
904*b89261baSDavid van Moolenbroek 
905*b89261baSDavid van Moolenbroek     /* return the result */
906*b89261baSDavid van Moolenbroek     return (fmt);
907*b89261baSDavid van Moolenbroek }
908*b89261baSDavid van Moolenbroek 
909*b89261baSDavid van Moolenbroek /* comparison routines for qsort */
910*b89261baSDavid van Moolenbroek 
911*b89261baSDavid van Moolenbroek /*
912*b89261baSDavid van Moolenbroek  * There are currently four possible comparison routines.  main selects
913*b89261baSDavid van Moolenbroek  * one of these by indexing in to the array proc_compares.
914*b89261baSDavid van Moolenbroek  *
915*b89261baSDavid van Moolenbroek  * Possible keys are defined as macros below.  Currently these keys are
916*b89261baSDavid van Moolenbroek  * defined:  percent cpu, cpu ticks, process state, resident set size,
917*b89261baSDavid van Moolenbroek  * total virtual memory usage.  The process states are ordered as follows
918*b89261baSDavid van Moolenbroek  * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
919*b89261baSDavid van Moolenbroek  * The array declaration below maps a process state index into a number
920*b89261baSDavid van Moolenbroek  * that reflects this ordering.
921*b89261baSDavid van Moolenbroek  */
922*b89261baSDavid van Moolenbroek 
923*b89261baSDavid van Moolenbroek /* First, the possible comparison keys.  These are defined in such a way
924*b89261baSDavid van Moolenbroek    that they can be merely listed in the source code to define the actual
925*b89261baSDavid van Moolenbroek    desired ordering.
926*b89261baSDavid van Moolenbroek  */
927*b89261baSDavid van Moolenbroek 
928*b89261baSDavid van Moolenbroek #define ORDERKEY_PCTCPU  if (dresult = p2->pcpu - p1->pcpu,\
929*b89261baSDavid van Moolenbroek 							 (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
930*b89261baSDavid van Moolenbroek #define ORDERKEY_CPTICKS if ((result = (long)p2->time - (long)p1->time) == 0)
931*b89261baSDavid van Moolenbroek #define ORDERKEY_STATE   if ((result = (sort_state[p2->state] - \
932*b89261baSDavid van Moolenbroek 			sort_state[p1->state])) == 0)
933*b89261baSDavid van Moolenbroek #define ORDERKEY_PRIO    if ((result = p2->pri - p1->pri) == 0)
934*b89261baSDavid van Moolenbroek #define ORDERKEY_RSSIZE  if ((result = p2->rss - p1->rss) == 0)
935*b89261baSDavid van Moolenbroek #define ORDERKEY_MEM     if ((result = p2->size - p1->size) == 0)
936*b89261baSDavid van Moolenbroek #define ORDERKEY_NAME    if ((result = strcmp(p1->name, p2->name)) == 0)
937*b89261baSDavid van Moolenbroek 
938*b89261baSDavid van Moolenbroek /* Now the array that maps process state to a weight */
939*b89261baSDavid van Moolenbroek 
940*b89261baSDavid van Moolenbroek unsigned char sort_state[] =
941*b89261baSDavid van Moolenbroek {
942*b89261baSDavid van Moolenbroek 	0,	/* empty */
943*b89261baSDavid van Moolenbroek 	6, 	/* run */
944*b89261baSDavid van Moolenbroek 	3,	/* sleep */
945*b89261baSDavid van Moolenbroek 	5,	/* disk wait */
946*b89261baSDavid van Moolenbroek 	1,	/* zombie */
947*b89261baSDavid van Moolenbroek 	2,	/* stop */
948*b89261baSDavid van Moolenbroek 	4	/* swap */
949*b89261baSDavid van Moolenbroek };
950*b89261baSDavid van Moolenbroek 
951*b89261baSDavid van Moolenbroek 
952*b89261baSDavid van Moolenbroek /* compare_cpu - the comparison function for sorting by cpu percentage */
953*b89261baSDavid van Moolenbroek 
954*b89261baSDavid van Moolenbroek int
compare_cpu(struct top_proc ** pp1,struct top_proc ** pp2)955*b89261baSDavid van Moolenbroek compare_cpu (
956*b89261baSDavid van Moolenbroek 	       struct top_proc **pp1,
957*b89261baSDavid van Moolenbroek 	       struct top_proc **pp2)
958*b89261baSDavid van Moolenbroek   {
959*b89261baSDavid van Moolenbroek     register struct top_proc *p1;
960*b89261baSDavid van Moolenbroek     register struct top_proc *p2;
961*b89261baSDavid van Moolenbroek     register long result;
962*b89261baSDavid van Moolenbroek     double dresult;
963*b89261baSDavid van Moolenbroek 
964*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
965*b89261baSDavid van Moolenbroek     p1 = *pp1;
966*b89261baSDavid van Moolenbroek     p2 = *pp2;
967*b89261baSDavid van Moolenbroek 
968*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
969*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
970*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
971*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
972*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
973*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
974*b89261baSDavid van Moolenbroek     ;
975*b89261baSDavid van Moolenbroek 
976*b89261baSDavid van Moolenbroek     return result == 0 ? 0 : result < 0 ? -1 : 1;
977*b89261baSDavid van Moolenbroek   }
978*b89261baSDavid van Moolenbroek 
979*b89261baSDavid van Moolenbroek /* compare_size - the comparison function for sorting by total memory usage */
980*b89261baSDavid van Moolenbroek 
981*b89261baSDavid van Moolenbroek int
compare_size(struct top_proc ** pp1,struct top_proc ** pp2)982*b89261baSDavid van Moolenbroek compare_size (
983*b89261baSDavid van Moolenbroek 	       struct top_proc **pp1,
984*b89261baSDavid van Moolenbroek 	       struct top_proc **pp2)
985*b89261baSDavid van Moolenbroek   {
986*b89261baSDavid van Moolenbroek     register struct top_proc *p1;
987*b89261baSDavid van Moolenbroek     register struct top_proc *p2;
988*b89261baSDavid van Moolenbroek     register long result;
989*b89261baSDavid van Moolenbroek     double dresult;
990*b89261baSDavid van Moolenbroek 
991*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
992*b89261baSDavid van Moolenbroek     p1 = *pp1;
993*b89261baSDavid van Moolenbroek     p2 = *pp2;
994*b89261baSDavid van Moolenbroek 
995*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
996*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
997*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
998*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
999*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1000*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1001*b89261baSDavid van Moolenbroek     ;
1002*b89261baSDavid van Moolenbroek 
1003*b89261baSDavid van Moolenbroek     return result == 0 ? 0 : result < 0 ? -1 : 1;
1004*b89261baSDavid van Moolenbroek   }
1005*b89261baSDavid van Moolenbroek 
1006*b89261baSDavid van Moolenbroek /* compare_res - the comparison function for sorting by resident set size */
1007*b89261baSDavid van Moolenbroek 
1008*b89261baSDavid van Moolenbroek int
compare_res(struct top_proc ** pp1,struct top_proc ** pp2)1009*b89261baSDavid van Moolenbroek compare_res (
1010*b89261baSDavid van Moolenbroek 	       struct top_proc **pp1,
1011*b89261baSDavid van Moolenbroek 	       struct top_proc **pp2)
1012*b89261baSDavid van Moolenbroek   {
1013*b89261baSDavid van Moolenbroek     register struct top_proc *p1;
1014*b89261baSDavid van Moolenbroek     register struct top_proc *p2;
1015*b89261baSDavid van Moolenbroek     register long result;
1016*b89261baSDavid van Moolenbroek     double dresult;
1017*b89261baSDavid van Moolenbroek 
1018*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1019*b89261baSDavid van Moolenbroek     p1 = *pp1;
1020*b89261baSDavid van Moolenbroek     p2 = *pp2;
1021*b89261baSDavid van Moolenbroek 
1022*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1023*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1024*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1025*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1026*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1027*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1028*b89261baSDavid van Moolenbroek     ;
1029*b89261baSDavid van Moolenbroek 
1030*b89261baSDavid van Moolenbroek     return result == 0 ? 0 : result < 0 ? -1 : 1;
1031*b89261baSDavid van Moolenbroek   }
1032*b89261baSDavid van Moolenbroek 
1033*b89261baSDavid van Moolenbroek /* compare_time - the comparison function for sorting by total cpu time */
1034*b89261baSDavid van Moolenbroek 
1035*b89261baSDavid van Moolenbroek int
compare_time(struct top_proc ** pp1,struct top_proc ** pp2)1036*b89261baSDavid van Moolenbroek compare_time (
1037*b89261baSDavid van Moolenbroek 	       struct top_proc **pp1,
1038*b89261baSDavid van Moolenbroek 	       struct top_proc **pp2)
1039*b89261baSDavid van Moolenbroek   {
1040*b89261baSDavid van Moolenbroek     register struct top_proc *p1;
1041*b89261baSDavid van Moolenbroek     register struct top_proc *p2;
1042*b89261baSDavid van Moolenbroek     register long result;
1043*b89261baSDavid van Moolenbroek     double dresult;
1044*b89261baSDavid van Moolenbroek 
1045*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1046*b89261baSDavid van Moolenbroek     p1 = *pp1;
1047*b89261baSDavid van Moolenbroek     p2 = *pp2;
1048*b89261baSDavid van Moolenbroek 
1049*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1050*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1051*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1052*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1053*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1054*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1055*b89261baSDavid van Moolenbroek     ;
1056*b89261baSDavid van Moolenbroek 
1057*b89261baSDavid van Moolenbroek     return result == 0 ? 0 : result < 0 ? -1 : 1;
1058*b89261baSDavid van Moolenbroek   }
1059*b89261baSDavid van Moolenbroek 
1060*b89261baSDavid van Moolenbroek /* compare_cmd - the comparison function for sorting by command name */
1061*b89261baSDavid van Moolenbroek 
1062*b89261baSDavid van Moolenbroek int
compare_cmd(struct top_proc ** pp1,struct top_proc ** pp2)1063*b89261baSDavid van Moolenbroek compare_cmd (
1064*b89261baSDavid van Moolenbroek 	       struct top_proc **pp1,
1065*b89261baSDavid van Moolenbroek 	       struct top_proc **pp2)
1066*b89261baSDavid van Moolenbroek   {
1067*b89261baSDavid van Moolenbroek     register struct top_proc *p1;
1068*b89261baSDavid van Moolenbroek     register struct top_proc *p2;
1069*b89261baSDavid van Moolenbroek     register long result;
1070*b89261baSDavid van Moolenbroek     double dresult;
1071*b89261baSDavid van Moolenbroek 
1072*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
1073*b89261baSDavid van Moolenbroek     p1 = *pp1;
1074*b89261baSDavid van Moolenbroek     p2 = *pp2;
1075*b89261baSDavid van Moolenbroek 
1076*b89261baSDavid van Moolenbroek     ORDERKEY_NAME
1077*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
1078*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
1079*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
1080*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
1081*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
1082*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
1083*b89261baSDavid van Moolenbroek     ;
1084*b89261baSDavid van Moolenbroek 
1085*b89261baSDavid van Moolenbroek     return result == 0 ? 0 : result < 0 ? -1 : 1;
1086*b89261baSDavid van Moolenbroek   }
1087*b89261baSDavid van Moolenbroek 
1088*b89261baSDavid van Moolenbroek 
1089*b89261baSDavid van Moolenbroek /*
1090*b89261baSDavid van Moolenbroek  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
1091*b89261baSDavid van Moolenbroek  *              the process does not exist.
1092*b89261baSDavid van Moolenbroek  *              It is EXTREMLY IMPORTANT that this function work correctly.
1093*b89261baSDavid van Moolenbroek  *              If top runs setuid root (as in SVR4), then this function
1094*b89261baSDavid van Moolenbroek  *              is the only thing that stands in the way of a serious
1095*b89261baSDavid van Moolenbroek  *              security problem.  It validates requests for the "kill"
1096*b89261baSDavid van Moolenbroek  *              and "renice" commands.
1097*b89261baSDavid van Moolenbroek  */
1098*b89261baSDavid van Moolenbroek 
1099*b89261baSDavid van Moolenbroek int
proc_owner(int pid)1100*b89261baSDavid van Moolenbroek proc_owner(int pid)
1101*b89261baSDavid van Moolenbroek 
1102*b89261baSDavid van Moolenbroek {
1103*b89261baSDavid van Moolenbroek     struct stat sb;
1104*b89261baSDavid van Moolenbroek     char buffer[32];
1105*b89261baSDavid van Moolenbroek     sprintf(buffer, "%d", pid);
1106*b89261baSDavid van Moolenbroek 
1107*b89261baSDavid van Moolenbroek     if (stat(buffer, &sb) < 0)
1108*b89261baSDavid van Moolenbroek 	return -1;
1109*b89261baSDavid van Moolenbroek     else
1110*b89261baSDavid van Moolenbroek 	return (int)sb.st_uid;
1111*b89261baSDavid van Moolenbroek }
1112