Annotation of src/usr.bin/top/machine.c, Revision 1.25
1.25 ! deraadt 1: /* $OpenBSD: machine.c,v 1.24 2001/06/03 06:46:47 angelos Exp $ */
1.1 downsj 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: *
1.11 kstailey 15: * CFLAGS: -DHAVE_GETOPT -DORDER
1.1 downsj 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>
1.11 kstailey 20: * Patch for -DORDER by Kenneth Stailey <kstailey@disclosure.com>
1.15 weingart 21: * Patch for new swapctl(2) by Tobias Weingartner <weingart@openbsd.org>
1.1 downsj 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>
1.3 downsj 32: #include <string.h>
1.6 millert 33: #include <limits.h>
34: #include <err.h>
1.1 downsj 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
1.15 weingart 46: #include <sys/swap.h>
1.1 downsj 47: #include <err.h>
48: #endif
49:
50: static int swapmode __P((int *, int *));
51:
52: #include "top.h"
1.3 downsj 53: #include "display.h"
1.1 downsj 54: #include "machine.h"
55: #include "utils.h"
56:
57: /* get_process_info passes back a handle. This is what it looks like: */
58:
1.20 deraadt 59: struct handle {
60: struct kinfo_proc **next_proc; /* points to next valid proc pointer */
61: int remaining; /* number of pointers remaining */
1.1 downsj 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[] =
1.20 deraadt 78: " PID X PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND";
1.1 downsj 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:
1.20 deraadt 90: char *state_abbrev[] = {
91: "", "start", "run\0\0\0", "sleep", "stop", "zomb",
1.1 downsj 92: };
93:
94:
1.20 deraadt 95: static int stathz;
1.1 downsj 96:
97: /* these are for calculating cpu state percentages */
1.13 niklas 98: static long cp_time[CPUSTATES];
99: static long cp_old[CPUSTATES];
100: static long cp_diff[CPUSTATES];
1.1 downsj 101:
102: /* these are for detailing the process states */
1.20 deraadt 103: int process_states[7];
104: char *procstatenames[] = {
105: "", " starting, ", " running, ", " idle, ", " stopped, ", " zombie, ",
106: NULL
1.1 downsj 107: };
108:
109: /* these are for detailing the cpu states */
1.20 deraadt 110: int cpu_states[CPUSTATES];
111: char *cpustatenames[] = {
112: "user", "nice", "system", "interrupt", "idle", NULL
1.1 downsj 113: };
114:
115: /* these are for detailing the memory statistics */
1.20 deraadt 116: int memory_stats[8];
117: char *memorynames[] = {
118: "Real: ", "K/", "K act/tot ", "Free: ", "K ",
1.1 downsj 119: #ifdef DOSWAP
1.20 deraadt 120: "Swap: ", "K/", "K used/tot",
1.1 downsj 121: #endif
1.20 deraadt 122: NULL
1.1 downsj 123: };
124:
1.11 kstailey 125: #ifdef ORDER
126: /* these are names given to allowed sorting orders -- first is default */
1.20 deraadt 127: char *ordernames[] = {"cpu", "size", "res", "time", "pri", NULL};
1.11 kstailey 128: #endif
129:
1.1 downsj 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
1.18 deraadt 144: getstathz()
145: {
146: struct clockinfo cinf;
1.20 deraadt 147: size_t size = sizeof(cinf);
148: int mib[2];
1.18 deraadt 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
1.1 downsj 158: machine_init(statics)
1.20 deraadt 159: struct statics *statics;
1.1 downsj 160: {
1.25 ! deraadt 161: int pagesize;
1.20 deraadt 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;
1.11 kstailey 188: #ifdef ORDER
1.20 deraadt 189: statics->order_names = ordernames;
1.11 kstailey 190: #endif
1.20 deraadt 191: return (0);
1.1 downsj 192: }
193:
1.20 deraadt 194: char *
195: format_header(uname_field)
196: char *uname_field;
1.1 downsj 197: {
1.20 deraadt 198: char *ptr;
1.1 downsj 199:
1.20 deraadt 200: ptr = header + UNAME_START;
201: while (*uname_field != '\0') {
202: *ptr++ = *uname_field++;
203: }
204: return (header);
1.1 downsj 205: }
206:
207: void
208: get_system_info(si)
1.20 deraadt 209: struct system_info *si;
1.1 downsj 210: {
1.20 deraadt 211: static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
212: static int vmtotal_mib[] = {CTL_VM, VM_METER};
1.21 deraadt 213: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
1.1 downsj 214: struct loadavg sysload;
1.20 deraadt 215: struct vmtotal vmtotal;
216: double *infoloadp;
217: int total, i;
218: size_t size;
219:
1.21 deraadt 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: }
1.20 deraadt 225:
226: size = sizeof(sysload);
227: if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0) {
228: warn("sysctl failed");
1.22 deraadt 229: total = 0;
1.1 downsj 230: }
231: infoloadp = si->load_avg;
232: for (i = 0; i < 3; i++)
1.20 deraadt 233: *infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
1.1 downsj 234:
1.20 deraadt 235: /* convert cp_time counts to percentages */
236: total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
1.1 downsj 237:
238: /* get total -- systemwide main memory usage structure */
1.20 deraadt 239: size = sizeof(vmtotal);
240: if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) {
241: warn("sysctl failed");
242: bzero(&vmtotal, sizeof(vmtotal));
1.1 downsj 243: }
244: /* convert memory stats to Kbytes */
245: memory_stats[0] = -1;
1.20 deraadt 246: memory_stats[1] = pagetok(vmtotal.t_arm);
247: memory_stats[2] = pagetok(vmtotal.t_rm);
1.1 downsj 248: memory_stats[3] = -1;
1.20 deraadt 249: memory_stats[4] = pagetok(vmtotal.t_free);
1.1 downsj 250: memory_stats[5] = -1;
251: #ifdef DOSWAP
252: if (!swapmode(&memory_stats[6], &memory_stats[7])) {
1.20 deraadt 253: memory_stats[6] = 0;
254: memory_stats[7] = 0;
1.1 downsj 255: }
256: #endif
257:
1.20 deraadt 258: /* set arrays and strings */
259: si->cpustates = cpu_states;
260: si->memory = memory_stats;
261: si->last_pid = -1;
1.1 downsj 262: }
263:
264: static struct handle handle;
265:
1.22 deraadt 266: struct kinfo_proc *
267: getprocs(op, arg, cnt)
268: int op, arg;
269: int *cnt;
270: {
1.24 angelos 271: size_t size = sizeof(int);
1.22 deraadt 272: int mib[4] = {CTL_KERN, KERN_PROC, op, arg};
1.24 angelos 273: int smib[2] = {CTL_KERN, KERN_NPROCS};
1.23 deraadt 274: static struct kinfo_proc *procbase;
1.24 angelos 275: int st;
1.22 deraadt 276:
1.24 angelos 277: st = sysctl(smib, 2, cnt, &size, NULL, 0);
1.22 deraadt 278: if (st == -1) {
279: /* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
280: return (0);
281: }
1.23 deraadt 282: if (procbase)
283: free(procbase);
1.24 angelos 284: size = (6 * (*cnt) * sizeof(struct kinfo_proc)) / 5;
1.22 deraadt 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:
1.20 deraadt 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:
1.22 deraadt 313: if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) {
314: /* warnx("%s", kvm_geterr(kd)); */
1.20 deraadt 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;
1.1 downsj 326:
1.20 deraadt 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);
1.1 downsj 399: #define COMSIZ sizeof(PP(pp, p_comm))
1.20 deraadt 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,
1.1 downsj 426: Proc_format,
427: PP(pp, p_pid),
1.20 deraadt 428: (*get_userid) (EP(pp, e_pcred.p_ruid)),
1.1 downsj 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))),
1.2 kstailey 433: (PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > MAXSLP)
1.20 deraadt 434: ? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)],
1.1 downsj 435: p_wait,
436: format_time(cputime),
437: 100.0 * pct,
438: printable(PP(pp, p_comm)));
439:
1.20 deraadt 440: /* return the result */
441: return (fmt);
1.1 downsj 442: }
443:
444: /* comparison routine for qsort */
1.11 kstailey 445: static unsigned char sorted_state[] =
446: {
1.20 deraadt 447: 0, /* not used */
448: 4, /* start */
449: 5, /* run */
450: 2, /* sleep */
451: 3, /* stop */
452: 1 /* zombie */
1.11 kstailey 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 \
1.12 niklas 468: if (lresult = (pctcpu)PP(p2, p_pctcpu) - (pctcpu)PP(p1, p_pctcpu), \
1.22 deraadt 469: (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
1.11 kstailey 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)] - \
1.22 deraadt 476: sorted_state[(unsigned char) PP(p1, p_stat)]) == 0)
1.11 kstailey 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:
1.20 deraadt 484:
1.11 kstailey 485: /* compare_cpu - the comparison function for sorting by cpu percentage */
486: int
487: compare_cpu(v1, v2)
1.20 deraadt 488: const void *v1, *v2;
1.11 kstailey 489: {
1.20 deraadt 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);
1.11 kstailey 509: }
510:
511: /* compare_size - the comparison function for sorting by total memory usage */
512: int
513: compare_size(v1, v2)
1.20 deraadt 514: const void *v1, *v2;
1.11 kstailey 515: {
1.20 deraadt 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);
1.11 kstailey 535: }
536:
537: /* compare_res - the comparison function for sorting by resident set size */
538: int
539: compare_res(v1, v2)
1.20 deraadt 540: const void *v1, *v2;
1.11 kstailey 541: {
1.20 deraadt 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);
1.11 kstailey 561: }
562:
563: /* compare_time - the comparison function for sorting by CPU time */
564: int
565: compare_time(v1, v2)
1.20 deraadt 566: const void *v1, *v2;
1.11 kstailey 567: {
1.20 deraadt 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);
1.11 kstailey 587: }
588:
589: /* compare_prio - the comparison function for sorting by CPU time */
590: int
591: compare_prio(v1, v2)
1.20 deraadt 592: const void *v1, *v2;
1.11 kstailey 593: {
1.20 deraadt 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
1.11 kstailey 622: };
1.20 deraadt 623: #else
1.1 downsj 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
1.3 downsj 635: proc_compare(v1, v2)
1.20 deraadt 636: const void *v1, *v2;
1.1 downsj 637: {
1.20 deraadt 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 */
1.22 deraadt 657: if ((result = PP(p2, p_priority) -
658: PP(p1, p_priority)) == 0) {
1.20 deraadt 659: /* use resident set size (rssize) to
660: * break the tie */
1.22 deraadt 661: if ((result = VP(p2, vm_rssize) -
662: VP(p1, vm_rssize)) == 0) {
1.20 deraadt 663: /* use total memory to break
664: * the tie */
665: result = PROCSIZE(p2) - PROCSIZE(p1);
666: }
667: }
668: }
1.1 downsj 669: }
1.20 deraadt 670: } else {
671: result = lresult < 0 ? -1 : 1;
1.1 downsj 672: }
1.20 deraadt 673: return (result);
1.1 downsj 674: }
1.11 kstailey 675: #endif
1.1 downsj 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: */
1.20 deraadt 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: }
1.1 downsj 700: }
1.20 deraadt 701: return (-1);
1.1 downsj 702: }
703: #ifdef DOSWAP
704: /*
1.17 todd 705: * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
1.15 weingart 706: * to be based on the new swapctl(2) system call.
1.1 downsj 707: */
708: static int
709: swapmode(used, total)
1.20 deraadt 710: int *used;
711: int *total;
1.1 downsj 712: {
1.20 deraadt 713: int nswap, rnswap, i;
1.15 weingart 714: struct swapent *swdev;
1.1 downsj 715:
1.15 weingart 716: nswap = swapctl(SWAP_NSWAP, 0, 0);
1.20 deraadt 717: if (nswap == 0)
1.15 weingart 718: return 0;
719:
720: swdev = malloc(nswap * sizeof(*swdev));
1.20 deraadt 721: if (swdev == NULL)
1.15 weingart 722: return 0;
723:
724: rnswap = swapctl(SWAP_STATS, swdev, nswap);
1.20 deraadt 725: if (rnswap == -1)
1.15 weingart 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) {
1.20 deraadt 734: *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
735: *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
1.1 downsj 736: }
737: }
738:
1.20 deraadt 739: free(swdev);
1.1 downsj 740: return 1;
741: }
742: #endif