xref: /openbsd-src/usr.bin/top/machine.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: machine.c,v 1.25 2001/07/12 05:17:26 deraadt Exp $	*/
2 
3 /*
4  * top - a top users display for Unix
5  *
6  * SYNOPSIS:  For an OpenBSD system
7  *
8  * DESCRIPTION:
9  * This is the machine-dependent module for OpenBSD
10  * Tested on:
11  *	i386
12  *
13  * TERMCAP: -ltermlib
14  *
15  * CFLAGS: -DHAVE_GETOPT -DORDER
16  *
17  * AUTHOR:  Thorsten Lockert <tholo@sigmasoft.com>
18  *          Adapted from BSD4.4 by Christos Zoulas <christos@ee.cornell.edu>
19  *          Patch for process wait display by Jarl F. Greipsland <jarle@idt.unit.no>
20  *	    Patch for -DORDER by Kenneth Stailey <kstailey@disclosure.com>
21  *	    Patch for new swapctl(2) by Tobias Weingartner <weingart@openbsd.org>
22  */
23 
24 #include <sys/types.h>
25 #include <sys/signal.h>
26 #include <sys/param.h>
27 
28 #define DOSWAP
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <err.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <sys/errno.h>
38 #include <sys/sysctl.h>
39 #include <sys/dir.h>
40 #include <sys/dkstat.h>
41 #include <sys/file.h>
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 
45 #ifdef DOSWAP
46 #include <sys/swap.h>
47 #include <err.h>
48 #endif
49 
50 static int swapmode __P((int *, int *));
51 
52 #include "top.h"
53 #include "display.h"
54 #include "machine.h"
55 #include "utils.h"
56 
57 /* get_process_info passes back a handle.  This is what it looks like: */
58 
59 struct handle {
60 	struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
61 	int     remaining;	/* number of pointers remaining */
62 };
63 
64 /* declarations for load_avg */
65 #include "loadavg.h"
66 
67 #define PP(pp, field) ((pp)->kp_proc . field)
68 #define EP(pp, field) ((pp)->kp_eproc . field)
69 #define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
70 
71 /* what we consider to be process size: */
72 #define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
73 
74 /*
75  *  These definitions control the format of the per-process area
76  */
77 static char header[] =
78 "  PID X        PRI NICE  SIZE   RES STATE WAIT     TIME    CPU COMMAND";
79 /* 0123456   -- field to fill in starts at header+6 */
80 #define UNAME_START 6
81 
82 #define Proc_format \
83 	"%5d %-8.8s %3d %4d %5s %5s %-5s %-6.6s %6s %5.2f%% %.14s"
84 
85 
86 /* process state names for the "STATE" column of the display */
87 /* the extra nulls in the string "run" are for adding a slash and
88    the processor number when needed */
89 
90 char *state_abbrev[] = {
91 	"", "start", "run\0\0\0", "sleep", "stop", "zomb",
92 };
93 
94 
95 static int stathz;
96 
97 /* these are for calculating cpu state percentages */
98 static long cp_time[CPUSTATES];
99 static long cp_old[CPUSTATES];
100 static long cp_diff[CPUSTATES];
101 
102 /* these are for detailing the process states */
103 int     process_states[7];
104 char   *procstatenames[] = {
105 	"", " starting, ", " running, ", " idle, ", " stopped, ", " zombie, ",
106 	NULL
107 };
108 
109 /* these are for detailing the cpu states */
110 int     cpu_states[CPUSTATES];
111 char   *cpustatenames[] = {
112 	"user", "nice", "system", "interrupt", "idle", NULL
113 };
114 
115 /* these are for detailing the memory statistics */
116 int     memory_stats[8];
117 char   *memorynames[] = {
118 	"Real: ", "K/", "K act/tot  ", "Free: ", "K  ",
119 #ifdef DOSWAP
120 	"Swap: ", "K/", "K used/tot",
121 #endif
122 	NULL
123 };
124 
125 #ifdef ORDER
126 /* these are names given to allowed sorting orders -- first is default */
127 char   *ordernames[] = {"cpu", "size", "res", "time", "pri", NULL};
128 #endif
129 
130 /* these are for keeping track of the proc array */
131 static int nproc;
132 static int onproc = -1;
133 static int pref_len;
134 static struct kinfo_proc *pbase;
135 static struct kinfo_proc **pref;
136 
137 /* these are for getting the memory statistics */
138 static int pageshift;		/* log base 2 of the pagesize */
139 
140 /* define pagetok in terms of pageshift */
141 #define pagetok(size) ((size) << pageshift)
142 
143 int
144 getstathz()
145 {
146 	struct clockinfo cinf;
147 	size_t  size = sizeof(cinf);
148 	int     mib[2];
149 
150 	mib[0] = CTL_KERN;
151 	mib[1] = KERN_CLOCKRATE;
152 	if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
153 		return (-1);
154 	return (cinf.stathz);
155 }
156 
157 int
158 machine_init(statics)
159 	struct statics *statics;
160 {
161 	int pagesize;
162 
163 	stathz = getstathz();
164 	if (stathz == -1)
165 		return (-1);
166 
167 	pbase = NULL;
168 	pref = NULL;
169 	onproc = -1;
170 	nproc = 0;
171 
172 	/* get the page size with "getpagesize" and calculate pageshift from
173 	 * it */
174 	pagesize = getpagesize();
175 	pageshift = 0;
176 	while (pagesize > 1) {
177 		pageshift++;
178 		pagesize >>= 1;
179 	}
180 
181 	/* we only need the amount of log(2)1024 for our conversion */
182 	pageshift -= LOG1024;
183 
184 	/* fill in the statics information */
185 	statics->procstate_names = procstatenames;
186 	statics->cpustate_names = cpustatenames;
187 	statics->memory_names = memorynames;
188 #ifdef ORDER
189 	statics->order_names = ordernames;
190 #endif
191 	return (0);
192 }
193 
194 char *
195 format_header(uname_field)
196 	char   *uname_field;
197 {
198 	char *ptr;
199 
200 	ptr = header + UNAME_START;
201 	while (*uname_field != '\0') {
202 		*ptr++ = *uname_field++;
203 	}
204 	return (header);
205 }
206 
207 void
208 get_system_info(si)
209 	struct system_info *si;
210 {
211 	static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
212 	static int vmtotal_mib[] = {CTL_VM, VM_METER};
213 	static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
214 	struct loadavg sysload;
215 	struct vmtotal vmtotal;
216 	double *infoloadp;
217 	int total, i;
218 	size_t  size;
219 
220 	size = sizeof(cp_time);
221 	if (sysctl(cp_time_mib, 2, &cp_time, &size, NULL, 0) < 0) {
222 		warn("sysctl kern.cp_time failed");
223 		total = 0;
224 	}
225 
226 	size = sizeof(sysload);
227 	if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0) {
228 		warn("sysctl failed");
229 		total = 0;
230 	}
231 	infoloadp = si->load_avg;
232 	for (i = 0; i < 3; i++)
233 		*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
234 
235 	/* convert cp_time counts to percentages */
236 	total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
237 
238 	/* get total -- systemwide main memory usage structure */
239 	size = sizeof(vmtotal);
240 	if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) {
241 		warn("sysctl failed");
242 		bzero(&vmtotal, sizeof(vmtotal));
243 	}
244 	/* convert memory stats to Kbytes */
245 	memory_stats[0] = -1;
246 	memory_stats[1] = pagetok(vmtotal.t_arm);
247 	memory_stats[2] = pagetok(vmtotal.t_rm);
248 	memory_stats[3] = -1;
249 	memory_stats[4] = pagetok(vmtotal.t_free);
250 	memory_stats[5] = -1;
251 #ifdef DOSWAP
252 	if (!swapmode(&memory_stats[6], &memory_stats[7])) {
253 		memory_stats[6] = 0;
254 		memory_stats[7] = 0;
255 	}
256 #endif
257 
258 	/* set arrays and strings */
259 	si->cpustates = cpu_states;
260 	si->memory = memory_stats;
261 	si->last_pid = -1;
262 }
263 
264 static struct handle handle;
265 
266 struct kinfo_proc *
267 getprocs(op, arg, cnt)
268 	int op, arg;
269 	int *cnt;
270 {
271 	size_t size = sizeof(int);
272 	int mib[4] = {CTL_KERN, KERN_PROC, op, arg};
273 	int smib[2] = {CTL_KERN, KERN_NPROCS};
274 	static struct kinfo_proc *procbase;
275 	int st;
276 
277 	st = sysctl(smib, 2, cnt, &size, NULL, 0);
278 	if (st == -1) {
279 		/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
280 		return (0);
281 	}
282 	if (procbase)
283 		free(procbase);
284 	size = (6 * (*cnt) * sizeof(struct kinfo_proc)) / 5;
285 	procbase = (struct kinfo_proc *)malloc(size);
286 	if (procbase == NULL)
287 		return (0);
288 	st = sysctl(mib, 4, procbase, &size, NULL, 0);
289 	if (st == -1) {
290 		/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
291 		return (0);
292 	}
293 	if (size % sizeof(struct kinfo_proc) != 0) {
294 		/* _kvm_err(kd, kd->program,
295 		    "proc size mismatch (%d total, %d chunks)",
296 		    size, sizeof(struct kinfo_proc)); */
297 		return (0);
298 	}
299 	return (procbase);
300 }
301 
302 caddr_t
303 get_process_info(si, sel, compare)
304 	struct system_info *si;
305 	struct process_select *sel;
306 	int (*compare) __P((const void *, const void *));
307 
308 {
309 	int show_idle, show_system, show_uid, show_command;
310 	int total_procs, active_procs, i;
311 	struct kinfo_proc **prefp, *pp;
312 
313 	if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) {
314 		/* warnx("%s", kvm_geterr(kd)); */
315 		quit(23);
316 	}
317 	if (nproc > onproc)
318 		pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
319 		    * (onproc = nproc));
320 	if (pref == NULL) {
321 		warnx("Out of memory.");
322 		quit(23);
323 	}
324 	/* get a pointer to the states summary array */
325 	si->procstates = process_states;
326 
327 	/* set up flags which define what we are going to select */
328 	show_idle = sel->idle;
329 	show_system = sel->system;
330 	show_uid = sel->uid != -1;
331 	show_command = sel->command != NULL;
332 
333 	/* count up process states and get pointers to interesting procs */
334 	total_procs = 0;
335 	active_procs = 0;
336 	memset((char *) process_states, 0, sizeof(process_states));
337 	prefp = pref;
338 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
339 		/*
340 		 *  Place pointers to each valid proc structure in pref[].
341 		 *  Process slots that are actually in use have a non-zero
342 		 *  status field.  Processes with SSYS set are system
343 		 *  processes---these get ignored unless show_sysprocs is set.
344 		 */
345 		if (PP(pp, p_stat) != 0 &&
346 		    (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) {
347 			total_procs++;
348 			process_states[(unsigned char) PP(pp, p_stat)]++;
349 			if ((PP(pp, p_stat) != SZOMB) &&
350 			    (show_idle || (PP(pp, p_pctcpu) != 0) ||
351 				(PP(pp, p_stat) == SRUN)) &&
352 			    (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t) sel->uid)) {
353 				*prefp++ = pp;
354 				active_procs++;
355 			}
356 		}
357 	}
358 
359 	/* if requested, sort the "interesting" processes */
360 	if (compare != NULL) {
361 		qsort((char *) pref, active_procs, sizeof(struct kinfo_proc *), compare);
362 	}
363 	/* remember active and total counts */
364 	si->p_total = total_procs;
365 	si->p_active = pref_len = active_procs;
366 
367 	/* pass back a handle */
368 	handle.next_proc = pref;
369 	handle.remaining = active_procs;
370 	return ((caddr_t) & handle);
371 }
372 
373 char    fmt[MAX_COLS];		/* static area where result is built */
374 
375 char *
376 format_next_process(handle, get_userid)
377 	caddr_t handle;
378 	char *(*get_userid)();
379 
380 {
381 	char waddr[sizeof(void *) * 2 + 3];	/* Hexify void pointer */
382 	struct kinfo_proc *pp;
383 	struct handle *hp;
384 	char *p_wait;
385 	int cputime;
386 	double pct;
387 
388 	/* find and remember the next proc structure */
389 	hp = (struct handle *) handle;
390 	pp = *(hp->next_proc++);
391 	hp->remaining--;
392 
393 	/* get the process's user struct and set cputime */
394 	if ((PP(pp, p_flag) & P_INMEM) == 0) {
395 		/*
396 		 * Print swapped processes as <pname>
397 		 */
398 		char   *comm = PP(pp, p_comm);
399 #define COMSIZ sizeof(PP(pp, p_comm))
400 		char    buf[COMSIZ];
401 		(void) strncpy(buf, comm, COMSIZ);
402 		comm[0] = '<';
403 		(void) strncpy(&comm[1], buf, COMSIZ - 2);
404 		comm[COMSIZ - 2] = '\0';
405 		(void) strncat(comm, ">", COMSIZ - 1);
406 		comm[COMSIZ - 1] = '\0';
407 	}
408 	cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz;
409 
410 	/* calculate the base for cpu percentages */
411 	pct = pctdouble(PP(pp, p_pctcpu));
412 
413 	if (PP(pp, p_wchan))
414 		if (PP(pp, p_wmesg))
415 			p_wait = EP(pp, e_wmesg);
416 		else {
417 			snprintf(waddr, sizeof(waddr), "%lx",
418 			    (unsigned long) (PP(pp, p_wchan)) & ~KERNBASE);
419 			p_wait = waddr;
420 		}
421 	else
422 		p_wait = "-";
423 
424 	/* format this entry */
425 	snprintf(fmt, MAX_COLS,
426 	    Proc_format,
427 	    PP(pp, p_pid),
428 	    (*get_userid) (EP(pp, e_pcred.p_ruid)),
429 	    PP(pp, p_priority) - PZERO,
430 	    PP(pp, p_nice) - NZERO,
431 	    format_k(pagetok(PROCSIZE(pp))),
432 	    format_k(pagetok(VP(pp, vm_rssize))),
433 	    (PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > MAXSLP)
434 	    ? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)],
435 	    p_wait,
436 	    format_time(cputime),
437 	    100.0 * pct,
438 	    printable(PP(pp, p_comm)));
439 
440 	/* return the result */
441 	return (fmt);
442 }
443 
444 /* comparison routine for qsort */
445 static unsigned char sorted_state[] =
446 {
447 	0,			/* not used		 */
448 	4,			/* start		 */
449 	5,			/* run			 */
450 	2,			/* sleep		 */
451 	3,			/* stop			 */
452 	1			/* zombie		 */
453 };
454 #ifdef ORDER
455 
456 /*
457  *  proc_compares - comparison functions for "qsort"
458  */
459 
460 /*
461  * First, the possible comparison keys.  These are defined in such a way
462  * that they can be merely listed in the source code to define the actual
463  * desired ordering.
464  */
465 
466 
467 #define ORDERKEY_PCTCPU \
468 	if (lresult = (pctcpu)PP(p2, p_pctcpu) - (pctcpu)PP(p1, p_pctcpu), \
469 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
470 #define ORDERKEY_CPUTIME \
471 	if ((result = PP(p2, p_rtime.tv_sec) - PP(p1, p_rtime.tv_sec)) == 0) \
472 		if ((result = PP(p2, p_rtime.tv_usec) - \
473 		     PP(p1, p_rtime.tv_usec)) == 0)
474 #define ORDERKEY_STATE \
475 	if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - \
476 	    sorted_state[(unsigned char) PP(p1, p_stat)])  == 0)
477 #define ORDERKEY_PRIO \
478 	if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
479 #define ORDERKEY_RSSIZE \
480 	if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
481 #define ORDERKEY_MEM \
482 	if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
483 
484 
485 /* compare_cpu - the comparison function for sorting by cpu percentage */
486 int
487 compare_cpu(v1, v2)
488 	const void *v1, *v2;
489 {
490 	struct proc **pp1 = (struct proc **) v1;
491 	struct proc **pp2 = (struct proc **) v2;
492 	struct kinfo_proc *p1;
493 	struct kinfo_proc *p2;
494 	int result;
495 	pctcpu lresult;
496 
497 	/* remove one level of indirection */
498 	p1 = *(struct kinfo_proc **) pp1;
499 	p2 = *(struct kinfo_proc **) pp2;
500 
501 	ORDERKEY_PCTCPU
502 	    ORDERKEY_CPUTIME
503 	    ORDERKEY_STATE
504 	    ORDERKEY_PRIO
505 	    ORDERKEY_RSSIZE
506 	    ORDERKEY_MEM
507 	    ;
508 	return (result);
509 }
510 
511 /* compare_size - the comparison function for sorting by total memory usage */
512 int
513 compare_size(v1, v2)
514 	const void *v1, *v2;
515 {
516 	struct proc **pp1 = (struct proc **) v1;
517 	struct proc **pp2 = (struct proc **) v2;
518 	struct kinfo_proc *p1;
519 	struct kinfo_proc *p2;
520 	int result;
521 	pctcpu lresult;
522 
523 	/* remove one level of indirection */
524 	p1 = *(struct kinfo_proc **) pp1;
525 	p2 = *(struct kinfo_proc **) pp2;
526 
527 	ORDERKEY_MEM
528 	    ORDERKEY_RSSIZE
529 	    ORDERKEY_PCTCPU
530 	    ORDERKEY_CPUTIME
531 	    ORDERKEY_STATE
532 	    ORDERKEY_PRIO
533 	    ;
534 	return (result);
535 }
536 
537 /* compare_res - the comparison function for sorting by resident set size */
538 int
539 compare_res(v1, v2)
540 	const void *v1, *v2;
541 {
542 	struct proc **pp1 = (struct proc **) v1;
543 	struct proc **pp2 = (struct proc **) v2;
544 	struct kinfo_proc *p1;
545 	struct kinfo_proc *p2;
546 	int result;
547 	pctcpu lresult;
548 
549 	/* remove one level of indirection */
550 	p1 = *(struct kinfo_proc **) pp1;
551 	p2 = *(struct kinfo_proc **) pp2;
552 
553 	ORDERKEY_RSSIZE
554 	    ORDERKEY_MEM
555 	    ORDERKEY_PCTCPU
556 	    ORDERKEY_CPUTIME
557 	    ORDERKEY_STATE
558 	    ORDERKEY_PRIO
559 	    ;
560 	return (result);
561 }
562 
563 /* compare_time - the comparison function for sorting by CPU time */
564 int
565 compare_time(v1, v2)
566 	const void *v1, *v2;
567 {
568 	struct proc **pp1 = (struct proc **) v1;
569 	struct proc **pp2 = (struct proc **) v2;
570 	struct kinfo_proc *p1;
571 	struct kinfo_proc *p2;
572 	int result;
573 	pctcpu lresult;
574 
575 	/* remove one level of indirection */
576 	p1 = *(struct kinfo_proc **) pp1;
577 	p2 = *(struct kinfo_proc **) pp2;
578 
579 	ORDERKEY_CPUTIME
580 	    ORDERKEY_PCTCPU
581 	    ORDERKEY_STATE
582 	    ORDERKEY_PRIO
583 	    ORDERKEY_MEM
584 	    ORDERKEY_RSSIZE
585 	    ;
586 	return (result);
587 }
588 
589 /* compare_prio - the comparison function for sorting by CPU time */
590 int
591 compare_prio(v1, v2)
592 	const void *v1, *v2;
593 {
594 	struct proc **pp1 = (struct proc **) v1;
595 	struct proc **pp2 = (struct proc **) v2;
596 	struct kinfo_proc *p1;
597 	struct kinfo_proc *p2;
598 	int result;
599 	pctcpu lresult;
600 
601 	/* remove one level of indirection */
602 	p1 = *(struct kinfo_proc **) pp1;
603 	p2 = *(struct kinfo_proc **) pp2;
604 
605 	ORDERKEY_PRIO
606 	    ORDERKEY_PCTCPU
607 	    ORDERKEY_CPUTIME
608 	    ORDERKEY_STATE
609 	    ORDERKEY_RSSIZE
610 	    ORDERKEY_MEM
611 	    ;
612 	return (result);
613 }
614 
615 int     (*proc_compares[]) () = {
616 	compare_cpu,
617 	compare_size,
618 	compare_res,
619 	compare_time,
620 	compare_prio,
621 	NULL
622 };
623 #else
624 /*
625  *  proc_compare - comparison function for "qsort"
626  *	Compares the resource consumption of two processes using five
627  *  	distinct keys.  The keys (in descending order of importance) are:
628  *  	percent cpu, cpu ticks, state, resident set size, total virtual
629  *  	memory usage.  The process states are ordered as follows (from least
630  *  	to most important):  zombie, sleep, stop, start, run.  The array
631  *  	declaration below maps a process state index into a number that
632  *  	reflects this ordering.
633  */
634 int
635 proc_compare(v1, v2)
636 	const void *v1, *v2;
637 {
638 	struct proc **pp1 = (struct proc **) v1;
639 	struct proc **pp2 = (struct proc **) v2;
640 	struct kinfo_proc *p1;
641 	struct kinfo_proc *p2;
642 	int result;
643 	pctcpu lresult;
644 
645 	/* remove one level of indirection */
646 	p1 = *(struct kinfo_proc **) pp1;
647 	p2 = *(struct kinfo_proc **) pp2;
648 
649 	/* compare percent cpu (pctcpu) */
650 	if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) {
651 		/* use CPU usage to break the tie */
652 		if ((result = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec) == 0) {
653 			/* use process state to break the tie */
654 			if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] -
655 				sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) {
656 				/* use priority to break the tie */
657 				if ((result = PP(p2, p_priority) -
658 				    PP(p1, p_priority)) == 0) {
659 					/* use resident set size (rssize) to
660 					 * break the tie */
661 					if ((result = VP(p2, vm_rssize) -
662 					    VP(p1, vm_rssize)) == 0) {
663 						/* use total memory to break
664 						 * the tie */
665 						result = PROCSIZE(p2) - PROCSIZE(p1);
666 					}
667 				}
668 			}
669 		}
670 	} else {
671 		result = lresult < 0 ? -1 : 1;
672 	}
673 	return (result);
674 }
675 #endif
676 
677 /*
678  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
679  *		the process does not exist.
680  *		It is EXTREMLY IMPORTANT that this function work correctly.
681  *		If top runs setuid root (as in SVR4), then this function
682  *		is the only thing that stands in the way of a serious
683  *		security problem.  It validates requests for the "kill"
684  *		and "renice" commands.
685  */
686 int
687 proc_owner(pid)
688 	pid_t   pid;
689 {
690 	struct kinfo_proc **prefp, *pp;
691 	int cnt;
692 
693 	prefp = pref;
694 	cnt = pref_len;
695 	while (--cnt >= 0) {
696 		pp = *prefp++;
697 		if (PP(pp, p_pid) == pid) {
698 			return ((int) EP(pp, e_pcred.p_ruid));
699 		}
700 	}
701 	return (-1);
702 }
703 #ifdef DOSWAP
704 /*
705  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
706  * to be based on the new swapctl(2) system call.
707  */
708 static int
709 swapmode(used, total)
710 	int    *used;
711 	int    *total;
712 {
713 	int     nswap, rnswap, i;
714 	struct swapent *swdev;
715 
716 	nswap = swapctl(SWAP_NSWAP, 0, 0);
717 	if (nswap == 0)
718 		return 0;
719 
720 	swdev = malloc(nswap * sizeof(*swdev));
721 	if (swdev == NULL)
722 		return 0;
723 
724 	rnswap = swapctl(SWAP_STATS, swdev, nswap);
725 	if (rnswap == -1)
726 		return 0;
727 
728 	/* if rnswap != nswap, then what? */
729 
730 	/* Total things up */
731 	*total = *used = 0;
732 	for (i = 0; i < nswap; i++) {
733 		if (swdev[i].se_flags & SWF_ENABLE) {
734 			*used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
735 			*total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
736 		}
737 	}
738 
739 	free(swdev);
740 	return 1;
741 }
742 #endif
743