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