xref: /minix3/external/bsd/top/dist/machine/m_decosf1.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:  OSF/1, Digital Unix 4.0, Compaq Tru64 5.0
37*b89261baSDavid van Moolenbroek  *
38*b89261baSDavid van Moolenbroek  * DESCRIPTION:
39*b89261baSDavid van Moolenbroek  * This is the machine-dependent module for DEC OSF/1 and its descendents
40*b89261baSDavid van Moolenbroek  * It is known to work on OSF/1 1.2, 1.3, 2.0-T3, 3.0, Digital Unix V4.0,
41*b89261baSDavid van Moolenbroek  * Digital Unix 5.0, and Tru64 5.0.
42*b89261baSDavid van Moolenbroek  * WARNING: if you use optimization with the standard "cc" compiler that
43*b89261baSDavid van Moolenbroek  * .        comes with V3.0 the resulting executable may core dump.  If
44*b89261baSDavid van Moolenbroek  * .        this happens, recompile without optimization.
45*b89261baSDavid van Moolenbroek  *
46*b89261baSDavid van Moolenbroek  * LIBS: -lmld -lmach
47*b89261baSDavid van Moolenbroek  *
48*b89261baSDavid van Moolenbroek  * CFLAGS: -DHAVE_GETOPT -DORDER
49*b89261baSDavid van Moolenbroek  *
50*b89261baSDavid van Moolenbroek  * AUTHOR:  Anthony Baxter, <anthony@aaii.oz.au>
51*b89261baSDavid van Moolenbroek  * Derived originally from m_ultrix, by David S. Comay <dsc@seismo.css.gov>,
52*b89261baSDavid van Moolenbroek  * although by now there is hardly any of the code from m_ultrix left.
53*b89261baSDavid van Moolenbroek  * Helped a lot by having the source for syd(1), by Claus Kalle, and
54*b89261baSDavid van Moolenbroek  * from several people at DEC who helped with providing information on
55*b89261baSDavid van Moolenbroek  * some of the less-documented bits of the kernel interface.
56*b89261baSDavid van Moolenbroek  *
57*b89261baSDavid van Moolenbroek  * Modified: 31-Oct-94, Pat Welch, tpw@physics.orst.edu
58*b89261baSDavid van Moolenbroek  *	changed _mpid to pidtab for compatibility with OSF/1 version 3.0
59*b89261baSDavid van Moolenbroek  *
60*b89261baSDavid van Moolenbroek  * Modified: 13-Dec-94, William LeFebvre, lefebvre@dis.anl.gov
61*b89261baSDavid van Moolenbroek  *	removed used of pidtab (that was bogus) and changed things to
62*b89261baSDavid van Moolenbroek  *	automatically detect the absence of _mpid in the nlist and
63*b89261baSDavid van Moolenbroek  *	recover gracefully---this appears to be the only difference
64*b89261baSDavid van Moolenbroek  *	with 3.0.
65*b89261baSDavid van Moolenbroek  *
66*b89261baSDavid van Moolenbroek  * Modified: 3-Mar-00, Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
67*b89261baSDavid van Moolenbroek  *	added support for sort ordering.
68*b89261baSDavid van Moolenbroek  */
69*b89261baSDavid van Moolenbroek /*
70*b89261baSDavid van Moolenbroek  * Theory of operation:
71*b89261baSDavid van Moolenbroek  *
72*b89261baSDavid van Moolenbroek  * Use Mach calls to build up a structure that contains all the sorts
73*b89261baSDavid van Moolenbroek  * of stuff normally found in a struct proc in a BSD system. Then
74*b89261baSDavid van Moolenbroek  * everything else uses this structure. This has major performance wins,
75*b89261baSDavid van Moolenbroek  * and also should work for future versions of the O/S.
76*b89261baSDavid van Moolenbroek  */
77*b89261baSDavid van Moolenbroek 
78*b89261baSDavid van Moolenbroek #include "config.h"
79*b89261baSDavid van Moolenbroek 
80*b89261baSDavid van Moolenbroek #include <sys/types.h>
81*b89261baSDavid van Moolenbroek #include <sys/signal.h>
82*b89261baSDavid van Moolenbroek #include <sys/param.h>
83*b89261baSDavid van Moolenbroek 
84*b89261baSDavid van Moolenbroek #include <string.h>
85*b89261baSDavid van Moolenbroek #include <sys/user.h>
86*b89261baSDavid van Moolenbroek #include <stdio.h>
87*b89261baSDavid van Moolenbroek #include <nlist.h>
88*b89261baSDavid van Moolenbroek #include <math.h>
89*b89261baSDavid van Moolenbroek #include <sys/dir.h>
90*b89261baSDavid van Moolenbroek #include <sys/user.h>
91*b89261baSDavid van Moolenbroek #include <sys/proc.h>
92*b89261baSDavid van Moolenbroek #include <sys/dk.h>
93*b89261baSDavid van Moolenbroek #include <sys/vm.h>
94*b89261baSDavid van Moolenbroek #include <sys/file.h>
95*b89261baSDavid van Moolenbroek #include <sys/time.h>
96*b89261baSDavid van Moolenbroek /* #include <machine/pte.h> */
97*b89261baSDavid van Moolenbroek /* forward declarations, needed by <net/if.h> included from <sys/table.h> */
98*b89261baSDavid van Moolenbroek struct rtentry;
99*b89261baSDavid van Moolenbroek struct mbuf;
100*b89261baSDavid van Moolenbroek #include <sys/table.h>
101*b89261baSDavid van Moolenbroek #include <mach.h>
102*b89261baSDavid van Moolenbroek #include <mach/mach_types.h>
103*b89261baSDavid van Moolenbroek #include <mach/vm_statistics.h>
104*b89261baSDavid van Moolenbroek #include <sys/syscall.h> /* for SYS_setpriority, in setpriority(), below */
105*b89261baSDavid van Moolenbroek 
106*b89261baSDavid van Moolenbroek 
107*b89261baSDavid van Moolenbroek #include "top.h"
108*b89261baSDavid van Moolenbroek #include "machine.h"
109*b89261baSDavid van Moolenbroek #include "utils.h"
110*b89261baSDavid van Moolenbroek 
111*b89261baSDavid van Moolenbroek extern int errno, sys_nerr;
112*b89261baSDavid van Moolenbroek extern char *sys_errlist[];
113*b89261baSDavid van Moolenbroek #define strerror(e) (((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")
114*b89261baSDavid van Moolenbroek 
115*b89261baSDavid van Moolenbroek #define VMUNIX	"/vmunix"
116*b89261baSDavid van Moolenbroek #define KMEM	"/dev/kmem"
117*b89261baSDavid van Moolenbroek #define MEM	"/dev/mem"
118*b89261baSDavid van Moolenbroek 
119*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle.  This is what it looks like: */
120*b89261baSDavid van Moolenbroek 
121*b89261baSDavid van Moolenbroek struct handle
122*b89261baSDavid van Moolenbroek {
123*b89261baSDavid van Moolenbroek     struct osf1_top_proc **next_proc;	/* points to next valid proc pointer */
124*b89261baSDavid van Moolenbroek     int remaining;		/* number of pointers remaining */
125*b89261baSDavid van Moolenbroek };
126*b89261baSDavid van Moolenbroek 
127*b89261baSDavid van Moolenbroek /* declarations for load_avg */
128*b89261baSDavid van Moolenbroek #include "loadavg.h"
129*b89261baSDavid van Moolenbroek 
130*b89261baSDavid van Moolenbroek /* definitions for indices in the nlist array */
131*b89261baSDavid van Moolenbroek #define X_MPID		0
132*b89261baSDavid van Moolenbroek 
133*b89261baSDavid van Moolenbroek static struct nlist nlst[] = {
134*b89261baSDavid van Moolenbroek     { "_mpid" },		/* 0 */
135*b89261baSDavid van Moolenbroek     { 0 }
136*b89261baSDavid van Moolenbroek };
137*b89261baSDavid van Moolenbroek 
138*b89261baSDavid van Moolenbroek /* Some versions of OSF/1 don't support reporting of the last PID.
139*b89261baSDavid van Moolenbroek    This flag indicates whether or not we are reporting the last PID. */
140*b89261baSDavid van Moolenbroek static int do_last_pid = 1;
141*b89261baSDavid van Moolenbroek 
142*b89261baSDavid van Moolenbroek /*
143*b89261baSDavid van Moolenbroek  *  These definitions control the format of the per-process area
144*b89261baSDavid van Moolenbroek  */
145*b89261baSDavid van Moolenbroek 
146*b89261baSDavid van Moolenbroek static char header[] =
147*b89261baSDavid van Moolenbroek   "   PID X        PRI NICE  SIZE   RES STATE   TIME    CPU COMMAND";
148*b89261baSDavid van Moolenbroek /* 01234567   -- field to fill in starts at header+7 */
149*b89261baSDavid van Moolenbroek #define UNAME_START 7
150*b89261baSDavid van Moolenbroek 
151*b89261baSDavid van Moolenbroek #define Proc_format \
152*b89261baSDavid van Moolenbroek 	"%6d %-8.8s %3d %4d %5s %5s %-5s %-6s %5.2f%% %s"
153*b89261baSDavid van Moolenbroek 
154*b89261baSDavid van Moolenbroek 
155*b89261baSDavid van Moolenbroek /* process state names for the "STATE" column of the display */
156*b89261baSDavid van Moolenbroek /* the extra nulls in the string "run" are for adding a slash and
157*b89261baSDavid van Moolenbroek  * the processor number when needed. Although OSF/1 doesnt support
158*b89261baSDavid van Moolenbroek  * multiple processors yet, (and this module _certainly_ doesnt
159*b89261baSDavid van Moolenbroek  * support it, either, we may as well plan for the future. :-)
160*b89261baSDavid van Moolenbroek  */
161*b89261baSDavid van Moolenbroek 
162*b89261baSDavid van Moolenbroek char *state_abbrev[] =
163*b89261baSDavid van Moolenbroek {
164*b89261baSDavid van Moolenbroek     "", "run\0\0\0", "WAIT", "sleep", "sleep", "stop", "halt", "???", "zomb"
165*b89261baSDavid van Moolenbroek };
166*b89261baSDavid van Moolenbroek 
167*b89261baSDavid van Moolenbroek 
168*b89261baSDavid van Moolenbroek static int kmem, mem;
169*b89261baSDavid van Moolenbroek 
170*b89261baSDavid van Moolenbroek /* values that we stash away in _init and use in later routines */
171*b89261baSDavid van Moolenbroek 
172*b89261baSDavid van Moolenbroek static double logcpu;
173*b89261baSDavid van Moolenbroek 
174*b89261baSDavid van Moolenbroek /* these are retrieved from the kernel in _init */
175*b89261baSDavid van Moolenbroek 
176*b89261baSDavid van Moolenbroek static unsigned long proc;
177*b89261baSDavid van Moolenbroek static          int  nproc;
178*b89261baSDavid van Moolenbroek static load_avg  ccpu;
179*b89261baSDavid van Moolenbroek 
180*b89261baSDavid van Moolenbroek typedef long mtime_t;
181*b89261baSDavid van Moolenbroek 
182*b89261baSDavid van Moolenbroek /* these are offsets obtained via nlist and used in the get_ functions */
183*b89261baSDavid van Moolenbroek 
184*b89261baSDavid van Moolenbroek static unsigned long mpid_offset;
185*b89261baSDavid van Moolenbroek 
186*b89261baSDavid van Moolenbroek /* these are for detailing the process states */
187*b89261baSDavid van Moolenbroek 
188*b89261baSDavid van Moolenbroek int process_states[9];
189*b89261baSDavid van Moolenbroek char *procstatenames[] = {
190*b89261baSDavid van Moolenbroek     "", " running, ", " waiting, ", " sleeping, ", " idle, ",
191*b89261baSDavid van Moolenbroek     " stopped, ", " halted, ", "", " zombie",
192*b89261baSDavid van Moolenbroek     NULL
193*b89261baSDavid van Moolenbroek };
194*b89261baSDavid van Moolenbroek 
195*b89261baSDavid van Moolenbroek /* these are for detailing the cpu states */
196*b89261baSDavid van Moolenbroek 
197*b89261baSDavid van Moolenbroek int cpu_states[5];
198*b89261baSDavid van Moolenbroek char *cpustatenames[] = {
199*b89261baSDavid van Moolenbroek     "user", "nice", "system", "wio", "idle", NULL
200*b89261baSDavid van Moolenbroek };
201*b89261baSDavid van Moolenbroek 
202*b89261baSDavid van Moolenbroek long old_cpu_ticks[5];
203*b89261baSDavid van Moolenbroek 
204*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
205*b89261baSDavid van Moolenbroek 
206*b89261baSDavid van Moolenbroek long memory_stats[5];
207*b89261baSDavid van Moolenbroek char *memorynames[] = {
208*b89261baSDavid van Moolenbroek     "K active, ", "K inactive, ", "K total, ", "K free", NULL
209*b89261baSDavid van Moolenbroek };
210*b89261baSDavid van Moolenbroek 
211*b89261baSDavid van Moolenbroek long swap_stats[3];
212*b89261baSDavid van Moolenbroek char *swapnames[] = {
213*b89261baSDavid van Moolenbroek     "K in use, ", "K total", NULL
214*b89261baSDavid van Moolenbroek };
215*b89261baSDavid van Moolenbroek 
216*b89261baSDavid van Moolenbroek /* these are names given to allowed sorting orders -- first is default */
217*b89261baSDavid van Moolenbroek char *ordernames[] = {
218*b89261baSDavid van Moolenbroek     "cpu", "size", "res", "time", NULL
219*b89261baSDavid van Moolenbroek };
220*b89261baSDavid van Moolenbroek 
221*b89261baSDavid van Moolenbroek /* forward definitions for comparison functions */
222*b89261baSDavid van Moolenbroek int compare_cpu();
223*b89261baSDavid van Moolenbroek int compare_size();
224*b89261baSDavid van Moolenbroek int compare_res();
225*b89261baSDavid van Moolenbroek int compare_time();
226*b89261baSDavid van Moolenbroek 
227*b89261baSDavid van Moolenbroek int (*proc_compares[])() = {
228*b89261baSDavid van Moolenbroek     compare_cpu,
229*b89261baSDavid van Moolenbroek     compare_size,
230*b89261baSDavid van Moolenbroek     compare_res,
231*b89261baSDavid van Moolenbroek     compare_time,
232*b89261baSDavid van Moolenbroek     NULL
233*b89261baSDavid van Moolenbroek };
234*b89261baSDavid van Moolenbroek 
235*b89261baSDavid van Moolenbroek /* these are for getting the memory statistics */
236*b89261baSDavid van Moolenbroek 
237*b89261baSDavid van Moolenbroek static int pageshift;		/* log base 2 of the pagesize */
238*b89261baSDavid van Moolenbroek 
239*b89261baSDavid van Moolenbroek /* define pagetok in terms of pageshift */
240*b89261baSDavid van Moolenbroek 
241*b89261baSDavid van Moolenbroek #define pagetok(size) ((size) << pageshift)
242*b89261baSDavid van Moolenbroek 
243*b89261baSDavid van Moolenbroek /* take a process, make it a mach task, and grab all the info out */
244*b89261baSDavid van Moolenbroek void do_threads_calculations();
245*b89261baSDavid van Moolenbroek 
246*b89261baSDavid van Moolenbroek /*
247*b89261baSDavid van Moolenbroek  * Because I dont feel like repeatedly grunging through the kernel with
248*b89261baSDavid van Moolenbroek  * Mach calls, and I also dont want the horrid performance hit this
249*b89261baSDavid van Moolenbroek  * would give, I read the stuff I need out, and put in into my own
250*b89261baSDavid van Moolenbroek  * structure, for later use.
251*b89261baSDavid van Moolenbroek  */
252*b89261baSDavid van Moolenbroek 
253*b89261baSDavid van Moolenbroek struct osf1_top_proc {
254*b89261baSDavid van Moolenbroek     size_t p_mach_virt_size;
255*b89261baSDavid van Moolenbroek     char p_mach_state;
256*b89261baSDavid van Moolenbroek     int p_flag;
257*b89261baSDavid van Moolenbroek     fixpt_t p_mach_pct_cpu; /* aka p_pctcpu */
258*b89261baSDavid van Moolenbroek     int used_ticks;
259*b89261baSDavid van Moolenbroek     size_t process_size;
260*b89261baSDavid van Moolenbroek     pid_t p_pid;
261*b89261baSDavid van Moolenbroek     uid_t p_ruid;
262*b89261baSDavid van Moolenbroek     char p_pri;
263*b89261baSDavid van Moolenbroek     char p_nice;
264*b89261baSDavid van Moolenbroek     size_t p_rssize;
265*b89261baSDavid van Moolenbroek     char u_comm[PI_COMLEN + 1];
266*b89261baSDavid van Moolenbroek } ;
267*b89261baSDavid van Moolenbroek 
268*b89261baSDavid van Moolenbroek /* these are for keeping track of the proc array */
269*b89261baSDavid van Moolenbroek 
270*b89261baSDavid van Moolenbroek static int bytes;
271*b89261baSDavid van Moolenbroek static int pref_len;
272*b89261baSDavid van Moolenbroek static struct osf1_top_proc *pbase;
273*b89261baSDavid van Moolenbroek static struct osf1_top_proc **pref;
274*b89261baSDavid van Moolenbroek 
275*b89261baSDavid van Moolenbroek /* useful externals */
276*b89261baSDavid van Moolenbroek extern int errno;
277*b89261baSDavid van Moolenbroek extern char *sys_errlist[];
278*b89261baSDavid van Moolenbroek 
279*b89261baSDavid van Moolenbroek long percentages();
280*b89261baSDavid van Moolenbroek 
281*b89261baSDavid van Moolenbroek machine_init(statics)
282*b89261baSDavid van Moolenbroek struct statics *statics;
283*b89261baSDavid van Moolenbroek {
284*b89261baSDavid van Moolenbroek     register int i = 0;
285*b89261baSDavid van Moolenbroek     register int pagesize;
286*b89261baSDavid van Moolenbroek     struct tbl_sysinfo sibuf;
287*b89261baSDavid van Moolenbroek 
288*b89261baSDavid van Moolenbroek     if ((kmem = open(KMEM, O_RDONLY)) == -1) {
289*b89261baSDavid van Moolenbroek 	perror(KMEM);
290*b89261baSDavid van Moolenbroek 	return(-1);
291*b89261baSDavid van Moolenbroek     }
292*b89261baSDavid van Moolenbroek     if ((mem = open(MEM, O_RDONLY)) == -1) {
293*b89261baSDavid van Moolenbroek 	perror(MEM);
294*b89261baSDavid van Moolenbroek 	return(-1);
295*b89261baSDavid van Moolenbroek     }
296*b89261baSDavid van Moolenbroek 
297*b89261baSDavid van Moolenbroek     /* get the list of symbols we want to access in the kernel */
298*b89261baSDavid van Moolenbroek     if (nlist(VMUNIX, nlst) == -1)
299*b89261baSDavid van Moolenbroek     {
300*b89261baSDavid van Moolenbroek 	perror("TOP(nlist)");
301*b89261baSDavid van Moolenbroek 	return (-1);
302*b89261baSDavid van Moolenbroek     }
303*b89261baSDavid van Moolenbroek 
304*b89261baSDavid van Moolenbroek     if (nlst[X_MPID].n_type == 0)
305*b89261baSDavid van Moolenbroek     {
306*b89261baSDavid van Moolenbroek 	/* this kernel has no _mpid, so go without */
307*b89261baSDavid van Moolenbroek 	do_last_pid = 0;
308*b89261baSDavid van Moolenbroek     }
309*b89261baSDavid van Moolenbroek     else
310*b89261baSDavid van Moolenbroek     {
311*b89261baSDavid van Moolenbroek 	/* stash away mpid pointer for later use */
312*b89261baSDavid van Moolenbroek 	mpid_offset = nlst[X_MPID].n_value;
313*b89261baSDavid van Moolenbroek     }
314*b89261baSDavid van Moolenbroek 
315*b89261baSDavid van Moolenbroek     /* get the symbol values out of kmem */
316*b89261baSDavid van Moolenbroek     nproc  = table(TBL_PROCINFO, 0, (struct tbl_procinfo *)NULL, INT_MAX, 0);
317*b89261baSDavid van Moolenbroek 
318*b89261baSDavid van Moolenbroek     /* allocate space for proc structure array and array of pointers */
319*b89261baSDavid van Moolenbroek     bytes = nproc * sizeof(struct osf1_top_proc);
320*b89261baSDavid van Moolenbroek     pbase = (struct osf1_top_proc *)malloc(bytes);
321*b89261baSDavid van Moolenbroek     pref  = (struct osf1_top_proc **)malloc(nproc *
322*b89261baSDavid van Moolenbroek                                               sizeof(struct osf1_top_proc *));
323*b89261baSDavid van Moolenbroek 
324*b89261baSDavid van Moolenbroek     /* Just in case ... */
325*b89261baSDavid van Moolenbroek     if (pbase == (struct osf1_top_proc *)NULL ||
326*b89261baSDavid van Moolenbroek                                   pref == (struct osf1_top_proc **)NULL)
327*b89261baSDavid van Moolenbroek     {
328*b89261baSDavid van Moolenbroek 	fprintf(stderr, "top: cannot allocate sufficient memory\n");
329*b89261baSDavid van Moolenbroek 	return(-1);
330*b89261baSDavid van Moolenbroek     }
331*b89261baSDavid van Moolenbroek 
332*b89261baSDavid van Moolenbroek     /* get the page size with "getpagesize" and calculate pageshift from it */
333*b89261baSDavid van Moolenbroek     pagesize = getpagesize();
334*b89261baSDavid van Moolenbroek     pageshift = 0;
335*b89261baSDavid van Moolenbroek     while (pagesize > 1)
336*b89261baSDavid van Moolenbroek     {
337*b89261baSDavid van Moolenbroek 	pageshift++;
338*b89261baSDavid van Moolenbroek 	pagesize >>= 1;
339*b89261baSDavid van Moolenbroek     }
340*b89261baSDavid van Moolenbroek 
341*b89261baSDavid van Moolenbroek     /* we only need the amount of log(2)1024 for our conversion */
342*b89261baSDavid van Moolenbroek     pageshift -= LOG1024;
343*b89261baSDavid van Moolenbroek 
344*b89261baSDavid van Moolenbroek     /* fill in the statics information */
345*b89261baSDavid van Moolenbroek     statics->procstate_names = procstatenames;
346*b89261baSDavid van Moolenbroek     statics->cpustate_names = cpustatenames;
347*b89261baSDavid van Moolenbroek     statics->memory_names = memorynames;
348*b89261baSDavid van Moolenbroek     statics->order_names = ordernames;
349*b89261baSDavid van Moolenbroek     statics->swap_names = swapnames;
350*b89261baSDavid van Moolenbroek 
351*b89261baSDavid van Moolenbroek     /* initialise this, for calculating cpu time */
352*b89261baSDavid van Moolenbroek     if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {
353*b89261baSDavid van Moolenbroek 	perror("TBL_SYSINFO");
354*b89261baSDavid van Moolenbroek 	return(-1);
355*b89261baSDavid van Moolenbroek     }
356*b89261baSDavid van Moolenbroek     old_cpu_ticks[0] = sibuf.si_user;
357*b89261baSDavid van Moolenbroek     old_cpu_ticks[1] = sibuf.si_nice;
358*b89261baSDavid van Moolenbroek     old_cpu_ticks[2] = sibuf.si_sys;
359*b89261baSDavid van Moolenbroek     old_cpu_ticks[3] = sibuf.wait;
360*b89261baSDavid van Moolenbroek     old_cpu_ticks[4] = sibuf.si_idle;
361*b89261baSDavid van Moolenbroek 
362*b89261baSDavid van Moolenbroek     /* all done! */
363*b89261baSDavid van Moolenbroek     return(0);
364*b89261baSDavid van Moolenbroek }
365*b89261baSDavid van Moolenbroek 
format_header(uname_field)366*b89261baSDavid van Moolenbroek char *format_header(uname_field)
367*b89261baSDavid van Moolenbroek register char *uname_field;
368*b89261baSDavid van Moolenbroek {
369*b89261baSDavid van Moolenbroek     register char *ptr;
370*b89261baSDavid van Moolenbroek 
371*b89261baSDavid van Moolenbroek     ptr = header + UNAME_START;
372*b89261baSDavid van Moolenbroek     while (*uname_field != '\0')
373*b89261baSDavid van Moolenbroek     {
374*b89261baSDavid van Moolenbroek 	*ptr++ = *uname_field++;
375*b89261baSDavid van Moolenbroek     }
376*b89261baSDavid van Moolenbroek 
377*b89261baSDavid van Moolenbroek     return(header);
378*b89261baSDavid van Moolenbroek }
379*b89261baSDavid van Moolenbroek 
get_system_info(si)380*b89261baSDavid van Moolenbroek void get_system_info(si)
381*b89261baSDavid van Moolenbroek struct system_info *si;
382*b89261baSDavid van Moolenbroek {
383*b89261baSDavid van Moolenbroek     struct tbl_loadavg labuf;
384*b89261baSDavid van Moolenbroek     struct tbl_sysinfo sibuf;
385*b89261baSDavid van Moolenbroek     struct tbl_swapinfo swbuf;
386*b89261baSDavid van Moolenbroek     vm_statistics_data_t vmstats;
387*b89261baSDavid van Moolenbroek     int swap_pages=0,swap_free=0,i;
388*b89261baSDavid van Moolenbroek     long new_ticks[5],diff_ticks[5];
389*b89261baSDavid van Moolenbroek     long delta_ticks;
390*b89261baSDavid van Moolenbroek 
391*b89261baSDavid van Moolenbroek     if (do_last_pid)
392*b89261baSDavid van Moolenbroek     {
393*b89261baSDavid van Moolenbroek 	/* last pid assigned */
394*b89261baSDavid van Moolenbroek 	(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
395*b89261baSDavid van Moolenbroek 		       "_mpid");
396*b89261baSDavid van Moolenbroek     }
397*b89261baSDavid van Moolenbroek     else
398*b89261baSDavid van Moolenbroek     {
399*b89261baSDavid van Moolenbroek 	si->last_pid = -1;
400*b89261baSDavid van Moolenbroek     }
401*b89261baSDavid van Moolenbroek 
402*b89261baSDavid van Moolenbroek     /* get load averages */
403*b89261baSDavid van Moolenbroek     if (table(TBL_LOADAVG,0,&labuf,1,sizeof(struct tbl_loadavg))<0) {
404*b89261baSDavid van Moolenbroek 	perror("TBL_LOADAVG");
405*b89261baSDavid van Moolenbroek 	return;
406*b89261baSDavid van Moolenbroek     }
407*b89261baSDavid van Moolenbroek     if (labuf.tl_lscale)   /* scaled */
408*b89261baSDavid van Moolenbroek 	for(i=0;i<3;i++)
409*b89261baSDavid van Moolenbroek 	    si->load_avg[i] = ((double)labuf.tl_avenrun.l[i] /
410*b89261baSDavid van Moolenbroek                                             (double)labuf.tl_lscale );
411*b89261baSDavid van Moolenbroek     else                   /* not scaled */
412*b89261baSDavid van Moolenbroek 	for(i=0;i<3;i++)
413*b89261baSDavid van Moolenbroek 	    si->load_avg[i] = labuf.tl_avenrun.d[i];
414*b89261baSDavid van Moolenbroek 
415*b89261baSDavid van Moolenbroek     /* array of cpu state counters */
416*b89261baSDavid van Moolenbroek     if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {
417*b89261baSDavid van Moolenbroek 	perror("TBL_SYSINFO");
418*b89261baSDavid van Moolenbroek 	return;
419*b89261baSDavid van Moolenbroek     }
420*b89261baSDavid van Moolenbroek     new_ticks[0] = sibuf.si_user ; new_ticks[1] = sibuf.si_nice;
421*b89261baSDavid van Moolenbroek     new_ticks[2] = sibuf.si_sys  ; new_ticks[3] = sibuf.wait;
422*b89261baSDavid van Moolenbroek     new_ticks[4] = sibuf.si_idle;
423*b89261baSDavid van Moolenbroek     delta_ticks=0;
424*b89261baSDavid van Moolenbroek     for(i=0;i<5;i++) {
425*b89261baSDavid van Moolenbroek 	diff_ticks[i] = new_ticks[i] - old_cpu_ticks[i];
426*b89261baSDavid van Moolenbroek 	delta_ticks += diff_ticks[i];
427*b89261baSDavid van Moolenbroek 	old_cpu_ticks[i] = new_ticks[i];
428*b89261baSDavid van Moolenbroek     }
429*b89261baSDavid van Moolenbroek     si->cpustates = cpu_states;
430*b89261baSDavid van Moolenbroek     if(delta_ticks)
431*b89261baSDavid van Moolenbroek 	for(i=0;i<5;i++)
432*b89261baSDavid van Moolenbroek 	    si->cpustates[i] = (int)( ( (double)diff_ticks[i] /
433*b89261baSDavid van Moolenbroek                                            (double)delta_ticks ) * 1000 );
434*b89261baSDavid van Moolenbroek 
435*b89261baSDavid van Moolenbroek     /* memory information */
436*b89261baSDavid van Moolenbroek     /* this is possibly bogus - we work out total # pages by */
437*b89261baSDavid van Moolenbroek     /* adding up the free, active, inactive, wired down, and */
438*b89261baSDavid van Moolenbroek     /* zero filled. Anyone who knows a better way, TELL ME!  */
439*b89261baSDavid van Moolenbroek     /* Change: dont use zero filled. */
440*b89261baSDavid van Moolenbroek     (void) vm_statistics(task_self(),&vmstats);
441*b89261baSDavid van Moolenbroek 
442*b89261baSDavid van Moolenbroek     /* thanks DEC for the table() command. No thanks at all for   */
443*b89261baSDavid van Moolenbroek     /* omitting the man page for it from OSF/1 1.2, and failing   */
444*b89261baSDavid van Moolenbroek     /* to document SWAPINFO in the 1.3 man page. Lets hear it for */
445*b89261baSDavid van Moolenbroek     /* include files. */
446*b89261baSDavid van Moolenbroek     i=0;
447*b89261baSDavid van Moolenbroek     while(table(TBL_SWAPINFO,i,&swbuf,1,sizeof(struct tbl_swapinfo))>0) {
448*b89261baSDavid van Moolenbroek 	swap_pages += swbuf.size;
449*b89261baSDavid van Moolenbroek 	swap_free  += swbuf.free;
450*b89261baSDavid van Moolenbroek 	i++;
451*b89261baSDavid van Moolenbroek     }
452*b89261baSDavid van Moolenbroek     memory_stats[0] = pagetok(vmstats.active_count);
453*b89261baSDavid van Moolenbroek     memory_stats[1] = pagetok(vmstats.inactive_count);
454*b89261baSDavid van Moolenbroek     memory_stats[2] = pagetok((vmstats.free_count + vmstats.active_count +
455*b89261baSDavid van Moolenbroek 	vmstats.inactive_count + vmstats.wire_count));
456*b89261baSDavid van Moolenbroek     memory_stats[3] = pagetok(vmstats.free_count);
457*b89261baSDavid van Moolenbroek     swap_stats[0] = pagetok(swap_pages - swap_free);
458*b89261baSDavid van Moolenbroek     swap_stats[1] = pagetok(swap_pages);
459*b89261baSDavid van Moolenbroek     si->memory = memory_stats;
460*b89261baSDavid van Moolenbroek     si->swap = swap_stats;
461*b89261baSDavid van Moolenbroek }
462*b89261baSDavid van Moolenbroek 
463*b89261baSDavid van Moolenbroek static struct handle handle;
464*b89261baSDavid van Moolenbroek 
get_process_info(si,sel,compare_index)465*b89261baSDavid van Moolenbroek caddr_t get_process_info(si, sel, compare_index)
466*b89261baSDavid van Moolenbroek struct system_info *si;
467*b89261baSDavid van Moolenbroek struct process_select *sel;
468*b89261baSDavid van Moolenbroek int compare_index;
469*b89261baSDavid van Moolenbroek {
470*b89261baSDavid van Moolenbroek     register int i;
471*b89261baSDavid van Moolenbroek     register int total_procs;
472*b89261baSDavid van Moolenbroek     register int active_procs;
473*b89261baSDavid van Moolenbroek     register struct osf1_top_proc **prefp;
474*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *pp;
475*b89261baSDavid van Moolenbroek     struct tbl_procinfo p_i[8];
476*b89261baSDavid van Moolenbroek     int j,k,r;
477*b89261baSDavid van Moolenbroek 
478*b89261baSDavid van Moolenbroek     /* these are copied out of sel for speed */
479*b89261baSDavid van Moolenbroek     int show_idle;
480*b89261baSDavid van Moolenbroek     int show_uid;
481*b89261baSDavid van Moolenbroek     int show_command;
482*b89261baSDavid van Moolenbroek 
483*b89261baSDavid van Moolenbroek     /* get a pointer to the states summary array */
484*b89261baSDavid van Moolenbroek     si->procstates = process_states;
485*b89261baSDavid van Moolenbroek 
486*b89261baSDavid van Moolenbroek     /* set up flags which define what we are going to select */
487*b89261baSDavid van Moolenbroek     show_idle = sel->idle;
488*b89261baSDavid van Moolenbroek     show_uid = sel->uid != -1;
489*b89261baSDavid van Moolenbroek     show_command = sel->command != NULL;
490*b89261baSDavid van Moolenbroek 
491*b89261baSDavid van Moolenbroek     /* count up process states and get pointers to interesting procs */
492*b89261baSDavid van Moolenbroek     total_procs = 0;
493*b89261baSDavid van Moolenbroek     active_procs = 0;
494*b89261baSDavid van Moolenbroek     memset((char *)process_states, 0, sizeof(process_states));
495*b89261baSDavid van Moolenbroek     prefp = pref;
496*b89261baSDavid van Moolenbroek     pp=pbase;
497*b89261baSDavid van Moolenbroek     for (j=0; j<nproc; j += 8)
498*b89261baSDavid van Moolenbroek     {
499*b89261baSDavid van Moolenbroek 	r = table(TBL_PROCINFO, j, (struct tbl_procinfo *)p_i, 8,
500*b89261baSDavid van Moolenbroek                                                sizeof(struct tbl_procinfo));
501*b89261baSDavid van Moolenbroek 	for (k=0; k < r; k++ , pp++)
502*b89261baSDavid van Moolenbroek 	{
503*b89261baSDavid van Moolenbroek 	    if(p_i[k].pi_pid == 0)
504*b89261baSDavid van Moolenbroek 	    {
505*b89261baSDavid van Moolenbroek 		pp->p_pid = 0;
506*b89261baSDavid van Moolenbroek 	    }
507*b89261baSDavid van Moolenbroek 	    else
508*b89261baSDavid van Moolenbroek 	    {
509*b89261baSDavid van Moolenbroek 		pp->p_pid = p_i[k].pi_pid;
510*b89261baSDavid van Moolenbroek 		pp->p_ruid = p_i[k].pi_ruid;
511*b89261baSDavid van Moolenbroek 		pp->p_flag = p_i[k].pi_flag;
512*b89261baSDavid van Moolenbroek 		pp->p_nice = getpriority(PRIO_PROCESS,p_i[k].pi_pid);
513*b89261baSDavid van Moolenbroek 		/* Load useful values into the proc structure */
514*b89261baSDavid van Moolenbroek 		do_threads_calculations(pp);
515*b89261baSDavid van Moolenbroek 		/*
516*b89261baSDavid van Moolenbroek 		 *  Place pointers to each valid proc structure in pref[].
517*b89261baSDavid van Moolenbroek 		 *  Process slots that are actually in use have a non-zero
518*b89261baSDavid van Moolenbroek 		 *  status field.
519*b89261baSDavid van Moolenbroek 		 */
520*b89261baSDavid van Moolenbroek #ifdef DEBUG
521*b89261baSDavid van Moolenbroek 		/*
522*b89261baSDavid van Moolenbroek 		 *  Emit debug info about all processes before selection.
523*b89261baSDavid van Moolenbroek 		 */
524*b89261baSDavid van Moolenbroek 		fprintf(stderr, "pid = %d ruid = %d comm = %s p_mach_state = %d p_stat = %d p_flag = 0x%x\n",
525*b89261baSDavid van Moolenbroek 			pp->p_pid, pp->p_ruid, p_i[k].pi_comm,
526*b89261baSDavid van Moolenbroek 			pp->p_mach_state, p_i[k].pi_status, pp->p_flag);
527*b89261baSDavid van Moolenbroek #endif
528*b89261baSDavid van Moolenbroek 		if (pp->p_mach_state != 0)
529*b89261baSDavid van Moolenbroek 		{
530*b89261baSDavid van Moolenbroek 		    total_procs++;
531*b89261baSDavid van Moolenbroek 		    process_states[pp->p_mach_state]++;
532*b89261baSDavid van Moolenbroek 		    if ((pp->p_mach_state != 8) &&
533*b89261baSDavid van Moolenbroek 			(show_idle || (pp->p_mach_pct_cpu != 0) ||
534*b89261baSDavid van Moolenbroek 			 (pp->p_mach_state == 1)) &&
535*b89261baSDavid van Moolenbroek 			(!show_uid || pp->p_ruid == (uid_t)sel->uid)) {
536*b89261baSDavid van Moolenbroek 			*prefp++ = pp;
537*b89261baSDavid van Moolenbroek 			active_procs++;
538*b89261baSDavid van Moolenbroek 		    }
539*b89261baSDavid van Moolenbroek 		}
540*b89261baSDavid van Moolenbroek 	    }
541*b89261baSDavid van Moolenbroek 	}
542*b89261baSDavid van Moolenbroek     }
543*b89261baSDavid van Moolenbroek 
544*b89261baSDavid van Moolenbroek     /* if requested, sort the "interesting" processes */
545*b89261baSDavid van Moolenbroek     if (proc_compares[compare_index] != NULL)
546*b89261baSDavid van Moolenbroek     {
547*b89261baSDavid van Moolenbroek 	qsort((char *)pref, active_procs, sizeof(struct osf1_top_proc *),
548*b89261baSDavid van Moolenbroek 	      proc_compares[compare_index]);
549*b89261baSDavid van Moolenbroek     }
550*b89261baSDavid van Moolenbroek 
551*b89261baSDavid van Moolenbroek     /* remember active and total counts */
552*b89261baSDavid van Moolenbroek     si->p_total = total_procs;
553*b89261baSDavid van Moolenbroek     si->p_active = pref_len = active_procs;
554*b89261baSDavid van Moolenbroek 
555*b89261baSDavid van Moolenbroek     /* pass back a handle */
556*b89261baSDavid van Moolenbroek     handle.next_proc = pref;
557*b89261baSDavid van Moolenbroek     handle.remaining = active_procs;
558*b89261baSDavid van Moolenbroek     return((caddr_t)&handle);
559*b89261baSDavid van Moolenbroek }
560*b89261baSDavid van Moolenbroek 
561*b89261baSDavid van Moolenbroek char fmt[MAX_COLS];		/* static area where result is built */
562*b89261baSDavid van Moolenbroek 
format_next_process(handle,get_userid)563*b89261baSDavid van Moolenbroek char *format_next_process(handle, get_userid)
564*b89261baSDavid van Moolenbroek caddr_t handle;
565*b89261baSDavid van Moolenbroek char *(*get_userid)();
566*b89261baSDavid van Moolenbroek {
567*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *pp;
568*b89261baSDavid van Moolenbroek     register long cputime;
569*b89261baSDavid van Moolenbroek     register double pct;
570*b89261baSDavid van Moolenbroek     struct user u;
571*b89261baSDavid van Moolenbroek     struct handle *hp;
572*b89261baSDavid van Moolenbroek 
573*b89261baSDavid van Moolenbroek     /* find and remember the next proc structure */
574*b89261baSDavid van Moolenbroek     hp = (struct handle *)handle;
575*b89261baSDavid van Moolenbroek     pp = *(hp->next_proc++);
576*b89261baSDavid van Moolenbroek     hp->remaining--;
577*b89261baSDavid van Moolenbroek 
578*b89261baSDavid van Moolenbroek     /* get the process's user struct and set cputime */
579*b89261baSDavid van Moolenbroek 
580*b89261baSDavid van Moolenbroek     if (table(TBL_UAREA,pp->p_pid,&u,1,sizeof(struct user))<0) {
581*b89261baSDavid van Moolenbroek     /* whoops, it must have died between the read of the proc area
582*b89261baSDavid van Moolenbroek      * and now. Oh well, lets just dump some meaningless thing out
583*b89261baSDavid van Moolenbroek      * to keep the rest of the program happy
584*b89261baSDavid van Moolenbroek      */
585*b89261baSDavid van Moolenbroek 	sprintf(fmt,
586*b89261baSDavid van Moolenbroek 		Proc_format,
587*b89261baSDavid van Moolenbroek 		pp->p_pid,
588*b89261baSDavid van Moolenbroek 		(*get_userid)(pp->p_ruid),
589*b89261baSDavid van Moolenbroek 		0,
590*b89261baSDavid van Moolenbroek 		0,
591*b89261baSDavid van Moolenbroek 		"",
592*b89261baSDavid van Moolenbroek 		"",
593*b89261baSDavid van Moolenbroek 		"dead",
594*b89261baSDavid van Moolenbroek 		"",
595*b89261baSDavid van Moolenbroek 		0.0,
596*b89261baSDavid van Moolenbroek 		"<dead>");
597*b89261baSDavid van Moolenbroek 	    return(fmt);
598*b89261baSDavid van Moolenbroek     }
599*b89261baSDavid van Moolenbroek 
600*b89261baSDavid van Moolenbroek     /* set u_comm for system processes */
601*b89261baSDavid van Moolenbroek     if (u.u_comm[0] == '\0')
602*b89261baSDavid van Moolenbroek     {
603*b89261baSDavid van Moolenbroek 	if (pp->p_pid == 0)
604*b89261baSDavid van Moolenbroek 	{
605*b89261baSDavid van Moolenbroek 	    (void) strcpy(u.u_comm, "[idle]");
606*b89261baSDavid van Moolenbroek 	}
607*b89261baSDavid van Moolenbroek 	else if (pp->p_pid == 2)
608*b89261baSDavid van Moolenbroek 	{
609*b89261baSDavid van Moolenbroek 	    (void) strcpy(u.u_comm, "[execpt.hndlr]");
610*b89261baSDavid van Moolenbroek 	}
611*b89261baSDavid van Moolenbroek     }
612*b89261baSDavid van Moolenbroek 
613*b89261baSDavid van Moolenbroek     /* Check if process is in core */
614*b89261baSDavid van Moolenbroek     if (!(pp->p_flag & SLOAD)) {
615*b89261baSDavid van Moolenbroek 	/*
616*b89261baSDavid van Moolenbroek 	 * Print swapped processes as <pname>
617*b89261baSDavid van Moolenbroek 	 */
618*b89261baSDavid van Moolenbroek 	char buf[sizeof(u.u_comm)];
619*b89261baSDavid van Moolenbroek 	(void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
620*b89261baSDavid van Moolenbroek 	u.u_comm[0] = '<';
621*b89261baSDavid van Moolenbroek 	(void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
622*b89261baSDavid van Moolenbroek 	u.u_comm[sizeof(u.u_comm) - 2] = '\0';
623*b89261baSDavid van Moolenbroek 	(void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
624*b89261baSDavid van Moolenbroek 	u.u_comm[sizeof(u.u_comm) - 1] = '\0';
625*b89261baSDavid van Moolenbroek     }
626*b89261baSDavid van Moolenbroek 
627*b89261baSDavid van Moolenbroek     cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
628*b89261baSDavid van Moolenbroek 
629*b89261baSDavid van Moolenbroek     /* calculate the base for cpu percentages */
630*b89261baSDavid van Moolenbroek     pct = pctdouble(pp->p_mach_pct_cpu);
631*b89261baSDavid van Moolenbroek 
632*b89261baSDavid van Moolenbroek     /* format this entry */
633*b89261baSDavid van Moolenbroek     sprintf(fmt,
634*b89261baSDavid van Moolenbroek 	    Proc_format,
635*b89261baSDavid van Moolenbroek 	    pp->p_pid,
636*b89261baSDavid van Moolenbroek 	    (*get_userid)(pp->p_ruid),
637*b89261baSDavid van Moolenbroek 	    pp->p_pri,
638*b89261baSDavid van Moolenbroek 	    pp->p_nice,
639*b89261baSDavid van Moolenbroek             format_k(pp->p_mach_virt_size/1024),
640*b89261baSDavid van Moolenbroek             format_k(pp->p_rssize/1000),
641*b89261baSDavid van Moolenbroek 	    state_abbrev[pp->p_mach_state],
642*b89261baSDavid van Moolenbroek 	    format_time(cputime),
643*b89261baSDavid van Moolenbroek 	    100.0 * ((double)pp->p_mach_pct_cpu / 10000.0),
644*b89261baSDavid van Moolenbroek 	    printable(u.u_comm));
645*b89261baSDavid van Moolenbroek 
646*b89261baSDavid van Moolenbroek     /* return the result */
647*b89261baSDavid van Moolenbroek     return(fmt);
648*b89261baSDavid van Moolenbroek }
649*b89261baSDavid van Moolenbroek 
650*b89261baSDavid van Moolenbroek /*
651*b89261baSDavid van Moolenbroek  *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
652*b89261baSDavid van Moolenbroek  *	"offset" is the byte offset into the kernel for the desired value,
653*b89261baSDavid van Moolenbroek  *  	"ptr" points to a buffer into which the value is retrieved,
654*b89261baSDavid van Moolenbroek  *  	"size" is the size of the buffer (and the object to retrieve),
655*b89261baSDavid van Moolenbroek  *  	"refstr" is a reference string used when printing error meessages,
656*b89261baSDavid van Moolenbroek  *	    if "refstr" starts with a '!', then a failure on read will not
657*b89261baSDavid van Moolenbroek  *  	    be fatal (this may seem like a silly way to do things, but I
658*b89261baSDavid van Moolenbroek  *  	    really didn't want the overhead of another argument).
659*b89261baSDavid van Moolenbroek  *
660*b89261baSDavid van Moolenbroek  */
661*b89261baSDavid van Moolenbroek 
getkval(offset,ptr,size,refstr)662*b89261baSDavid van Moolenbroek getkval(offset, ptr, size, refstr)
663*b89261baSDavid van Moolenbroek 
664*b89261baSDavid van Moolenbroek unsigned long offset;
665*b89261baSDavid van Moolenbroek int *ptr;
666*b89261baSDavid van Moolenbroek int size;
667*b89261baSDavid van Moolenbroek char *refstr;
668*b89261baSDavid van Moolenbroek 
669*b89261baSDavid van Moolenbroek {
670*b89261baSDavid van Moolenbroek     if (lseek(kmem, (long)offset, L_SET) == -1) {
671*b89261baSDavid van Moolenbroek         if (*refstr == '!')
672*b89261baSDavid van Moolenbroek             refstr++;
673*b89261baSDavid van Moolenbroek         (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
674*b89261baSDavid van Moolenbroek 		       refstr, strerror(errno));
675*b89261baSDavid van Moolenbroek         quit(23);
676*b89261baSDavid van Moolenbroek     }
677*b89261baSDavid van Moolenbroek     if (read(kmem, (char *) ptr, size) == -1) {
678*b89261baSDavid van Moolenbroek         if (*refstr == '!')
679*b89261baSDavid van Moolenbroek             return(0);
680*b89261baSDavid van Moolenbroek         else {
681*b89261baSDavid van Moolenbroek             (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
682*b89261baSDavid van Moolenbroek 			   refstr, strerror(errno));
683*b89261baSDavid van Moolenbroek             quit(23);
684*b89261baSDavid van Moolenbroek         }
685*b89261baSDavid van Moolenbroek     }
686*b89261baSDavid van Moolenbroek     return(1);
687*b89261baSDavid van Moolenbroek }
688*b89261baSDavid van Moolenbroek 
689*b89261baSDavid van Moolenbroek /* comparison routines for qsort */
690*b89261baSDavid van Moolenbroek 
691*b89261baSDavid van Moolenbroek /*
692*b89261baSDavid van Moolenbroek  * There are currently four possible comparison routines.  main selects
693*b89261baSDavid van Moolenbroek  * one of these by indexing in to the array proc_compares.
694*b89261baSDavid van Moolenbroek  *
695*b89261baSDavid van Moolenbroek  * Possible keys are defined as macros below.  Currently these keys are
696*b89261baSDavid van Moolenbroek  * defined:  percent cpu, cpu ticks, process state, resident set size,
697*b89261baSDavid van Moolenbroek  * total virtual memory usage.  The process states are ordered as follows
698*b89261baSDavid van Moolenbroek  * (from least to most important):  WAIT, zomb, ???, halt, idle, sleep,
699*b89261baSDavid van Moolenbroek  * stop, run.  The array declaration below maps a process state index into
700*b89261baSDavid van Moolenbroek  * a number that reflects this ordering.
701*b89261baSDavid van Moolenbroek  */
702*b89261baSDavid van Moolenbroek 
703*b89261baSDavid van Moolenbroek /* First, the possible comparison keys.  These are defined in such a way
704*b89261baSDavid van Moolenbroek    that they can be merely listed in the source code to define the actual
705*b89261baSDavid van Moolenbroek    desired ordering.
706*b89261baSDavid van Moolenbroek  */
707*b89261baSDavid van Moolenbroek 
708*b89261baSDavid van Moolenbroek #define ORDERKEY_PCTCPU  if (lresult = p2->p_mach_pct_cpu - p1->p_mach_pct_cpu,\
709*b89261baSDavid van Moolenbroek                            (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
710*b89261baSDavid van Moolenbroek #define ORDERKEY_CPTICKS if ((result = p2->used_ticks - p1->used_ticks) == 0)
711*b89261baSDavid van Moolenbroek #define ORDERKEY_STATE   if ((result = sorted_state[p2->p_mach_state] - \
712*b89261baSDavid van Moolenbroek                             sorted_state[p1->p_mach_state])  == 0)
713*b89261baSDavid van Moolenbroek #define ORDERKEY_PRIO    if ((result = p2->p_pri - p1->p_pri) == 0)
714*b89261baSDavid van Moolenbroek #define ORDERKEY_RSSIZE  if ((result = p2->p_rssize - p1->p_rssize) == 0)
715*b89261baSDavid van Moolenbroek #define ORDERKEY_MEM     if ((result = p2->p_mach_virt_size - p1->p_mach_virt_size) == 0)
716*b89261baSDavid van Moolenbroek 
717*b89261baSDavid van Moolenbroek /* Now the array that maps process state to a weight */
718*b89261baSDavid van Moolenbroek 
719*b89261baSDavid van Moolenbroek static unsigned char sorted_state[] =
720*b89261baSDavid van Moolenbroek {
721*b89261baSDavid van Moolenbroek    0, /*""*/
722*b89261baSDavid van Moolenbroek    8, /*"run"*/
723*b89261baSDavid van Moolenbroek    1, /*"WAIT"*/
724*b89261baSDavid van Moolenbroek    6, /*"sleep"*/
725*b89261baSDavid van Moolenbroek    5, /*"idle"*/
726*b89261baSDavid van Moolenbroek    7, /*"stop"*/
727*b89261baSDavid van Moolenbroek    4, /*"halt"*/
728*b89261baSDavid van Moolenbroek    3, /*"???"*/
729*b89261baSDavid van Moolenbroek    2, /*"zomb"*/
730*b89261baSDavid van Moolenbroek };
731*b89261baSDavid van Moolenbroek 
732*b89261baSDavid van Moolenbroek /* compare_cpu - the comparison function for sorting by cpu percentage */
733*b89261baSDavid van Moolenbroek 
734*b89261baSDavid van Moolenbroek compare_cpu(pp1, pp2)
735*b89261baSDavid van Moolenbroek 
736*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp1;
737*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp2;
738*b89261baSDavid van Moolenbroek 
739*b89261baSDavid van Moolenbroek {
740*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p1;
741*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p2;
742*b89261baSDavid van Moolenbroek     register long result;
743*b89261baSDavid van Moolenbroek     register pctcpu lresult;
744*b89261baSDavid van Moolenbroek 
745*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
746*b89261baSDavid van Moolenbroek     p1 = *pp1;
747*b89261baSDavid van Moolenbroek     p2 = *pp2;
748*b89261baSDavid van Moolenbroek 
749*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
750*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
751*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
752*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
753*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
754*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
755*b89261baSDavid van Moolenbroek     ;
756*b89261baSDavid van Moolenbroek 
757*b89261baSDavid van Moolenbroek     return(result);
758*b89261baSDavid van Moolenbroek }
759*b89261baSDavid van Moolenbroek 
760*b89261baSDavid van Moolenbroek /* compare_size - the comparison function for sorting by total memory usage */
761*b89261baSDavid van Moolenbroek 
762*b89261baSDavid van Moolenbroek compare_size(pp1, pp2)
763*b89261baSDavid van Moolenbroek 
764*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp1;
765*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp2;
766*b89261baSDavid van Moolenbroek 
767*b89261baSDavid van Moolenbroek {
768*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p1;
769*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p2;
770*b89261baSDavid van Moolenbroek     register long result;
771*b89261baSDavid van Moolenbroek     register pctcpu lresult;
772*b89261baSDavid van Moolenbroek 
773*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
774*b89261baSDavid van Moolenbroek     p1 = *pp1;
775*b89261baSDavid van Moolenbroek     p2 = *pp2;
776*b89261baSDavid van Moolenbroek 
777*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
778*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
779*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
780*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
781*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
782*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
783*b89261baSDavid van Moolenbroek     ;
784*b89261baSDavid van Moolenbroek 
785*b89261baSDavid van Moolenbroek     return(result);
786*b89261baSDavid van Moolenbroek }
787*b89261baSDavid van Moolenbroek 
788*b89261baSDavid van Moolenbroek /* compare_res - the comparison function for sorting by resident set size */
789*b89261baSDavid van Moolenbroek 
790*b89261baSDavid van Moolenbroek compare_res(pp1, pp2)
791*b89261baSDavid van Moolenbroek 
792*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp1;
793*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp2;
794*b89261baSDavid van Moolenbroek 
795*b89261baSDavid van Moolenbroek {
796*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p1;
797*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p2;
798*b89261baSDavid van Moolenbroek     register long result;
799*b89261baSDavid van Moolenbroek     register pctcpu lresult;
800*b89261baSDavid van Moolenbroek 
801*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
802*b89261baSDavid van Moolenbroek     p1 = *pp1;
803*b89261baSDavid van Moolenbroek     p2 = *pp2;
804*b89261baSDavid van Moolenbroek 
805*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
806*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
807*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
808*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
809*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
810*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
811*b89261baSDavid van Moolenbroek     ;
812*b89261baSDavid van Moolenbroek 
813*b89261baSDavid van Moolenbroek     return(result);
814*b89261baSDavid van Moolenbroek }
815*b89261baSDavid van Moolenbroek 
816*b89261baSDavid van Moolenbroek /* compare_time - the comparison function for sorting by total cpu time */
817*b89261baSDavid van Moolenbroek 
818*b89261baSDavid van Moolenbroek compare_time(pp1, pp2)
819*b89261baSDavid van Moolenbroek 
820*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp1;
821*b89261baSDavid van Moolenbroek struct osf1_top_proc **pp2;
822*b89261baSDavid van Moolenbroek 
823*b89261baSDavid van Moolenbroek {
824*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p1;
825*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *p2;
826*b89261baSDavid van Moolenbroek     register long result;
827*b89261baSDavid van Moolenbroek     register pctcpu lresult;
828*b89261baSDavid van Moolenbroek 
829*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
830*b89261baSDavid van Moolenbroek     p1 = *pp1;
831*b89261baSDavid van Moolenbroek     p2 = *pp2;
832*b89261baSDavid van Moolenbroek 
833*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
834*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
835*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
836*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
837*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
838*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
839*b89261baSDavid van Moolenbroek     ;
840*b89261baSDavid van Moolenbroek 
841*b89261baSDavid van Moolenbroek     return(result);
842*b89261baSDavid van Moolenbroek }
843*b89261baSDavid van Moolenbroek 
844*b89261baSDavid van Moolenbroek /*
845*b89261baSDavid van Moolenbroek  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
846*b89261baSDavid van Moolenbroek  *		the process does not exist.
847*b89261baSDavid van Moolenbroek  *		It is EXTREMLY IMPORTANT that this function work correctly.
848*b89261baSDavid van Moolenbroek  *		If top runs setuid root (as in SVR4), then this function
849*b89261baSDavid van Moolenbroek  *		is the only thing that stands in the way of a serious
850*b89261baSDavid van Moolenbroek  *		security problem.  It validates requests for the "kill"
851*b89261baSDavid van Moolenbroek  *		and "renice" commands.
852*b89261baSDavid van Moolenbroek  */
853*b89261baSDavid van Moolenbroek 
proc_owner(pid)854*b89261baSDavid van Moolenbroek int proc_owner(pid)
855*b89261baSDavid van Moolenbroek 
856*b89261baSDavid van Moolenbroek int pid;
857*b89261baSDavid van Moolenbroek 
858*b89261baSDavid van Moolenbroek {
859*b89261baSDavid van Moolenbroek     register int cnt;
860*b89261baSDavid van Moolenbroek     register struct osf1_top_proc **prefp;
861*b89261baSDavid van Moolenbroek     register struct osf1_top_proc *pp;
862*b89261baSDavid van Moolenbroek 
863*b89261baSDavid van Moolenbroek     prefp = pref;
864*b89261baSDavid van Moolenbroek     cnt = pref_len;
865*b89261baSDavid van Moolenbroek     while (--cnt >= 0)
866*b89261baSDavid van Moolenbroek     {
867*b89261baSDavid van Moolenbroek 	if ((pp = *prefp++)->p_pid == (pid_t)pid)
868*b89261baSDavid van Moolenbroek 	{
869*b89261baSDavid van Moolenbroek 	    return((int)pp->p_ruid);
870*b89261baSDavid van Moolenbroek 	}
871*b89261baSDavid van Moolenbroek     }
872*b89261baSDavid van Moolenbroek     return(-1);
873*b89261baSDavid van Moolenbroek }
874*b89261baSDavid van Moolenbroek 
875*b89261baSDavid van Moolenbroek 
876*b89261baSDavid van Moolenbroek /*
877*b89261baSDavid van Moolenbroek  * We use the Mach interface, as well as the table(UAREA,,,) call to
878*b89261baSDavid van Moolenbroek  * get some more information, then put it into unused fields in our
879*b89261baSDavid van Moolenbroek  * copy of the proc structure, to make it faster and easier to get at
880*b89261baSDavid van Moolenbroek  * later.
881*b89261baSDavid van Moolenbroek  */
do_threads_calculations(thisproc)882*b89261baSDavid van Moolenbroek void do_threads_calculations(thisproc)
883*b89261baSDavid van Moolenbroek struct osf1_top_proc *thisproc;
884*b89261baSDavid van Moolenbroek {
885*b89261baSDavid van Moolenbroek   int j;
886*b89261baSDavid van Moolenbroek   task_t  thistask;
887*b89261baSDavid van Moolenbroek   task_basic_info_data_t   taskinfo;
888*b89261baSDavid van Moolenbroek   unsigned int taskinfo_l;
889*b89261baSDavid van Moolenbroek   thread_array_t    threadarr;
890*b89261baSDavid van Moolenbroek   unsigned int threadarr_l;
891*b89261baSDavid van Moolenbroek   thread_basic_info_t     threadinfo;
892*b89261baSDavid van Moolenbroek   thread_basic_info_data_t threadinfodata;
893*b89261baSDavid van Moolenbroek   unsigned int threadinfo_l;
894*b89261baSDavid van Moolenbroek   int task_tot_cpu=0;  /* total cpu usage of threads in a task */
895*b89261baSDavid van Moolenbroek   struct user u;
896*b89261baSDavid van Moolenbroek 
897*b89261baSDavid van Moolenbroek   thisproc->p_pri=0;
898*b89261baSDavid van Moolenbroek   thisproc->p_rssize=0;
899*b89261baSDavid van Moolenbroek   thisproc->p_mach_virt_size=0;
900*b89261baSDavid van Moolenbroek   thisproc->p_mach_state=0;
901*b89261baSDavid van Moolenbroek   thisproc->p_mach_pct_cpu=0;
902*b89261baSDavid van Moolenbroek 
903*b89261baSDavid van Moolenbroek   if(task_by_unix_pid(task_self(), thisproc->p_pid, &thistask)
904*b89261baSDavid van Moolenbroek                                                 != KERN_SUCCESS){
905*b89261baSDavid van Moolenbroek       thisproc->p_mach_state=8; /* (zombie) */
906*b89261baSDavid van Moolenbroek   } else {
907*b89261baSDavid van Moolenbroek     taskinfo_l=TASK_BASIC_INFO_COUNT;
908*b89261baSDavid van Moolenbroek     if(task_info(thistask, TASK_BASIC_INFO, (task_info_t) &taskinfo,
909*b89261baSDavid van Moolenbroek                                       &taskinfo_l)
910*b89261baSDavid van Moolenbroek        != KERN_SUCCESS) {
911*b89261baSDavid van Moolenbroek       thisproc->p_mach_state=8; /* (zombie) */
912*b89261baSDavid van Moolenbroek     } else {
913*b89261baSDavid van Moolenbroek       int minim_state=99,mcurp=1000,mbasp=1000,mslpt=999;
914*b89261baSDavid van Moolenbroek 
915*b89261baSDavid van Moolenbroek       thisproc->p_rssize=taskinfo.resident_size;
916*b89261baSDavid van Moolenbroek       thisproc->p_mach_virt_size=taskinfo.virtual_size;
917*b89261baSDavid van Moolenbroek 
918*b89261baSDavid van Moolenbroek       if (task_threads(thistask, &threadarr, &threadarr_l) != KERN_SUCCESS)
919*b89261baSDavid van Moolenbroek 	  return;
920*b89261baSDavid van Moolenbroek       threadinfo= &threadinfodata;
921*b89261baSDavid van Moolenbroek       for(j=0; j < threadarr_l; j++) {
922*b89261baSDavid van Moolenbroek 	threadinfo_l=THREAD_BASIC_INFO_COUNT;
923*b89261baSDavid van Moolenbroek 	if(thread_info(threadarr[j],THREAD_BASIC_INFO,
924*b89261baSDavid van Moolenbroek 	       (thread_info_t) threadinfo, &threadinfo_l) == KERN_SUCCESS) {
925*b89261baSDavid van Moolenbroek 
926*b89261baSDavid van Moolenbroek 	  task_tot_cpu += threadinfo->cpu_usage;
927*b89261baSDavid van Moolenbroek 	  if(minim_state>threadinfo->run_state)
928*b89261baSDavid van Moolenbroek               minim_state=threadinfo->run_state;
929*b89261baSDavid van Moolenbroek 	  if(mcurp>threadinfo->cur_priority)
930*b89261baSDavid van Moolenbroek               mcurp=threadinfo->cur_priority;
931*b89261baSDavid van Moolenbroek 	  if(mbasp>threadinfo->base_priority)
932*b89261baSDavid van Moolenbroek               mbasp=threadinfo->base_priority;
933*b89261baSDavid van Moolenbroek 	  if(mslpt>threadinfo->sleep_time)
934*b89261baSDavid van Moolenbroek               mslpt=threadinfo->sleep_time;
935*b89261baSDavid van Moolenbroek 	}
936*b89261baSDavid van Moolenbroek       }
937*b89261baSDavid van Moolenbroek       switch (minim_state) {
938*b89261baSDavid van Moolenbroek       case TH_STATE_RUNNING:
939*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=1;  break;
940*b89261baSDavid van Moolenbroek       case TH_STATE_UNINTERRUPTIBLE:
941*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=2; break;
942*b89261baSDavid van Moolenbroek       case TH_STATE_WAITING:
943*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=(threadinfo->sleep_time > 20) ? 4 : 3; break;
944*b89261baSDavid van Moolenbroek       case TH_STATE_STOPPED:
945*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=5; break;
946*b89261baSDavid van Moolenbroek       case TH_STATE_HALTED:
947*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=6; break;
948*b89261baSDavid van Moolenbroek       default:
949*b89261baSDavid van Moolenbroek 	    thisproc->p_mach_state=7; break;
950*b89261baSDavid van Moolenbroek       }
951*b89261baSDavid van Moolenbroek 
952*b89261baSDavid van Moolenbroek       thisproc->p_pri=mcurp;
953*b89261baSDavid van Moolenbroek       thisproc->p_mach_pct_cpu=(fixpt_t)(task_tot_cpu*10);
954*b89261baSDavid van Moolenbroek       vm_deallocate(task_self(),(vm_address_t)threadarr,threadarr_l);
955*b89261baSDavid van Moolenbroek     }
956*b89261baSDavid van Moolenbroek   }
957*b89261baSDavid van Moolenbroek   if (table(TBL_UAREA,thisproc->p_pid,&u,1,sizeof(struct user))>=0) {
958*b89261baSDavid van Moolenbroek     thisproc->used_ticks=(u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec);
959*b89261baSDavid van Moolenbroek     thisproc->process_size=u.u_tsize + u.u_dsize + u.u_ssize;
960*b89261baSDavid van Moolenbroek   }
961*b89261baSDavid van Moolenbroek }
962*b89261baSDavid van Moolenbroek 
963*b89261baSDavid van Moolenbroek /* The reason for this function is that the system call will let
964*b89261baSDavid van Moolenbroek  * someone lower their own processes priority (because top is setuid :-(
965*b89261baSDavid van Moolenbroek  * Yes, using syscall() is a hack, if you can come up with something
966*b89261baSDavid van Moolenbroek  * better, then I'd be thrilled to hear it. I'm not holding my breath,
967*b89261baSDavid van Moolenbroek  * though.
968*b89261baSDavid van Moolenbroek  *             Anthony.
969*b89261baSDavid van Moolenbroek  */
setpriority(int dummy,int procnum,int niceval)970*b89261baSDavid van Moolenbroek int setpriority(int dummy, int procnum, int niceval)
971*b89261baSDavid van Moolenbroek {
972*b89261baSDavid van Moolenbroek 
973*b89261baSDavid van Moolenbroek     int uid, curprio;
974*b89261baSDavid van Moolenbroek 
975*b89261baSDavid van Moolenbroek     uid=getuid();
976*b89261baSDavid van Moolenbroek     if ( (curprio=getpriority(PRIO_PROCESS,procnum) ) == -1)
977*b89261baSDavid van Moolenbroek     {
978*b89261baSDavid van Moolenbroek 	return(-1); /* errno goes back to renice_process() */
979*b89261baSDavid van Moolenbroek     }
980*b89261baSDavid van Moolenbroek     /* check for not-root - if so, dont allow users to decrease priority */
981*b89261baSDavid van Moolenbroek     else if ( uid && (niceval<curprio) )
982*b89261baSDavid van Moolenbroek     {
983*b89261baSDavid van Moolenbroek 	errno=EACCES;
984*b89261baSDavid van Moolenbroek 	return(-1);
985*b89261baSDavid van Moolenbroek     }
986*b89261baSDavid van Moolenbroek     return(syscall(SYS_setpriority,PRIO_PROCESS,procnum,niceval));
987*b89261baSDavid van Moolenbroek }
988*b89261baSDavid van Moolenbroek 
989