Annotation of src/usr.bin/top/machine.c, Revision 1.24
1.24 ! angelos 1: /* $OpenBSD: machine.c,v 1.23 2001/02/22 03:10:24 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: {
1.24 ! angelos 277: size_t size = sizeof(int);
1.22 deraadt 278: int mib[4] = {CTL_KERN, KERN_PROC, op, arg};
1.24 ! angelos 279: int smib[2] = {CTL_KERN, KERN_NPROCS};
1.23 deraadt 280: static struct kinfo_proc *procbase;
1.24 ! angelos 281: int st;
1.22 deraadt 282:
1.24 ! angelos 283: st = sysctl(smib, 2, cnt, &size, NULL, 0);
1.22 deraadt 284: if (st == -1) {
285: /* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
286: return (0);
287: }
1.23 deraadt 288: if (procbase)
289: free(procbase);
1.24 ! angelos 290: size = (6 * (*cnt) * sizeof(struct kinfo_proc)) / 5;
1.22 deraadt 291: procbase = (struct kinfo_proc *)malloc(size);
292: if (procbase == NULL)
293: return (0);
294: st = sysctl(mib, 4, procbase, &size, NULL, 0);
295: if (st == -1) {
296: /* _kvm_syserr(kd, kd->program, "kvm_getprocs"); */
297: return (0);
298: }
299: if (size % sizeof(struct kinfo_proc) != 0) {
300: /* _kvm_err(kd, kd->program,
301: "proc size mismatch (%d total, %d chunks)",
302: size, sizeof(struct kinfo_proc)); */
303: return (0);
304: }
305: return (procbase);
306: }
307:
1.20 deraadt 308: caddr_t
309: get_process_info(si, sel, compare)
310: struct system_info *si;
311: struct process_select *sel;
312: int (*compare) __P((const void *, const void *));
313:
314: {
315: int show_idle, show_system, show_uid, show_command;
316: int total_procs, active_procs, i;
317: struct kinfo_proc **prefp, *pp;
318:
1.22 deraadt 319: if ((pbase = getprocs(KERN_PROC_KTHREAD, 0, &nproc)) == NULL) {
320: /* warnx("%s", kvm_geterr(kd)); */
1.20 deraadt 321: quit(23);
322: }
323: if (nproc > onproc)
324: pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
325: * (onproc = nproc));
326: if (pref == NULL) {
327: warnx("Out of memory.");
328: quit(23);
329: }
330: /* get a pointer to the states summary array */
331: si->procstates = process_states;
1.1 downsj 332:
1.20 deraadt 333: /* set up flags which define what we are going to select */
334: show_idle = sel->idle;
335: show_system = sel->system;
336: show_uid = sel->uid != -1;
337: show_command = sel->command != NULL;
338:
339: /* count up process states and get pointers to interesting procs */
340: total_procs = 0;
341: active_procs = 0;
342: memset((char *) process_states, 0, sizeof(process_states));
343: prefp = pref;
344: for (pp = pbase, i = 0; i < nproc; pp++, i++) {
345: /*
346: * Place pointers to each valid proc structure in pref[].
347: * Process slots that are actually in use have a non-zero
348: * status field. Processes with SSYS set are system
349: * processes---these get ignored unless show_sysprocs is set.
350: */
351: if (PP(pp, p_stat) != 0 &&
352: (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0))) {
353: total_procs++;
354: process_states[(unsigned char) PP(pp, p_stat)]++;
355: if ((PP(pp, p_stat) != SZOMB) &&
356: (show_idle || (PP(pp, p_pctcpu) != 0) ||
357: (PP(pp, p_stat) == SRUN)) &&
358: (!show_uid || EP(pp, e_pcred.p_ruid) == (uid_t) sel->uid)) {
359: *prefp++ = pp;
360: active_procs++;
361: }
362: }
363: }
364:
365: /* if requested, sort the "interesting" processes */
366: if (compare != NULL) {
367: qsort((char *) pref, active_procs, sizeof(struct kinfo_proc *), compare);
368: }
369: /* remember active and total counts */
370: si->p_total = total_procs;
371: si->p_active = pref_len = active_procs;
372:
373: /* pass back a handle */
374: handle.next_proc = pref;
375: handle.remaining = active_procs;
376: return ((caddr_t) & handle);
377: }
378:
379: char fmt[MAX_COLS]; /* static area where result is built */
380:
381: char *
382: format_next_process(handle, get_userid)
383: caddr_t handle;
384: char *(*get_userid)();
385:
386: {
387: char waddr[sizeof(void *) * 2 + 3]; /* Hexify void pointer */
388: struct kinfo_proc *pp;
389: struct handle *hp;
390: char *p_wait;
391: int cputime;
392: double pct;
393:
394: /* find and remember the next proc structure */
395: hp = (struct handle *) handle;
396: pp = *(hp->next_proc++);
397: hp->remaining--;
398:
399: /* get the process's user struct and set cputime */
400: if ((PP(pp, p_flag) & P_INMEM) == 0) {
401: /*
402: * Print swapped processes as <pname>
403: */
404: char *comm = PP(pp, p_comm);
1.1 downsj 405: #define COMSIZ sizeof(PP(pp, p_comm))
1.20 deraadt 406: char buf[COMSIZ];
407: (void) strncpy(buf, comm, COMSIZ);
408: comm[0] = '<';
409: (void) strncpy(&comm[1], buf, COMSIZ - 2);
410: comm[COMSIZ - 2] = '\0';
411: (void) strncat(comm, ">", COMSIZ - 1);
412: comm[COMSIZ - 1] = '\0';
413: }
414: cputime = (PP(pp, p_uticks) + PP(pp, p_sticks) + PP(pp, p_iticks)) / stathz;
415:
416: /* calculate the base for cpu percentages */
417: pct = pctdouble(PP(pp, p_pctcpu));
418:
419: if (PP(pp, p_wchan))
420: if (PP(pp, p_wmesg))
421: p_wait = EP(pp, e_wmesg);
422: else {
423: snprintf(waddr, sizeof(waddr), "%lx",
424: (unsigned long) (PP(pp, p_wchan)) & ~KERNBASE);
425: p_wait = waddr;
426: }
427: else
428: p_wait = "-";
429:
430: /* format this entry */
431: snprintf(fmt, MAX_COLS,
1.1 downsj 432: Proc_format,
433: PP(pp, p_pid),
1.20 deraadt 434: (*get_userid) (EP(pp, e_pcred.p_ruid)),
1.1 downsj 435: PP(pp, p_priority) - PZERO,
436: PP(pp, p_nice) - NZERO,
437: format_k(pagetok(PROCSIZE(pp))),
438: format_k(pagetok(VP(pp, vm_rssize))),
1.2 kstailey 439: (PP(pp, p_stat) == SSLEEP && PP(pp, p_slptime) > MAXSLP)
1.20 deraadt 440: ? "idle" : state_abbrev[(unsigned char) PP(pp, p_stat)],
1.1 downsj 441: p_wait,
442: format_time(cputime),
443: 100.0 * pct,
444: printable(PP(pp, p_comm)));
445:
1.20 deraadt 446: /* return the result */
447: return (fmt);
1.1 downsj 448: }
449:
450: /* comparison routine for qsort */
1.11 kstailey 451: static unsigned char sorted_state[] =
452: {
1.20 deraadt 453: 0, /* not used */
454: 4, /* start */
455: 5, /* run */
456: 2, /* sleep */
457: 3, /* stop */
458: 1 /* zombie */
1.11 kstailey 459: };
460: #ifdef ORDER
461:
462: /*
463: * proc_compares - comparison functions for "qsort"
464: */
465:
466: /*
467: * First, the possible comparison keys. These are defined in such a way
468: * that they can be merely listed in the source code to define the actual
469: * desired ordering.
470: */
471:
472:
473: #define ORDERKEY_PCTCPU \
1.12 niklas 474: if (lresult = (pctcpu)PP(p2, p_pctcpu) - (pctcpu)PP(p1, p_pctcpu), \
1.22 deraadt 475: (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
1.11 kstailey 476: #define ORDERKEY_CPUTIME \
477: if ((result = PP(p2, p_rtime.tv_sec) - PP(p1, p_rtime.tv_sec)) == 0) \
478: if ((result = PP(p2, p_rtime.tv_usec) - \
479: PP(p1, p_rtime.tv_usec)) == 0)
480: #define ORDERKEY_STATE \
481: if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] - \
1.22 deraadt 482: sorted_state[(unsigned char) PP(p1, p_stat)]) == 0)
1.11 kstailey 483: #define ORDERKEY_PRIO \
484: if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
485: #define ORDERKEY_RSSIZE \
486: if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0)
487: #define ORDERKEY_MEM \
488: if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
489:
1.20 deraadt 490:
1.11 kstailey 491: /* compare_cpu - the comparison function for sorting by cpu percentage */
492: int
493: compare_cpu(v1, v2)
1.20 deraadt 494: const void *v1, *v2;
1.11 kstailey 495: {
1.20 deraadt 496: struct proc **pp1 = (struct proc **) v1;
497: struct proc **pp2 = (struct proc **) v2;
498: struct kinfo_proc *p1;
499: struct kinfo_proc *p2;
500: int result;
501: pctcpu lresult;
502:
503: /* remove one level of indirection */
504: p1 = *(struct kinfo_proc **) pp1;
505: p2 = *(struct kinfo_proc **) pp2;
506:
507: ORDERKEY_PCTCPU
508: ORDERKEY_CPUTIME
509: ORDERKEY_STATE
510: ORDERKEY_PRIO
511: ORDERKEY_RSSIZE
512: ORDERKEY_MEM
513: ;
514: return (result);
1.11 kstailey 515: }
516:
517: /* compare_size - the comparison function for sorting by total memory usage */
518: int
519: compare_size(v1, v2)
1.20 deraadt 520: const void *v1, *v2;
1.11 kstailey 521: {
1.20 deraadt 522: struct proc **pp1 = (struct proc **) v1;
523: struct proc **pp2 = (struct proc **) v2;
524: struct kinfo_proc *p1;
525: struct kinfo_proc *p2;
526: int result;
527: pctcpu lresult;
528:
529: /* remove one level of indirection */
530: p1 = *(struct kinfo_proc **) pp1;
531: p2 = *(struct kinfo_proc **) pp2;
532:
533: ORDERKEY_MEM
534: ORDERKEY_RSSIZE
535: ORDERKEY_PCTCPU
536: ORDERKEY_CPUTIME
537: ORDERKEY_STATE
538: ORDERKEY_PRIO
539: ;
540: return (result);
1.11 kstailey 541: }
542:
543: /* compare_res - the comparison function for sorting by resident set size */
544: int
545: compare_res(v1, v2)
1.20 deraadt 546: const void *v1, *v2;
1.11 kstailey 547: {
1.20 deraadt 548: struct proc **pp1 = (struct proc **) v1;
549: struct proc **pp2 = (struct proc **) v2;
550: struct kinfo_proc *p1;
551: struct kinfo_proc *p2;
552: int result;
553: pctcpu lresult;
554:
555: /* remove one level of indirection */
556: p1 = *(struct kinfo_proc **) pp1;
557: p2 = *(struct kinfo_proc **) pp2;
558:
559: ORDERKEY_RSSIZE
560: ORDERKEY_MEM
561: ORDERKEY_PCTCPU
562: ORDERKEY_CPUTIME
563: ORDERKEY_STATE
564: ORDERKEY_PRIO
565: ;
566: return (result);
1.11 kstailey 567: }
568:
569: /* compare_time - the comparison function for sorting by CPU time */
570: int
571: compare_time(v1, v2)
1.20 deraadt 572: const void *v1, *v2;
1.11 kstailey 573: {
1.20 deraadt 574: struct proc **pp1 = (struct proc **) v1;
575: struct proc **pp2 = (struct proc **) v2;
576: struct kinfo_proc *p1;
577: struct kinfo_proc *p2;
578: int result;
579: pctcpu lresult;
580:
581: /* remove one level of indirection */
582: p1 = *(struct kinfo_proc **) pp1;
583: p2 = *(struct kinfo_proc **) pp2;
584:
585: ORDERKEY_CPUTIME
586: ORDERKEY_PCTCPU
587: ORDERKEY_STATE
588: ORDERKEY_PRIO
589: ORDERKEY_MEM
590: ORDERKEY_RSSIZE
591: ;
592: return (result);
1.11 kstailey 593: }
594:
595: /* compare_prio - the comparison function for sorting by CPU time */
596: int
597: compare_prio(v1, v2)
1.20 deraadt 598: const void *v1, *v2;
1.11 kstailey 599: {
1.20 deraadt 600: struct proc **pp1 = (struct proc **) v1;
601: struct proc **pp2 = (struct proc **) v2;
602: struct kinfo_proc *p1;
603: struct kinfo_proc *p2;
604: int result;
605: pctcpu lresult;
606:
607: /* remove one level of indirection */
608: p1 = *(struct kinfo_proc **) pp1;
609: p2 = *(struct kinfo_proc **) pp2;
610:
611: ORDERKEY_PRIO
612: ORDERKEY_PCTCPU
613: ORDERKEY_CPUTIME
614: ORDERKEY_STATE
615: ORDERKEY_RSSIZE
616: ORDERKEY_MEM
617: ;
618: return (result);
619: }
620:
621: int (*proc_compares[]) () = {
622: compare_cpu,
623: compare_size,
624: compare_res,
625: compare_time,
626: compare_prio,
627: NULL
1.11 kstailey 628: };
1.20 deraadt 629: #else
1.1 downsj 630: /*
631: * proc_compare - comparison function for "qsort"
632: * Compares the resource consumption of two processes using five
633: * distinct keys. The keys (in descending order of importance) are:
634: * percent cpu, cpu ticks, state, resident set size, total virtual
635: * memory usage. The process states are ordered as follows (from least
636: * to most important): zombie, sleep, stop, start, run. The array
637: * declaration below maps a process state index into a number that
638: * reflects this ordering.
639: */
640: int
1.3 downsj 641: proc_compare(v1, v2)
1.20 deraadt 642: const void *v1, *v2;
1.1 downsj 643: {
1.20 deraadt 644: struct proc **pp1 = (struct proc **) v1;
645: struct proc **pp2 = (struct proc **) v2;
646: struct kinfo_proc *p1;
647: struct kinfo_proc *p2;
648: int result;
649: pctcpu lresult;
650:
651: /* remove one level of indirection */
652: p1 = *(struct kinfo_proc **) pp1;
653: p2 = *(struct kinfo_proc **) pp2;
654:
655: /* compare percent cpu (pctcpu) */
656: if ((lresult = PP(p2, p_pctcpu) - PP(p1, p_pctcpu)) == 0) {
657: /* use CPU usage to break the tie */
658: if ((result = PP(p2, p_rtime).tv_sec - PP(p1, p_rtime).tv_sec) == 0) {
659: /* use process state to break the tie */
660: if ((result = sorted_state[(unsigned char) PP(p2, p_stat)] -
661: sorted_state[(unsigned char) PP(p1, p_stat)]) == 0) {
662: /* use priority to break the tie */
1.22 deraadt 663: if ((result = PP(p2, p_priority) -
664: PP(p1, p_priority)) == 0) {
1.20 deraadt 665: /* use resident set size (rssize) to
666: * break the tie */
1.22 deraadt 667: if ((result = VP(p2, vm_rssize) -
668: VP(p1, vm_rssize)) == 0) {
1.20 deraadt 669: /* use total memory to break
670: * the tie */
671: result = PROCSIZE(p2) - PROCSIZE(p1);
672: }
673: }
674: }
1.1 downsj 675: }
1.20 deraadt 676: } else {
677: result = lresult < 0 ? -1 : 1;
1.1 downsj 678: }
1.20 deraadt 679: return (result);
1.1 downsj 680: }
1.11 kstailey 681: #endif
1.1 downsj 682:
683: /*
684: * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
685: * the process does not exist.
686: * It is EXTREMLY IMPORTANT that this function work correctly.
687: * If top runs setuid root (as in SVR4), then this function
688: * is the only thing that stands in the way of a serious
689: * security problem. It validates requests for the "kill"
690: * and "renice" commands.
691: */
1.20 deraadt 692: int
693: proc_owner(pid)
694: pid_t pid;
695: {
696: struct kinfo_proc **prefp, *pp;
697: int cnt;
698:
699: prefp = pref;
700: cnt = pref_len;
701: while (--cnt >= 0) {
702: pp = *prefp++;
703: if (PP(pp, p_pid) == pid) {
704: return ((int) EP(pp, e_pcred.p_ruid));
705: }
1.1 downsj 706: }
1.20 deraadt 707: return (-1);
1.1 downsj 708: }
709: #ifdef DOSWAP
710: /*
1.17 todd 711: * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
1.15 weingart 712: * to be based on the new swapctl(2) system call.
1.1 downsj 713: */
714: static int
715: swapmode(used, total)
1.20 deraadt 716: int *used;
717: int *total;
1.1 downsj 718: {
1.20 deraadt 719: int nswap, rnswap, i;
1.15 weingart 720: struct swapent *swdev;
1.1 downsj 721:
1.15 weingart 722: nswap = swapctl(SWAP_NSWAP, 0, 0);
1.20 deraadt 723: if (nswap == 0)
1.15 weingart 724: return 0;
725:
726: swdev = malloc(nswap * sizeof(*swdev));
1.20 deraadt 727: if (swdev == NULL)
1.15 weingart 728: return 0;
729:
730: rnswap = swapctl(SWAP_STATS, swdev, nswap);
1.20 deraadt 731: if (rnswap == -1)
1.15 weingart 732: return 0;
733:
734: /* if rnswap != nswap, then what? */
735:
736: /* Total things up */
737: *total = *used = 0;
738: for (i = 0; i < nswap; i++) {
739: if (swdev[i].se_flags & SWF_ENABLE) {
1.20 deraadt 740: *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
741: *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
1.1 downsj 742: }
743: }
744:
1.20 deraadt 745: free(swdev);
1.1 downsj 746: return 1;
747: }
748: #endif