xref: /openbsd/usr.bin/top/machine.c (revision 78b63d65)
1 /*	$OpenBSD: machine.c,v 1.26 2001/12/05 02:29:19 art 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 maxslp;
144 
145 int
146 getstathz()
147 {
148 	struct clockinfo cinf;
149 	size_t  size = sizeof(cinf);
150 	int     mib[2];
151 
152 	mib[0] = CTL_KERN;
153 	mib[1] = KERN_CLOCKRATE;
154 	if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1)
155 		return (-1);
156 	return (cinf.stathz);
157 }
158 
159 int
160 machine_init(statics)
161 	struct statics *statics;
162 {
163 	int pagesize;
164 
165 	stathz = getstathz();
166 	if (stathz == -1)
167 		return (-1);
168 
169 	pbase = NULL;
170 	pref = NULL;
171 	onproc = -1;
172 	nproc = 0;
173 
174 	/* get the page size with "getpagesize" and calculate pageshift from
175 	 * it */
176 	pagesize = getpagesize();
177 	pageshift = 0;
178 	while (pagesize > 1) {
179 		pageshift++;
180 		pagesize >>= 1;
181 	}
182 
183 	/* we only need the amount of log(2)1024 for our conversion */
184 	pageshift -= LOG1024;
185 
186 	/* fill in the statics information */
187 	statics->procstate_names = procstatenames;
188 	statics->cpustate_names = cpustatenames;
189 	statics->memory_names = memorynames;
190 #ifdef ORDER
191 	statics->order_names = ordernames;
192 #endif
193 	return (0);
194 }
195 
196 char *
197 format_header(uname_field)
198 	char   *uname_field;
199 {
200 	char *ptr;
201 
202 	ptr = header + UNAME_START;
203 	while (*uname_field != '\0') {
204 		*ptr++ = *uname_field++;
205 	}
206 	return (header);
207 }
208 
209 void
210 get_system_info(si)
211 	struct system_info *si;
212 {
213 	static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
214 	static int vmtotal_mib[] = {CTL_VM, VM_METER};
215 	static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
216 	struct loadavg sysload;
217 	struct vmtotal vmtotal;
218 	double *infoloadp;
219 	int total, i;
220 	size_t  size;
221 
222 	size = sizeof(cp_time);
223 	if (sysctl(cp_time_mib, 2, &cp_time, &size, NULL, 0) < 0) {
224 		warn("sysctl kern.cp_time failed");
225 		total = 0;
226 	}
227 
228 	size = sizeof(sysload);
229 	if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0) {
230 		warn("sysctl failed");
231 		total = 0;
232 	}
233 	infoloadp = si->load_avg;
234 	for (i = 0; i < 3; i++)
235 		*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
236 
237 	/* convert cp_time counts to percentages */
238 	total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
239 
240 	/* get total -- systemwide main memory usage structure */
241 	size = sizeof(vmtotal);
242 	if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) {
243 		warn("sysctl failed");
244 		bzero(&vmtotal, sizeof(vmtotal));
245 	}
246 	/* convert memory stats to Kbytes */
247 	memory_stats[0] = -1;
248 	memory_stats[1] = pagetok(vmtotal.t_arm);
249 	memory_stats[2] = pagetok(vmtotal.t_rm);
250 	memory_stats[3] = -1;
251 	memory_stats[4] = pagetok(vmtotal.t_free);
252 	memory_stats[5] = -1;
253 #ifdef DOSWAP
254 	if (!swapmode(&memory_stats[6], &memory_stats[7])) {
255 		memory_stats[6] = 0;
256 		memory_stats[7] = 0;
257 	}
258 #endif
259 
260 	/* set arrays and strings */
261 	si->cpustates = cpu_states;
262 	si->memory = memory_stats;
263 	si->last_pid = -1;
264 }
265 
266 static struct handle handle;
267 
268 struct kinfo_proc *
269 getprocs(op, arg, cnt)
270 	int op, arg;
271 	int *cnt;
272 {
273 	size_t size = sizeof(int);
274 	int mib[4] = {CTL_KERN, KERN_PROC, op, arg};
275 	int smib[2] = {CTL_KERN, KERN_NPROCS};
276 	static int maxslp_mib[] = {CTL_VM, VM_MAXSLP};
277 	static struct kinfo_proc *procbase;
278 	int st;
279 
280 	size = sizeof(maxslp);
281 	if (sysctl(maxslp_mib, 2, &maxslp, &size, NULL, 0) < 0) {
282 		warn("sysctl vm.maxslp failed");
283 		return (0);
284 	}
285 
286 	st = sysctl(smib, 2, cnt, &size, NULL, 0);
287 	if (st == -1) {
288 		/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
289 		return (0);
290 	}
291 	if (procbase)
292 		free(procbase);
293 	size = (6 * (*cnt) * sizeof(struct kinfo_proc)) / 5;
294 	procbase = (struct kinfo_proc *)malloc(size);
295 	if (procbase == NULL)
296 		return (0);
297 	st = sysctl(mib, 4, procbase, &size, NULL, 0);
298 	if (st == -1) {
299 		/* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
300 		return (0);
301 	}
302 	if (size % sizeof(struct kinfo_proc) != 0) {
303 		/* _kvm_err(kd, kd->program,
304 		    "proc size mismatch (%d total, %d chunks)",
305 		    size, sizeof(struct kinfo_proc)); */
306 		return (0);
307 	}
308 	return (procbase);
309 }
310 
311 caddr_t
312 get_process_info(si, sel, compare)
313 	struct system_info *si;
314 	struct process_select *sel;
315 	int (*compare) __P((const void *, const void *));
316 
317 {
318 	int show_idle, show_system, show_uid, show_command;
319 	int total_procs, active_procs, i;
320 	struct kinfo_proc **prefp, *pp;
321 
322 	if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) {
323 		/* warnx("%s", kvm_geterr(kd)); */
324 		quit(23);
325 	}
326 	if (nproc > onproc)
327 		pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
328 		    * (onproc = nproc));
329 	if (pref == NULL) {
330 		warnx("Out of memory.");
331 		quit(23);
332 	}
333 	/* get a pointer to the states summary array */
334 	si->procstates = process_states;
335 
336 	/* set up flags which define what we are going to select */
337 	show_idle = sel->idle;
338 	show_system = sel->system;
339 	show_uid = sel->uid != -1;
340 	show_command = sel->command != NULL;
341 
342 	/* count up process states and get pointers to interesting procs */
343 	total_procs = 0;
344 	active_procs = 0;
345 	memset((char *) process_states, 0, sizeof(process_states));
346 	prefp = pref;
347 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
348 		/*
349 		 *  Place pointers to each valid proc structure in pref[].
350 		 *  Process slots that are actually in use have a non-zero
351 		 *  status field.  Processes with SSYS set are system
352 		 *  processes---these get ignored unless show_sysprocs is set.
353 		 */
354 		if (PP(pp, p_stat) != 0 &&
355 		    (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) {
356 			total_procs++;
357 			process_states[(unsigned char) PP(pp, p_stat)]++;
358 			if ((PP(pp, p_stat) != SZOMB) &&
359 			    (show_idle || (PP(pp, p_pctcpu) != 0) ||
360 				(PP(pp, p_stat) == SRUN)) &&
361 			    (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t) sel->uid)) {
362 				*prefp++ = pp;
363 				active_procs++;
364 			}
365 		}
366 	}
367 
368 	/* if requested, sort the "interesting" processes */
369 	if (compare != NULL) {
370 		qsort((char *) pref, active_procs, sizeof(struct kinfo_proc *), compare);
371 	}
372 	/* remember active and total counts */
373 	si->p_total = total_procs;
374 	si->p_active = pref_len = active_procs;
375 
376 	/* pass back a handle */
377 	handle.next_proc = pref;
378 	handle.remaining = active_procs;
379 	return ((caddr_t) & handle);
380 }
381 
382 char    fmt[MAX_COLS];		/* static area where result is built */
383 
384 char *
385 format_next_process(handle, get_userid)
386 	caddr_t handle;
387 	char *(*get_userid)();
388 
389 {
390 	char waddr[sizeof(void *) * 2 + 3];	/* Hexify void pointer */
391 	struct kinfo_proc *pp;
392 	struct handle *hp;
393 	char *p_wait;
394 	int cputime;
395 	double pct;
396 
397 	/* find and remember the next proc structure */
398 	hp = (struct handle *) handle;
399 	pp = *(hp->next_proc++);
400 	hp->remaining--;
401 
402 	/* get the process's user struct and set cputime */
403 	if ((PP(pp, p_flag) & P_INMEM) == 0) {
404 		/*
405 		 * Print swapped processes as <pname>
406 		 */
407 		char   *comm = PP(pp, p_comm);
408 #define COMSIZ sizeof(PP(pp, p_comm))
409 		char    buf[COMSIZ];
410 		(void) strncpy(buf, comm, COMSIZ);
411 		comm[0] = '<';
412 		(void) strncpy(&comm[1], buf, COMSIZ - 2);
413 		comm[COMSIZ - 2] = '\0';
414 		(void) strncat(comm, ">", COMSIZ - 1);
415 		comm[COMSIZ - 1] = '\0';
416 	}
417 	cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz;
418 
419 	/* calculate the base for cpu percentages */
420 	pct = pctdouble(PP(pp, p_pctcpu));
421 
422 	if (PP(pp, p_wchan))
423 		if (PP(pp, p_wmesg))
424 			p_wait = EP(pp, e_wmesg);
425 		else {
426 			snprintf(waddr, sizeof(waddr), "%lx",
427 			    (unsigned long) (PP(pp, p_wchan)) & ~KERNBASE);
428 			p_wait = waddr;
429 		}
430 	else
431 		p_wait = "-";
432 
433 	/* format this entry */
434 	snprintf(fmt, MAX_COLS,
435 	    Proc_format,
436 	    PP(pp, p_pid),
437 	    (*get_userid) (EP(pp, e_pcred.p_ruid)),
438 	    PP(pp, p_priority) - PZERO,
439 	    PP(pp, p_nice) - NZERO,
440 	    format_k(pagetok(PROCSIZE(pp))),
441 	    format_k(pagetok(VP(pp, vm_rssize))),
442 	    (PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > maxslp)
443 	    ? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)],
444 	    p_wait,
445 	    format_time(cputime),
446 	    100.0 * pct,
447 	    printable(PP(pp, p_comm)));
448 
449 	/* return the result */
450 	return (fmt);
451 }
452 
453 /* comparison routine for qsort */
454 static unsigned char sorted_state[] =
455 {
456 	0,			/* not used		 */
457 	4,			/* start		 */
458 	5,			/* run			 */
459 	2,			/* sleep		 */
460 	3,			/* stop			 */
461 	1			/* zombie		 */
462 };
463 #ifdef ORDER
464 
465 /*
466  *  proc_compares - comparison functions for "qsort"
467  */
468 
469 /*
470  * First, the possible comparison keys.  These are defined in such a way
471  * that they can be merely listed in the source code to define the actual
472  * desired ordering.
473  */
474 
475 
476 #define ORDERKEY_PCTCPU \
477 	if (lresult = (pctcpu)PP(p2, p_pctcpu) - (pctcpu)PP(p1, p_pctcpu), \
478 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
479 #define ORDERKEY_CPUTIME \
480 	if ((result = PP(p2, p_rtime.tv_sec) - PP(p1, p_rtime.tv_sec)) == 0) \
481 		if ((result = PP(p2, p_rtime.tv_usec) - \
482 		     PP(p1, p_rtime.tv_usec)) == 0)
483 #define ORDERKEY_STATE \
484 	if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - \
485 	    sorted_state[(unsigned char) PP(p1, p_stat)])  == 0)
486 #define ORDERKEY_PRIO \
487 	if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
488 #define ORDERKEY_RSSIZE \
489 	if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
490 #define ORDERKEY_MEM \
491 	if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
492 
493 
494 /* compare_cpu - the comparison function for sorting by cpu percentage */
495 int
496 compare_cpu(v1, v2)
497 	const void *v1, *v2;
498 {
499 	struct proc **pp1 = (struct proc **) v1;
500 	struct proc **pp2 = (struct proc **) v2;
501 	struct kinfo_proc *p1;
502 	struct kinfo_proc *p2;
503 	int result;
504 	pctcpu lresult;
505 
506 	/* remove one level of indirection */
507 	p1 = *(struct kinfo_proc **) pp1;
508 	p2 = *(struct kinfo_proc **) pp2;
509 
510 	ORDERKEY_PCTCPU
511 	    ORDERKEY_CPUTIME
512 	    ORDERKEY_STATE
513 	    ORDERKEY_PRIO
514 	    ORDERKEY_RSSIZE
515 	    ORDERKEY_MEM
516 	    ;
517 	return (result);
518 }
519 
520 /* compare_size - the comparison function for sorting by total memory usage */
521 int
522 compare_size(v1, v2)
523 	const void *v1, *v2;
524 {
525 	struct proc **pp1 = (struct proc **) v1;
526 	struct proc **pp2 = (struct proc **) v2;
527 	struct kinfo_proc *p1;
528 	struct kinfo_proc *p2;
529 	int result;
530 	pctcpu lresult;
531 
532 	/* remove one level of indirection */
533 	p1 = *(struct kinfo_proc **) pp1;
534 	p2 = *(struct kinfo_proc **) pp2;
535 
536 	ORDERKEY_MEM
537 	    ORDERKEY_RSSIZE
538 	    ORDERKEY_PCTCPU
539 	    ORDERKEY_CPUTIME
540 	    ORDERKEY_STATE
541 	    ORDERKEY_PRIO
542 	    ;
543 	return (result);
544 }
545 
546 /* compare_res - the comparison function for sorting by resident set size */
547 int
548 compare_res(v1, v2)
549 	const void *v1, *v2;
550 {
551 	struct proc **pp1 = (struct proc **) v1;
552 	struct proc **pp2 = (struct proc **) v2;
553 	struct kinfo_proc *p1;
554 	struct kinfo_proc *p2;
555 	int result;
556 	pctcpu lresult;
557 
558 	/* remove one level of indirection */
559 	p1 = *(struct kinfo_proc **) pp1;
560 	p2 = *(struct kinfo_proc **) pp2;
561 
562 	ORDERKEY_RSSIZE
563 	    ORDERKEY_MEM
564 	    ORDERKEY_PCTCPU
565 	    ORDERKEY_CPUTIME
566 	    ORDERKEY_STATE
567 	    ORDERKEY_PRIO
568 	    ;
569 	return (result);
570 }
571 
572 /* compare_time - the comparison function for sorting by CPU time */
573 int
574 compare_time(v1, v2)
575 	const void *v1, *v2;
576 {
577 	struct proc **pp1 = (struct proc **) v1;
578 	struct proc **pp2 = (struct proc **) v2;
579 	struct kinfo_proc *p1;
580 	struct kinfo_proc *p2;
581 	int result;
582 	pctcpu lresult;
583 
584 	/* remove one level of indirection */
585 	p1 = *(struct kinfo_proc **) pp1;
586 	p2 = *(struct kinfo_proc **) pp2;
587 
588 	ORDERKEY_CPUTIME
589 	    ORDERKEY_PCTCPU
590 	    ORDERKEY_STATE
591 	    ORDERKEY_PRIO
592 	    ORDERKEY_MEM
593 	    ORDERKEY_RSSIZE
594 	    ;
595 	return (result);
596 }
597 
598 /* compare_prio - the comparison function for sorting by CPU time */
599 int
600 compare_prio(v1, v2)
601 	const void *v1, *v2;
602 {
603 	struct proc **pp1 = (struct proc **) v1;
604 	struct proc **pp2 = (struct proc **) v2;
605 	struct kinfo_proc *p1;
606 	struct kinfo_proc *p2;
607 	int result;
608 	pctcpu lresult;
609 
610 	/* remove one level of indirection */
611 	p1 = *(struct kinfo_proc **) pp1;
612 	p2 = *(struct kinfo_proc **) pp2;
613 
614 	ORDERKEY_PRIO
615 	    ORDERKEY_PCTCPU
616 	    ORDERKEY_CPUTIME
617 	    ORDERKEY_STATE
618 	    ORDERKEY_RSSIZE
619 	    ORDERKEY_MEM
620 	    ;
621 	return (result);
622 }
623 
624 int     (*proc_compares[]) () = {
625 	compare_cpu,
626 	compare_size,
627 	compare_res,
628 	compare_time,
629 	compare_prio,
630 	NULL
631 };
632 #else
633 /*
634  *  proc_compare - comparison function for "qsort"
635  *	Compares the resource consumption of two processes using five
636  *  	distinct keys.  The keys (in descending order of importance) are:
637  *  	percent cpu, cpu ticks, state, resident set size, total virtual
638  *  	memory usage.  The process states are ordered as follows (from least
639  *  	to most important):  zombie, sleep, stop, start, run.  The array
640  *  	declaration below maps a process state index into a number that
641  *  	reflects this ordering.
642  */
643 int
644 proc_compare(v1, v2)
645 	const void *v1, *v2;
646 {
647 	struct proc **pp1 = (struct proc **) v1;
648 	struct proc **pp2 = (struct proc **) v2;
649 	struct kinfo_proc *p1;
650 	struct kinfo_proc *p2;
651 	int result;
652 	pctcpu lresult;
653 
654 	/* remove one level of indirection */
655 	p1 = *(struct kinfo_proc **) pp1;
656 	p2 = *(struct kinfo_proc **) pp2;
657 
658 	/* compare percent cpu (pctcpu) */
659 	if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) {
660 		/* use CPU usage to break the tie */
661 		if ((result = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec) == 0) {
662 			/* use process state to break the tie */
663 			if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] -
664 				sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) {
665 				/* use priority to break the tie */
666 				if ((result = PP(p2, p_priority) -
667 				    PP(p1, p_priority)) == 0) {
668 					/* use resident set size (rssize) to
669 					 * break the tie */
670 					if ((result = VP(p2, vm_rssize) -
671 					    VP(p1, vm_rssize)) == 0) {
672 						/* use total memory to break
673 						 * the tie */
674 						result = PROCSIZE(p2) - PROCSIZE(p1);
675 					}
676 				}
677 			}
678 		}
679 	} else {
680 		result = lresult < 0 ? -1 : 1;
681 	}
682 	return (result);
683 }
684 #endif
685 
686 /*
687  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
688  *		the process does not exist.
689  *		It is EXTREMLY IMPORTANT that this function work correctly.
690  *		If top runs setuid root (as in SVR4), then this function
691  *		is the only thing that stands in the way of a serious
692  *		security problem.  It validates requests for the "kill"
693  *		and "renice" commands.
694  */
695 int
696 proc_owner(pid)
697 	pid_t   pid;
698 {
699 	struct kinfo_proc **prefp, *pp;
700 	int cnt;
701 
702 	prefp = pref;
703 	cnt = pref_len;
704 	while (--cnt >= 0) {
705 		pp = *prefp++;
706 		if (PP(pp, p_pid) == pid) {
707 			return ((int) EP(pp, e_pcred.p_ruid));
708 		}
709 	}
710 	return (-1);
711 }
712 #ifdef DOSWAP
713 /*
714  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
715  * to be based on the new swapctl(2) system call.
716  */
717 static int
718 swapmode(used, total)
719 	int    *used;
720 	int    *total;
721 {
722 	int     nswap, rnswap, i;
723 	struct swapent *swdev;
724 
725 	nswap = swapctl(SWAP_NSWAP, 0, 0);
726 	if (nswap == 0)
727 		return 0;
728 
729 	swdev = malloc(nswap * sizeof(*swdev));
730 	if (swdev == NULL)
731 		return 0;
732 
733 	rnswap = swapctl(SWAP_STATS, swdev, nswap);
734 	if (rnswap == -1)
735 		return 0;
736 
737 	/* if rnswap != nswap, then what? */
738 
739 	/* Total things up */
740 	*total = *used = 0;
741 	for (i = 0; i < nswap; i++) {
742 		if (swdev[i].se_flags & SWF_ENABLE) {
743 			*used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
744 			*total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
745 		}
746 	}
747 
748 	free(swdev);
749 	return 1;
750 }
751 #endif
752