Home | History | Annotate | Line # | Download | only in machine
      1 /*
      2  * Copyright (c) 1984 through 2008, William LeFebvre
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *
     16  *     * Neither the name of William LeFebvre nor the names of other
     17  * contributors may be used to endorse or promote products derived from
     18  * this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * top - a top users display for Unix
     35  *
     36  * SYNOPSIS:  For FreeBSD 5.x, 6.x, 7.x, 8.x
     37  *
     38  * DESCRIPTION:
     39  * Originally written for BSD4.4 system by Christos Zoulas.
     40  * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
     41  * Order support hacked in from top-3.5beta6/machine/m_aix41.c
     42  *   by Monte Mitzelfelt
     43  * Ported to FreeBSD 5.x and higher by William LeFebvre
     44  *
     45  * AUTHOR:  Christos Zoulas <christos (at) ee.cornell.edu>
     46  *          Steven Wallace  <swallace (at) freebsd.org>
     47  *          Wolfram Schneider <wosch (at) FreeBSD.org>
     48  */
     49 
     50 
     51 #include <sys/time.h>
     52 #include <sys/types.h>
     53 #include <sys/signal.h>
     54 #include <sys/param.h>
     55 
     56 #include "config.h"
     57 #include <stdio.h>
     58 #include <string.h>
     59 #include <nlist.h>
     60 #include <math.h>
     61 #include <kvm.h>
     62 #include <pwd.h>
     63 #include <sys/errno.h>
     64 #include <sys/sysctl.h>
     65 #include <sys/dkstat.h>
     66 #include <sys/file.h>
     67 #include <sys/time.h>
     68 #include <sys/proc.h>
     69 #include <sys/user.h>
     70 #include <sys/vmmeter.h>
     71 #include <sys/resource.h>
     72 #include <sys/rtprio.h>
     73 #ifdef HAVE_UNISTD_H
     74 #include <unistd.h>
     75 #endif
     76 
     77 /* Swap */
     78 #include <stdlib.h>
     79 #include <sys/conf.h>
     80 
     81 #include <osreldate.h> /* for changes in kernel structures */
     82 
     83 #include "top.h"
     84 #include "machine.h"
     85 #include "utils.h"
     86 #include "username.h"
     87 #include "hash.h"
     88 #include "display.h"
     89 
     90 extern char* printable __P((char *));
     91 int swapmode __P((int *retavail, int *retfree));
     92 static int smpmode;
     93 static int namelength;
     94 
     95 /*
     96  * Versions prior to 5.x do not track threads in kinfo_proc, so we
     97  * simply do not display any information about them.
     98  * Versions 5.x, 6.x, and 7.x track threads but the data reported
     99  * as runtime for each thread is actually per-process and is just
    100  * duplicated across all threads.  It would be very wrong to show
    101  * this data individually for each thread.  Therefore we will show
    102  * a THR column (number of threads) but not provide any sort of
    103  * per-thread display.  We distinguish between these three ways of
    104  * handling threads as follows:  HAS_THREADS indicates that the
    105  * system has and tracks kernel threads (a THR column will appear
    106  * in the display).  HAS_SHOWTHREADS indicates that the system
    107  * reports correct per-thread information and we will provide a
    108  * per-thread display (the 'H' and 't' command) upon request.
    109  * HAS_SHOWTHREADS implies HAS_THREADS.
    110  */
    111 
    112 /* HAS_THREADS for anything 5.x and up */
    113 #if OSMAJOR >= 5
    114 #define HAS_THREADS
    115 #endif
    116 
    117 /* HAS_SHOWTHREADS for anything 8.x and up */
    118 #if OSMAJOR >=8
    119 #define HAS_SHOWTHREADS
    120 #endif
    121 
    122 /* get_process_info passes back a handle.  This is what it looks like: */
    123 
    124 struct handle
    125 {
    126     struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
    127     int remaining;		/* number of pointers remaining */
    128 };
    129 
    130 /* declarations for load_avg */
    131 #include "loadavg.h"
    132 
    133 /*
    134  * Macros to access process information:
    135  * In versions 4.x and earlier the kinfo_proc structure was a collection of
    136  * substructures (kp_proc and kp_eproc).  Starting with 5.0 kinfo_proc was
    137  * redesigned and "flattene" so that most of the information was available
    138  * in a single structure.  We use macros to access the various types of
    139  * information and define these macros according to the OS revision.  The
    140  * names PP, EP, and VP are due to the fact that information was originally
    141  * contained in the different substructures.  We retain these names in the
    142  * code for backward compatibility.  These macros use ANSI concatenation.
    143  * PP: proc
    144  * EP: extented proc
    145  * VP: vm (virtual memory information)
    146  * PRUID: Real uid
    147  * RP: rusage
    148  * PPCPU: where we store calculated cpu% data
    149  * SPPTR: where we store pointer to extra calculated data
    150  * SP: access to the extra calculated data pointed to by SPPTR
    151  */
    152 #if OSMAJOR <= 4
    153 #define PP(pp, field) ((pp)->kp_proc . p_##field)
    154 #define EP(pp, field) ((pp)->kp_eproc . e_##field)
    155 #define VP(pp, field) ((pp)->kp_eproc.e_vm . vm_##field)
    156 #define PRUID(pp) ((pp)->kp_eproc.e_pcred.p_ruid)
    157 #else
    158 #define PP(pp, field) ((pp)->ki_##field)
    159 #define EP(pp, field) ((pp)->ki_##field)
    160 #define VP(pp, field) ((pp)->ki_##field)
    161 #define PRUID(pp) ((pp)->ki_ruid)
    162 #define RP(pp, field) ((pp)->ki_rusage.ru_##field)
    163 #define PPCPU(pp) ((pp)->ki_sparelongs[0])
    164 #define SPPTR(pp) ((pp)->ki_spareptrs[0])
    165 #define SP(pp, field) (((struct save_proc *)((pp)->ki_spareptrs[0]))->sp_##field)
    166 #endif
    167 
    168 /* what we consider to be process size: */
    169 #if OSMAJOR <= 4
    170 #define PROCSIZE(pp) (VP((pp), map.size) / 1024)
    171 #else
    172 #define PROCSIZE(pp) (((pp)->ki_size) / 1024)
    173 #endif
    174 
    175 /* calculate a per-second rate using milliseconds */
    176 #define per_second(n, msec)   (((n) * 1000) / (msec))
    177 
    178 /* process state names for the "STATE" column of the display */
    179 /* the extra nulls in the string "run" are for adding a slash and
    180    the processor number when needed */
    181 
    182 char *state_abbrev[] =
    183 {
    184     "?", "START", "RUN", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK"
    185 };
    186 #define NUM_STATES 8
    187 
    188 /* kernel access */
    189 static kvm_t *kd;
    190 
    191 /* these are for dealing with sysctl-based data */
    192 #define MAXMIBLEN 8
    193 struct sysctl_mib {
    194     char *name;
    195     int mib[MAXMIBLEN];
    196     size_t miblen;
    197 };
    198 static struct sysctl_mib mibs[] = {
    199     { "vm.stats.sys.v_swtch" },
    200 #define V_SWTCH 0
    201     { "vm.stats.sys.v_trap" },
    202 #define V_TRAP 1
    203     { "vm.stats.sys.v_intr" },
    204 #define V_INTR 2
    205     { "vm.stats.sys.v_soft" },
    206 #define V_SOFT 3
    207     { "vm.stats.vm.v_forks" },
    208 #define V_FORKS 4
    209     { "vm.stats.vm.v_vforks" },
    210 #define V_VFORKS 5
    211     { "vm.stats.vm.v_rforks" },
    212 #define V_RFORKS 6
    213     { "vm.stats.vm.v_vm_faults" },
    214 #define V_VM_FAULTS 7
    215     { "vm.stats.vm.v_swapin" },
    216 #define V_SWAPIN 8
    217     { "vm.stats.vm.v_swapout" },
    218 #define V_SWAPOUT 9
    219     { "vm.stats.vm.v_tfree" },
    220 #define V_TFREE 10
    221     { "vm.stats.vm.v_vnodein" },
    222 #define V_VNODEIN 11
    223     { "vm.stats.vm.v_vnodeout" },
    224 #define V_VNODEOUT 12
    225     { "vm.stats.vm.v_active_count" },
    226 #define V_ACTIVE_COUNT 13
    227     { "vm.stats.vm.v_inactive_count" },
    228 #define V_INACTIVE_COUNT 14
    229     { "vm.stats.vm.v_wire_count" },
    230 #define V_WIRE_COUNT 15
    231     { "vm.stats.vm.v_cache_count" },
    232 #define V_CACHE_COUNT 16
    233     { "vm.stats.vm.v_free_count" },
    234 #define V_FREE_COUNT 17
    235     { "vm.stats.vm.v_swappgsin" },
    236 #define V_SWAPPGSIN 18
    237     { "vm.stats.vm.v_swappgsout" },
    238 #define V_SWAPPGSOUT 19
    239     { "vfs.bufspace" },
    240 #define VFS_BUFSPACE 20
    241     { "kern.cp_time" },
    242 #define K_CP_TIME 21
    243 #ifdef HAS_SHOWTHREADS
    244     { "kern.proc.all" },
    245 #else
    246     { "kern.proc.proc" },
    247 #endif
    248 #define K_PROC 22
    249     { NULL }
    250 };
    251 
    252 
    253 /* these are for calculating cpu state percentages */
    254 
    255 static long cp_time[CPUSTATES];
    256 static long cp_old[CPUSTATES];
    257 static long cp_diff[CPUSTATES];
    258 
    259 /* these are for detailing the process states */
    260 
    261 int process_states[8];
    262 char *procstatenames[] = {
    263     "", " starting, ", " running, ", " sleeping, ", " stopped, ", " zombie, ",
    264     " waiting, ", " locked, ",
    265     NULL
    266 };
    267 
    268 /* these are for detailing the cpu states */
    269 
    270 int cpu_states[CPUSTATES];
    271 char *cpustatenames[] = {
    272     "user", "nice", "system", "interrupt", "idle", NULL
    273 };
    274 
    275 /* these are for detailing the kernel information */
    276 
    277 int kernel_stats[9];
    278 char *kernelnames[] = {
    279     " ctxsw, ", " trap, ", " intr, ", " soft, ", " fork, ",
    280     " flt, ", " pgin, ", " pgout, ", " fr",
    281     NULL
    282 };
    283 
    284 /* these are for detailing the memory statistics */
    285 
    286 long memory_stats[7];
    287 char *memorynames[] = {
    288     "K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
    289     NULL
    290 };
    291 
    292 long swap_stats[7];
    293 char *swapnames[] = {
    294 /*   0           1            2           3            4       5 */
    295     "K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
    296     NULL
    297 };
    298 
    299 
    300 /*
    301  * pbase points to the array that holds the kinfo_proc structures.  pref
    302  * (pronounced p-ref) points to an array of kinfo_proc pointers and is where
    303  * we build up a list of processes we wish to display.  Both pbase and pref are
    304  * potentially resized on every call to get_process_info.  psize is the number
    305  * of procs for which we currently have space allocated.  pref_len is the number
    306  * of valid pointers in pref (this is used by proc_owner).  We start psize off
    307  * at -1 to ensure that space gets allocated on the first call to
    308  * get_process_info.
    309  */
    310 
    311 static int psize = -1;
    312 static int pref_len;
    313 static struct kinfo_proc *pbase = NULL;
    314 static struct kinfo_proc **pref = NULL;
    315 
    316 /* this structure retains information from the proc array between samples */
    317 struct save_proc {
    318     pid_t sp_pid;
    319     u_int64_t sp_runtime;
    320     long sp_vcsw;
    321     long sp_ivcsw;
    322     long sp_inblock;
    323     long sp_oublock;
    324     long sp_majflt;
    325     long sp_totalio;
    326     long sp_old_nvcsw;
    327     long sp_old_nivcsw;
    328     long sp_old_inblock;
    329     long sp_old_oublock;
    330     long sp_old_majflt;
    331 };
    332 hash_table *procs;
    333 
    334 struct proc_field {
    335     char *name;
    336     int width;
    337     int rjust;
    338     int min_screenwidth;
    339     int (*format)(char *, int, struct kinfo_proc *);
    340 };
    341 
    342 /* these are for getting the memory statistics */
    343 
    344 static int pagesize;		/* kept from getpagesize */
    345 static int pageshift;		/* log base 2 of the pagesize */
    346 
    347 /* define pagetok in terms of pageshift */
    348 
    349 #define pagetok(size) ((size) << pageshift)
    350 
    351 /* things that we track between updates */
    352 static u_int ctxsws = 0;
    353 static u_int traps = 0;
    354 static u_int intrs = 0;
    355 static u_int softs = 0;
    356 static u_int64_t forks = 0;
    357 static u_int pfaults;
    358 static u_int pagein;
    359 static u_int pageout;
    360 static u_int tfreed;
    361 static int swappgsin = -1;
    362 static int swappgsout = -1;
    363 extern struct timeval timeout;
    364 static struct timeval lasttime = { 0, 0 };
    365 static long elapsed_time;
    366 static long elapsed_msecs;
    367 
    368 /* things that we track during an update */
    369 static long total_io;
    370 static int show_fullcmd;
    371 static struct handle handle;
    372 static int username_length;
    373 static int show_usernames;
    374 static int display_mode;
    375 static int *display_fields;
    376 #ifdef HAS_SHOWTHREADS
    377 static int show_threads = 0;
    378 #endif
    379 
    380 
    381 /* sorting orders. first is default */
    382 char *ordernames[] = {
    383     "cpu", "size", "res", "time", "pri", "io", "pid", NULL
    384 };
    385 
    386 /* compare routines */
    387 int proc_compare(), compare_size(), compare_res(), compare_time(),
    388     compare_prio(), compare_io(), compare_pid();
    389 
    390 int (*proc_compares[])() = {
    391     proc_compare,
    392     compare_size,
    393     compare_res,
    394     compare_time,
    395     compare_prio,
    396     compare_io,
    397     compare_pid,
    398     NULL
    399 };
    400 
    401 /* swap related calculations */
    402 
    403 static int mib_swapinfo[16];
    404 static int *mib_swapinfo_idx;
    405 static int mib_swapinfo_size = 0;
    406 
    407 void
    408 swap_init()
    409 
    410 {
    411     size_t m;
    412 
    413     m = sizeof(mib_swapinfo) / sizeof(mib_swapinfo[0]);
    414     if (sysctlnametomib("vm.swap_info", mib_swapinfo, &m) != -1)
    415     {
    416 	mib_swapinfo_size = m + 1;
    417 	mib_swapinfo_idx = &(mib_swapinfo[m]);
    418     }
    419 }
    420 
    421 int
    422 swap_getdata(long long *retavail, long long *retfree)
    423 
    424 {
    425     int n;
    426     size_t size;
    427     long long total = 0;
    428     long long used = 0;
    429     struct xswdev xsw;
    430 
    431     n = 0;
    432     if (mib_swapinfo_size > 0)
    433     {
    434 	*mib_swapinfo_idx = 0;
    435 	while (size = sizeof(xsw),
    436 	       sysctl(mib_swapinfo, mib_swapinfo_size, &xsw, &size, NULL, 0) != -1)
    437 	{
    438 	    dprintf("swap_getdata: swaparea %d: nblks %d, used %d\n",
    439 		    n, xsw.xsw_nblks, xsw.xsw_used);
    440 	    total += (long long)xsw.xsw_nblks;
    441 	    used += (long long)xsw.xsw_used;
    442 	    *mib_swapinfo_idx = ++n;
    443 	}
    444 
    445 	*retavail = pagetok(total);
    446 	*retfree = pagetok(total) - pagetok(used);
    447 
    448 	if (total > 0)
    449 	{
    450 	    n = (int)((double)used * 100.0 / (double)total);
    451 	}
    452 	else
    453 	{
    454 	    n = 0;
    455 	}
    456     }
    457     else
    458     {
    459 	*retavail = 0;
    460 	*retfree = 0;
    461     }
    462 
    463     dprintf("swap_getdata: avail %lld, free %lld, %d%%\n",
    464 	    *retavail, *retfree, n);
    465     return(n);
    466 }
    467 
    468 /*
    469  *  getkval(offset, ptr, size) - get a value out of the kernel.
    470  *	"offset" is the byte offset into the kernel for the desired value,
    471  *  	"ptr" points to a buffer into which the value is retrieved,
    472  *  	"size" is the size of the buffer (and the object to retrieve).
    473  *      Return 0 on success, -1 on any kind of failure.
    474  */
    475 
    476 static int
    477 getkval(unsigned long offset, int *ptr, int size)
    478 
    479 {
    480     if (kd != NULL)
    481     {
    482 	if (kvm_read(kd, offset, (char *) ptr, size) == size)
    483 	{
    484 	    return(0);
    485 	}
    486     }
    487     return(-1);
    488 }
    489 
    490 int
    491 get_sysctl_mibs()
    492 
    493 {
    494     struct sysctl_mib *mp;
    495     size_t len;
    496 
    497     mp = mibs;
    498     while (mp->name != NULL)
    499     {
    500 	len = MAXMIBLEN;
    501 	if (sysctlnametomib(mp->name, mp->mib, &len) == -1)
    502 	{
    503 	    message_error(" sysctlnametomib: %s", strerror(errno));
    504 	    return -1;
    505 	}
    506 	mp->miblen = len;
    507 	mp++;
    508     }
    509     return 0;
    510 }
    511 
    512 int
    513 get_sysctl(int idx, void *v, size_t l)
    514 
    515 {
    516     struct sysctl_mib *m;
    517     size_t len;
    518 
    519     m = &(mibs[idx]);
    520     len = l;
    521     if (sysctl(m->mib, m->miblen, v, &len, NULL, 0) == -1)
    522     {
    523 	message_error(" sysctl: %s", strerror(errno));
    524 	return -1;
    525     }
    526     return len;
    527 }
    528 
    529 size_t
    530 get_sysctlsize(int idx)
    531 
    532 {
    533     size_t len;
    534     struct sysctl_mib *m;
    535 
    536     m = &(mibs[idx]);
    537     if (sysctl(m->mib, m->miblen, NULL, &len, NULL, 0) == -1)
    538     {
    539 	message_error(" sysctl (size): %s", strerror(errno));
    540 	len = 0;
    541     }
    542     return len;
    543 }
    544 
    545 int
    546 fmt_pid(char *buf, int sz, struct kinfo_proc *pp)
    547 
    548 {
    549     return snprintf(buf, sz, "%6d", PP(pp, pid));
    550 }
    551 
    552 int
    553 fmt_username(char *buf, int sz, struct kinfo_proc *pp)
    554 
    555 {
    556     return snprintf(buf, sz, "%-*.*s",
    557 		    username_length, username_length, username(PRUID(pp)));
    558 }
    559 
    560 int
    561 fmt_uid(char *buf, int sz, struct kinfo_proc *pp)
    562 
    563 {
    564     return snprintf(buf, sz, "%6d", PRUID(pp));
    565 }
    566 
    567 int
    568 fmt_thr(char *buf, int sz, struct kinfo_proc *pp)
    569 
    570 {
    571     return snprintf(buf, sz, "%3d", PP(pp, numthreads));
    572 }
    573 
    574 int
    575 fmt_pri(char *buf, int sz, struct kinfo_proc *pp)
    576 
    577 {
    578 #if OSMAJOR <= 4
    579     return snprintf(buf, sz, "%3d", PP(pp, priority));
    580 #else
    581     return snprintf(buf, sz, "%3d", PP(pp, pri.pri_level));
    582 #endif
    583 }
    584 
    585 int
    586 fmt_nice(char *buf, int sz, struct kinfo_proc *pp)
    587 
    588 {
    589     return snprintf(buf, sz, "%4d", PP(pp, nice) - NZERO);
    590 }
    591 
    592 int
    593 fmt_size(char *buf, int sz, struct kinfo_proc *pp)
    594 
    595 {
    596     return snprintf(buf, sz, "%5s", format_k(PROCSIZE(pp)));
    597 }
    598 
    599 int
    600 fmt_res(char *buf, int sz, struct kinfo_proc *pp)
    601 
    602 {
    603     return snprintf(buf, sz, "%5s", format_k(pagetok(VP(pp, rssize))));
    604 }
    605 
    606 int
    607 fmt_state(char *buf, int sz, struct kinfo_proc *pp)
    608 
    609 {
    610     int state;
    611     char status[16];
    612 
    613     state = PP(pp, stat);
    614     switch(state)
    615     {
    616     case SRUN:
    617 	if (smpmode && PP(pp, oncpu) != 0xff)
    618 	    sprintf(status, "CPU%d", PP(pp, oncpu));
    619 	else
    620 	    strcpy(status, "RUN");
    621 	break;
    622 
    623     case SSLEEP:
    624 	if (EP(pp, wmesg) != NULL) {
    625 	    sprintf(status, "%.6s", EP(pp, wmesg));
    626 	    break;
    627 	}
    628 	/* fall through */
    629     default:
    630 	if (state >= 0 && state < NUM_STATES)
    631 	    sprintf(status, "%.6s", state_abbrev[(unsigned char) state]);
    632 	else
    633 	    sprintf(status, "?%-5d", state);
    634 	break;
    635     }
    636 
    637     return snprintf(buf, sz, "%-6.6s", status);
    638 }
    639 
    640 int
    641 fmt_flags(char *buf, int sz, struct kinfo_proc *pp)
    642 
    643 {
    644     long flag;
    645     char chrs[12];
    646     char *p;
    647 
    648     flag = PP(pp, flag);
    649     p = chrs;
    650     if (PP(pp, nice) < NZERO)
    651 	*p++ = '<';
    652     else if (PP(pp, nice) > NZERO)
    653 	*p++ = 'N';
    654     if (flag & P_TRACED)
    655 	*p++ = 'X';
    656     if (flag & P_WEXIT && PP(pp, stat) != SZOMB)
    657 	*p++ = 'E';
    658     if (flag & P_PPWAIT)
    659 	*p++ = 'V';
    660     if (flag & P_SYSTEM || PP(pp, lock) > 0)
    661 	*p++ = 'L';
    662     if (PP(pp, kiflag) & KI_SLEADER)
    663 	*p++ = 's';
    664     if (flag & P_CONTROLT)
    665 	*p++ = '+';
    666     if (flag & P_JAILED)
    667 	*p++ = 'J';
    668     *p = '\0';
    669 
    670     return snprintf(buf, sz, "%-3.3s", chrs);
    671 }
    672 
    673 int
    674 fmt_c(char *buf, int sz, struct kinfo_proc *pp)
    675 
    676 {
    677     return snprintf(buf, sz, "%1x", PP(pp, lastcpu));
    678 }
    679 
    680 int
    681 fmt_time(char *buf, int sz, struct kinfo_proc *pp)
    682 
    683 {
    684     return snprintf(buf, sz, "%6s",
    685 		    format_time((PP(pp, runtime) + 500000) / 1000000));
    686 }
    687 
    688 int
    689 fmt_cpu(char *buf, int sz, struct kinfo_proc *pp)
    690 
    691 {
    692     return snprintf(buf, sz, "%5.2f%%", (double)PPCPU(pp) / 100.0);
    693 }
    694 
    695 int
    696 fmt_command(char *buf, int sz, struct kinfo_proc *pp)
    697 
    698 {
    699     int inmem;
    700     char cmd[MAX_COLS];
    701     char *bufp;
    702     struct pargs pargs;
    703     int len;
    704 
    705 #if OSMAJOR <= 4
    706     inmem = (PP(pp, flag) & P_INMEM);
    707 #else
    708     inmem = (PP(pp, sflag) & PS_INMEM);
    709 #endif
    710 
    711     if (show_fullcmd && inmem)
    712     {
    713         /* get the pargs structure */
    714         if (getkval((unsigned long)PP(pp, args), (int *)&pargs, sizeof(pargs)) != -1)
    715         {
    716             /* determine workable length */
    717             if ((len = pargs.ar_length) >= MAX_COLS)
    718             {
    719                 len = MAX_COLS - 1;
    720             }
    721 
    722             /* get the string from that */
    723             if (len > 0 && getkval((unsigned long)PP(pp, args) +
    724 				   sizeof(pargs.ar_ref) +
    725 				   sizeof(pargs.ar_length),
    726 				   (int *)cmd, len) != -1)
    727             {
    728                 /* successfull retrieval: now convert nulls in to spaces */
    729                 bufp = cmd;
    730                 while (len-- > 0)
    731                 {
    732                     if (*bufp == '\0')
    733                     {
    734                         *bufp = ' ';
    735                     }
    736                     bufp++;
    737                 }
    738 
    739                 /* null terminate cmd */
    740                 *--bufp = '\0';
    741 
    742 		/* format cmd as our answer */
    743 		return snprintf(buf, sz, "%s", cmd);
    744             }
    745         }
    746     }
    747 
    748     /* for anything else we just display comm */
    749     return snprintf(buf, sz, inmem ? "%s" : "<%s>", printable(PP(pp, comm)));
    750 }
    751 
    752 int
    753 fmt_vcsw(char *buf, int sz, struct kinfo_proc *pp)
    754 
    755 {
    756     return snprintf(buf, sz, "%6ld", per_second(SP(pp, vcsw), elapsed_msecs));
    757 }
    758 
    759 int
    760 fmt_ivcsw(char *buf, int sz, struct kinfo_proc *pp)
    761 
    762 {
    763     return snprintf(buf, sz, "%6ld", per_second(SP(pp, ivcsw), elapsed_msecs));
    764 }
    765 
    766 int
    767 fmt_read(char *buf, int sz, struct kinfo_proc *pp)
    768 
    769 {
    770     return snprintf(buf, sz, "%6ld", per_second(SP(pp, inblock), elapsed_msecs));
    771 }
    772 
    773 int
    774 fmt_write(char *buf, int sz, struct kinfo_proc *pp)
    775 
    776 {
    777     return snprintf(buf, sz, "%6ld", per_second(SP(pp, oublock), elapsed_msecs));
    778 }
    779 
    780 int
    781 fmt_fault(char *buf, int sz, struct kinfo_proc *pp)
    782 
    783 {
    784     return snprintf(buf, sz, "%6ld", per_second(SP(pp, majflt), elapsed_msecs));
    785 }
    786 
    787 int
    788 fmt_iototal(char *buf, int sz, struct kinfo_proc *pp)
    789 
    790 {
    791     return snprintf(buf, sz, "%6ld", per_second(SP(pp, totalio), elapsed_msecs));
    792 }
    793 
    794 int
    795 fmt_iopct(char *buf, int sz, struct kinfo_proc *pp)
    796 
    797 {
    798     return snprintf(buf, sz, "%6.2f", (SP(pp, totalio) * 100.) / total_io);
    799 }
    800 
    801 
    802 struct proc_field proc_field[] = {
    803     { "PID", 6, 1, 0, fmt_pid },
    804     { "USERNAME", 8, 0, 0, fmt_username },
    805 #define FIELD_USERNAME 1
    806     { "UID", 6, 1, 0, fmt_uid },
    807 #define FIELD_UID 2
    808     { "THR", 3, 1, 0, fmt_thr },
    809     { "PRI", 3, 1, 0, fmt_pri },
    810     { "NICE", 4, 1, 0, fmt_nice },
    811     { "SIZE", 5, 1, 0, fmt_size },
    812     { "RES", 5, 1, 0, fmt_res },
    813     { "STATE", 6, 0, 0, fmt_state },
    814     { "FLG", 3, 0, 84, fmt_flags },
    815     { "C", 1, 0, 0, fmt_c },
    816     { "TIME", 6, 1, 0, fmt_time },
    817     { "CPU", 6, 1, 0, fmt_cpu },
    818     { "COMMAND", 7, 0, 0, fmt_command },
    819     { "VCSW", 6, 1, 0, fmt_vcsw },
    820     { "IVCSW", 6, 1, 0, fmt_ivcsw },
    821     { "READ", 6, 1, 0, fmt_read },
    822     { "WRITE", 6, 1, 0, fmt_write },
    823     { "FAULT", 6, 1, 0, fmt_fault },
    824     { "TOTAL", 6, 1, 0, fmt_iototal },
    825     { "PERCENT", 7, 1, 0, fmt_iopct },
    826     { NULL, 0, 0, 0, NULL }
    827 };
    828 #define MAX_FIELDS 24
    829 
    830 static int mode0_display[MAX_FIELDS];
    831 static int mode0thr_display[MAX_FIELDS];
    832 static int mode1_display[MAX_FIELDS];
    833 
    834 int
    835 field_index(char *col)
    836 
    837 {
    838     struct proc_field *fp;
    839     int i = 0;
    840 
    841     fp = proc_field;
    842     while (fp->name != NULL)
    843     {
    844 	if (strcmp(col, fp->name) == 0)
    845 	{
    846 	    return i;
    847 	}
    848 	fp++;
    849 	i++;
    850     }
    851 
    852     return -1;
    853 }
    854 
    855 void
    856 field_subst(int *fp, int old, int new)
    857 
    858 {
    859     while (*fp != -1)
    860     {
    861 	if (*fp == old)
    862 	{
    863 	    *fp = new;
    864 	}
    865 	fp++;
    866     }
    867 }
    868 
    869 int
    870 machine_init(struct statics *statics)
    871 
    872 {
    873     int i = 0;
    874     size_t len;
    875     int *ip;
    876 
    877     struct timeval boottime;
    878 
    879     len = sizeof(smpmode);
    880     if ((sysctlbyname("machdep.smp_active", &smpmode, &len, NULL, 0) < 0 &&
    881          sysctlbyname("smp.smp_active", &smpmode, &len, NULL, 0) < 0) ||
    882 	len != sizeof(smpmode))
    883     {
    884 	smpmode = 0;
    885     }
    886     smpmode = smpmode != 0;
    887 
    888     /* kvm_open the active kernel: its okay if this fails */
    889     kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
    890 
    891     /* get boot time */
    892     len = sizeof(boottime);
    893     if (sysctlbyname("kern.boottime", &boottime, &len, NULL, 0) == -1)
    894     {
    895 	/* we have no boottime to report */
    896 	boottime.tv_sec = -1;
    897     }
    898 
    899     pbase = NULL;
    900     pref = NULL;
    901 
    902     /* get the page size with "getpagesize" and calculate pageshift from it */
    903     i = pagesize = getpagesize();
    904     pageshift = 0;
    905     while (i > 1)
    906     {
    907 	pageshift++;
    908 	i >>= 1;
    909     }
    910 
    911     /* translate sysctl paths to mibs for faster access */
    912     get_sysctl_mibs();
    913 
    914     /* initialize swap stuff */
    915     swap_init();
    916 
    917     /* create the hash table that remembers proc data */
    918     procs = hash_create(2039);
    919 
    920     /* we only need the amount of log(2)1024 for our conversion */
    921     pageshift -= LOG1024;
    922 
    923     /* fill in the statics information */
    924     statics->procstate_names = procstatenames;
    925     statics->cpustate_names = cpustatenames;
    926     statics->memory_names = memorynames;
    927     statics->kernel_names = kernelnames;
    928     statics->boottime = boottime.tv_sec;
    929     statics->swap_names = swapnames;
    930     statics->order_names = ordernames;
    931     statics->flags.warmup = 1;
    932     statics->modemax = 2;
    933 #ifdef HAS_SHOWTHREADS
    934     statics->flags.threads = 1;
    935 #endif
    936 
    937     /* we need kvm descriptor in order to show full commands */
    938     statics->flags.fullcmds = kd != NULL;
    939 
    940     /* set up the display indices for mode0 */
    941     ip = mode0_display;
    942     *ip++ = field_index("PID");
    943     *ip++ = field_index("USERNAME");
    944 #ifdef HAS_THREADS
    945     *ip++ = field_index("THR");
    946 #endif
    947     *ip++ = field_index("PRI");
    948     *ip++ = field_index("NICE");
    949     *ip++ = field_index("SIZE");
    950     *ip++ = field_index("RES");
    951     *ip++ = field_index("STATE");
    952     *ip++ = field_index("FLG");
    953     if (smpmode)
    954 	*ip++ = field_index("C");
    955     *ip++ = field_index("TIME");
    956     *ip++ = field_index("CPU");
    957     *ip++ = field_index("COMMAND");
    958     *ip = -1;
    959 
    960 #ifdef HAS_SHOWTHREADS
    961     /* set up the display indices for mode0 showing threads */
    962     ip = mode0thr_display;
    963     *ip++ = field_index("PID");
    964     *ip++ = field_index("USERNAME");
    965     *ip++ = field_index("PRI");
    966     *ip++ = field_index("NICE");
    967     *ip++ = field_index("SIZE");
    968     *ip++ = field_index("RES");
    969     *ip++ = field_index("STATE");
    970     *ip++ = field_index("FLG");
    971     if (smpmode)
    972 	*ip++ = field_index("C");
    973     *ip++ = field_index("TIME");
    974     *ip++ = field_index("CPU");
    975     *ip++ = field_index("COMMAND");
    976     *ip = -1;
    977 #endif
    978 
    979     /* set up the display indices for mode1 */
    980     ip = mode1_display;
    981     *ip++ = field_index("PID");
    982     *ip++ = field_index("USERNAME");
    983     *ip++ = field_index("VCSW");
    984     *ip++ = field_index("IVCSW");
    985     *ip++ = field_index("READ");
    986     *ip++ = field_index("WRITE");
    987     *ip++ = field_index("FAULT");
    988     *ip++ = field_index("TOTAL");
    989     *ip++ = field_index("PERCENT");
    990     *ip++ = field_index("COMMAND");
    991     *ip = -1;
    992 
    993     /* all done! */
    994     return(0);
    995 }
    996 
    997 char *format_header(char *uname_field)
    998 
    999 {
   1000     return "";
   1001 }
   1002 
   1003 void
   1004 get_vm_sum(struct vmmeter *sum)
   1005 
   1006 {
   1007 #define GET_VM_STAT(v, s)  (void)get_sysctl(v, &(sum->s), sizeof(sum->s))
   1008 
   1009     GET_VM_STAT(V_SWTCH, v_swtch);
   1010     GET_VM_STAT(V_TRAP, v_trap);
   1011     GET_VM_STAT(V_INTR, v_intr);
   1012     GET_VM_STAT(V_SOFT, v_soft);
   1013     GET_VM_STAT(V_VFORKS, v_vforks);
   1014     GET_VM_STAT(V_FORKS, v_forks);
   1015     GET_VM_STAT(V_RFORKS, v_rforks);
   1016     GET_VM_STAT(V_VM_FAULTS, v_vm_faults);
   1017     GET_VM_STAT(V_SWAPIN, v_swapin);
   1018     GET_VM_STAT(V_SWAPOUT, v_swapout);
   1019     GET_VM_STAT(V_TFREE, v_tfree);
   1020     GET_VM_STAT(V_VNODEIN, v_vnodein);
   1021     GET_VM_STAT(V_VNODEOUT, v_vnodeout);
   1022     GET_VM_STAT(V_ACTIVE_COUNT, v_active_count);
   1023     GET_VM_STAT(V_INACTIVE_COUNT, v_inactive_count);
   1024     GET_VM_STAT(V_WIRE_COUNT, v_wire_count);
   1025     GET_VM_STAT(V_CACHE_COUNT, v_cache_count);
   1026     GET_VM_STAT(V_FREE_COUNT, v_free_count);
   1027     GET_VM_STAT(V_SWAPPGSIN, v_swappgsin);
   1028     GET_VM_STAT(V_SWAPPGSOUT, v_swappgsout);
   1029 }
   1030 
   1031 void
   1032 get_system_info(struct system_info *si)
   1033 
   1034 {
   1035     long total;
   1036     struct timeval thistime;
   1037     struct timeval timediff;
   1038 
   1039     /* timestamp and time difference */
   1040     gettimeofday(&thistime, 0);
   1041     timersub(&thistime, &lasttime, &timediff);
   1042     elapsed_time = timediff.tv_sec * 1000000 + timediff.tv_usec;
   1043     elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
   1044 
   1045     /* get the load averages */
   1046     if (getloadavg(si->load_avg, NUM_AVERAGES) == -1)
   1047     {
   1048 	/* failed: fill in with zeroes */
   1049 	(void) memset(si->load_avg, 0, sizeof(si->load_avg));
   1050     }
   1051 
   1052     /* get the cp_time array */
   1053     (void)get_sysctl(K_CP_TIME, &cp_time, sizeof(cp_time));
   1054 
   1055     /* convert cp_time counts to percentages */
   1056     total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
   1057 
   1058     /* sum memory & swap statistics */
   1059     {
   1060 	struct vmmeter sum;
   1061 	static unsigned int swap_delay = 0;
   1062 	static long long swapavail = 0;
   1063 	static long long swapfree = 0;
   1064 	static int bufspace = 0;
   1065 
   1066 	get_vm_sum(&sum);
   1067 
   1068 	/* get bufspace */
   1069 	bufspace = 0;
   1070 	(void) get_sysctl(VFS_BUFSPACE, &bufspace, sizeof(bufspace));
   1071 
   1072 	/* kernel stats */
   1073 	dprintf("kernel: swtch %d, trap %d, intr %d, soft %d, vforks %d\n",
   1074 		sum.v_swtch, sum.v_trap, sum.v_intr, sum.v_soft, sum.v_vforks);
   1075 	kernel_stats[0] = per_second(sum.v_swtch - ctxsws, elapsed_msecs);
   1076 	kernel_stats[1] = per_second(sum.v_trap - traps, elapsed_msecs);
   1077 	kernel_stats[2] = per_second(sum.v_intr - intrs, elapsed_msecs);
   1078 	kernel_stats[3] = per_second(sum.v_soft - softs, elapsed_msecs);
   1079 	kernel_stats[4] = per_second(sum.v_vforks + sum.v_forks +
   1080 				     sum.v_rforks - forks, elapsed_msecs);
   1081 	kernel_stats[5] = per_second(sum.v_vm_faults - pfaults, elapsed_msecs);
   1082 	kernel_stats[6] = per_second(sum.v_swapin + sum.v_vnodein - pagein, elapsed_msecs);
   1083 	kernel_stats[7] = per_second(sum.v_swapout + sum.v_vnodeout - pageout, elapsed_msecs);
   1084 	kernel_stats[8] = per_second(sum.v_tfree - tfreed, elapsed_msecs);
   1085 	ctxsws = sum.v_swtch;
   1086 	traps = sum.v_trap;
   1087 	intrs = sum.v_intr;
   1088 	softs = sum.v_soft;
   1089 	forks = (u_int64_t)sum.v_vforks + sum.v_forks + sum.v_rforks;
   1090 	pfaults = sum.v_vm_faults;
   1091 	pagein = sum.v_swapin + sum.v_vnodein;
   1092 	pageout = sum.v_swapout + sum.v_vnodeout;
   1093 	tfreed = sum.v_tfree;
   1094 
   1095 	/* convert memory stats to Kbytes */
   1096 	memory_stats[0] = pagetok(sum.v_active_count);
   1097 	memory_stats[1] = pagetok(sum.v_inactive_count);
   1098 	memory_stats[2] = pagetok(sum.v_wire_count);
   1099 	memory_stats[3] = pagetok(sum.v_cache_count);
   1100 	memory_stats[4] = bufspace / 1024;
   1101 	memory_stats[5] = pagetok(sum.v_free_count);
   1102 	memory_stats[6] = -1;
   1103 
   1104 	/* first interval */
   1105         if (swappgsin < 0)
   1106 	{
   1107 	    swap_stats[4] = 0;
   1108 	    swap_stats[5] = 0;
   1109 	}
   1110 
   1111 	/* compute differences between old and new swap statistic */
   1112 	else
   1113 	{
   1114 	    swap_stats[4] = pagetok(sum.v_swappgsin - swappgsin);
   1115 	    swap_stats[5] = pagetok(sum.v_swappgsout - swappgsout);
   1116 	}
   1117 
   1118         swappgsin = sum.v_swappgsin;
   1119 	swappgsout = sum.v_swappgsout;
   1120 
   1121 	/* call CPU heavy swap_getdata() only for changes */
   1122         if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0)
   1123 	{
   1124 	    swap_stats[3] = swap_getdata(&swapavail, &swapfree);
   1125 	    swap_stats[0] = swapavail;
   1126 	    swap_stats[1] = swapavail - swapfree;
   1127 	    swap_stats[2] = swapfree;
   1128 	}
   1129         swap_delay = 1;
   1130 	swap_stats[6] = -1;
   1131     }
   1132 
   1133     /* set arrays and strings */
   1134     si->cpustates = cpu_states;
   1135     si->kernel = kernel_stats;
   1136     si->memory = memory_stats;
   1137     si->swap = swap_stats;
   1138 
   1139     si->last_pid = -1;
   1140 
   1141     lasttime = thistime;
   1142 }
   1143 
   1144 caddr_t
   1145 get_process_info(struct system_info *si,
   1146 			 struct process_select *sel,
   1147 			 int compare_index)
   1148 
   1149 {
   1150     int i;
   1151     int total_procs;
   1152     int active_procs;
   1153     struct kinfo_proc **prefp;
   1154     struct kinfo_proc *pp;
   1155     struct kinfo_proc *prev_pp = NULL;
   1156     struct save_proc *savep;
   1157     long proc_io;
   1158     pid_t pid;
   1159     size_t size;
   1160     int nproc;
   1161 
   1162     /* these are copied out of sel for speed */
   1163     int show_idle;
   1164     int show_self;
   1165     int show_system;
   1166     int show_uid;
   1167     char *show_command;
   1168 
   1169     /* get proc table size and give it a boost */
   1170     nproc = (int)get_sysctlsize(K_PROC) / sizeof(struct kinfo_proc);
   1171     nproc += nproc >> 4;
   1172     size = nproc * sizeof(struct kinfo_proc);
   1173     dprintf("get_process_info: nproc %d, psize %d, size %d\n", nproc, psize, size);
   1174 
   1175     /* make sure we have enough space allocated */
   1176     if (nproc > psize)
   1177     {
   1178 	/* reallocate both pbase and pref */
   1179 	pbase = (struct kinfo_proc *)realloc(pbase, size);
   1180 	pref  = (struct kinfo_proc **)realloc(pref,
   1181 		    sizeof(struct kinfo_proc *) * nproc);
   1182 	psize = nproc;
   1183     }
   1184 
   1185     /* make sure we got the space we asked for */
   1186     if (pref == NULL || pbase == NULL)
   1187     {
   1188 	/* abandon all hope */
   1189 	message_error(" Out of memory!");
   1190 	nproc = psize = 0;
   1191 	si->p_total = 0;
   1192 	si->p_active = 0;
   1193 	return NULL;
   1194     }
   1195 
   1196     /* get all process information (threads, too) */
   1197     if (size > 0)
   1198     {
   1199 	nproc = get_sysctl(K_PROC, pbase, size);
   1200 	if (nproc == -1)
   1201 	{
   1202 	    nproc = 0;
   1203 	}
   1204 	else
   1205 	{
   1206 	    nproc /= sizeof(struct kinfo_proc);
   1207 	}
   1208     }
   1209 
   1210     /* get a pointer to the states summary array */
   1211     si->procstates = process_states;
   1212 
   1213     /* set up flags which define what we are going to select */
   1214     show_idle = sel->idle;
   1215     show_self = 0;
   1216     show_system = sel->system;
   1217     show_uid = sel->uid != -1;
   1218     show_fullcmd = sel->fullcmd;
   1219     show_command = sel->command;
   1220     show_usernames = sel->usernames;
   1221     display_mode = sel->mode;
   1222 #ifdef HAS_SHOWTHREADS
   1223     show_threads = sel->threads;
   1224 #endif
   1225 
   1226     /* count up process states and get pointers to interesting procs */
   1227     total_procs = 0;
   1228     active_procs = 0;
   1229     total_io = 0;
   1230     memset((char *)process_states, 0, sizeof(process_states));
   1231     prefp = pref;
   1232     for (pp = pbase, i = 0; i < nproc; pp++, i++)
   1233     {
   1234 	/*
   1235 	 *  Place pointers to each valid proc structure in pref[].
   1236 	 *  Process slots that are actually in use have a non-zero
   1237 	 *  status field.  Processes with P_SYSTEM set are system
   1238 	 *  processes---these get ignored unless show_sysprocs is set.
   1239 	 */
   1240 	pid = PP(pp, pid);
   1241 	if (PP(pp, stat) != 0)
   1242 	{
   1243 #ifdef HAS_SHOWTHREADS
   1244 	    int is_thread;
   1245 	    lwpid_t tid;
   1246 
   1247 	    /* get thread id */
   1248 	    tid = PP(pp, tid);
   1249 
   1250 	    /* is this just a thread? */
   1251 	    is_thread = (prev_pp != NULL && PP(prev_pp, pid) == pid);
   1252 
   1253 	    /* count this process and its state */
   1254 	    /* only count threads if we are showing them */
   1255 	    if (show_threads || !is_thread)
   1256 	    {
   1257 		total_procs++;
   1258 		process_states[(unsigned char) PP(pp, stat)]++;
   1259 	    }
   1260 
   1261 	    /* grab old data from hash */
   1262 	    if ((savep = hash_lookup_lwpid(procs, tid)) != NULL)
   1263 	    {
   1264 		/* verify that this is not a new or different thread */
   1265 		/* (freebsd reuses thread ids fairly quickly) */
   1266 		/* pids must match and time can't have gone backwards */
   1267 		if (pid != savep->sp_pid || PP(pp, runtime) < savep->sp_runtime)
   1268 		{
   1269 		    /* not the same thread -- reuse the save_proc structure */
   1270 		    memset(savep, 0, sizeof(struct save_proc));
   1271 		    savep->sp_pid = pid;
   1272 		}
   1273 	    }
   1274 	    else
   1275 	    {
   1276 		/* havent seen this one before */
   1277 		savep = (struct save_proc *)calloc(1, sizeof(struct save_proc));
   1278 		savep->sp_pid = pid;
   1279 		hash_add_lwpid(procs, tid, savep);
   1280 	    }
   1281 
   1282 #else /* !HAS_SHOWTHREADS */
   1283 	    total_procs++;
   1284 	    process_states[(unsigned char) PP(pp, stat)]++;
   1285 
   1286 	    /* grab old data from hash */
   1287 	    if ((savep = hash_lookup_pid(procs, pid)) == NULL)
   1288 	    {
   1289 		/* havent seen this one before */
   1290 		savep = (struct save_proc *)calloc(1, sizeof(struct save_proc));
   1291 		savep->sp_pid = pid;
   1292 		hash_add_pid(procs, pid, savep);
   1293 	    }
   1294 #endif
   1295 
   1296 	    /* save the pointer to the sp struct */
   1297 	    SPPTR(pp) = (void *)savep;
   1298 
   1299 	    /* calculate %cpu */
   1300 	    PPCPU(pp) = ((PP(pp, runtime) - savep->sp_runtime) * 10000) /
   1301 		elapsed_time;
   1302 	    dprintf("%d (%d): runtime %lld, saved_pid %d, saved_runtime %lld, elapsed_time %d, ppcpu %d\n",
   1303 		    pid, PP(pp, tid), PP(pp, runtime), savep->sp_pid, savep->sp_runtime,
   1304 		    elapsed_time, PPCPU(pp));
   1305 
   1306 	    /* calculate io differences */
   1307 	    proc_io = 0;
   1308 	    savep->sp_vcsw = (RP(pp, nvcsw) - savep->sp_old_nvcsw);
   1309 	    savep->sp_ivcsw = (RP(pp, nivcsw) - savep->sp_old_nivcsw);
   1310 	    proc_io += (savep->sp_inblock = (RP(pp, inblock) - savep->sp_old_inblock));
   1311 	    proc_io += (savep->sp_oublock = (RP(pp, oublock) - savep->sp_old_oublock));
   1312 	    proc_io += (savep->sp_majflt = (RP(pp, majflt) - savep->sp_old_majflt));
   1313 	    total_io += proc_io;
   1314 	    savep->sp_totalio = proc_io;
   1315 
   1316 	    /* save data for next time */
   1317 	    savep->sp_runtime = PP(pp, runtime);
   1318 	    savep->sp_old_nvcsw = RP(pp, nvcsw);
   1319 	    savep->sp_old_nivcsw = RP(pp, nivcsw);
   1320 	    savep->sp_old_inblock = RP(pp, inblock);
   1321 	    savep->sp_old_oublock = RP(pp, oublock);
   1322 	    savep->sp_old_majflt = RP(pp, majflt);
   1323 
   1324 	    /* is this one selected for viewing? */
   1325 	    if ((PP(pp, stat) != SZOMB) &&
   1326 		(show_system || ((PP(pp, flag) & P_SYSTEM) == 0)) &&
   1327 		(show_idle || (PP(pp, pctcpu) != 0) ||
   1328 		 (PP(pp, stat) == SRUN)) &&
   1329 		(!show_uid || PRUID(pp) == (uid_t)sel->uid) &&
   1330 		(show_command == NULL ||
   1331 		 strcasestr(PP(pp, comm), show_command) != NULL))
   1332 	    {
   1333 #ifdef HAS_SHOWTHREADS
   1334 		/* yes, but make sure it isn't just a thread */
   1335 		if (show_threads || !is_thread)
   1336 		{
   1337 		    /* we will be showing this thread */
   1338 		    *prefp++ = pp;
   1339 		    active_procs++;
   1340 		}
   1341 		else
   1342 		{
   1343 		    /* we will not be showing this thread, but we need to roll
   1344 		       up its cpu usage in to its process */
   1345 		    PP(prev_pp, pctcpu) += PP(pp, pctcpu);
   1346 		}
   1347 #else /* !HAS_SHOWTHREADS */
   1348 		/* we will be showing this process */
   1349 		*prefp++ = pp;
   1350 		active_procs++;
   1351 #endif
   1352 	    }
   1353 	    prev_pp = pp;
   1354 	}
   1355     }
   1356 
   1357     dprintf("total_io: %d\n", total_io);
   1358     if (total_io == 0) total_io = 1;
   1359 
   1360     /* if requested, sort the "interesting" processes */
   1361     if (active_procs > 1)
   1362     {
   1363 	qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *),
   1364 	      proc_compares[compare_index]);
   1365     }
   1366 
   1367     /* remember active and total counts */
   1368     si->p_total = total_procs;
   1369     si->p_active = pref_len = active_procs;
   1370 
   1371     /* pass back a handle */
   1372     handle.next_proc = pref;
   1373     handle.remaining = active_procs;
   1374     return((caddr_t)&handle);
   1375 }
   1376 
   1377 static char p_header[MAX_COLS];
   1378 
   1379 char *
   1380 format_process_header(struct process_select *sel, caddr_t handle, int count)
   1381 
   1382 {
   1383     int cols;
   1384     int n;
   1385     int w;
   1386     char *p;
   1387     int *fi;
   1388     struct kinfo_proc **kip;
   1389     struct proc_field *fp;
   1390 
   1391     /* check for null handle */
   1392     if (handle == NULL)
   1393     {
   1394 	return("");
   1395     }
   1396 
   1397     /* remember how many columns there are on the display */
   1398     cols = display_columns();
   1399 
   1400     /* mode & threads dictate format */
   1401     fi = display_fields =
   1402 	sel->mode == 0 ?
   1403 	(sel->threads == 0 ? mode0_display : mode0thr_display) :
   1404 	mode1_display;
   1405 
   1406     /* set username field correctly */
   1407     if (!sel->usernames)
   1408     {
   1409 	/* display uids */
   1410 	field_subst(fi, FIELD_USERNAME, FIELD_UID);
   1411     }
   1412     else
   1413     {
   1414 	/* display usernames */
   1415 	field_subst(fi, FIELD_UID, FIELD_USERNAME);
   1416 
   1417 	/* we also need to determine the longest username for column width */
   1418 	/* calculate namelength from first "count" processes */
   1419 	kip = ((struct handle *)handle)->next_proc;
   1420 	n = ((struct handle *)handle)->remaining;
   1421 	if (n > count)
   1422 	    n = count;
   1423 	namelength = 0;
   1424 	while (n-- > 0)
   1425 	{
   1426 	    w = strlen(username(PRUID(*kip)));
   1427 	    if (w > namelength) namelength = w;
   1428 	    kip++;
   1429 	}
   1430 	dprintf("format_process_header: namelength %d\n", namelength);
   1431 
   1432 	/* place it in bounds */
   1433 	if (namelength < 8)
   1434 	{
   1435 	    namelength = 8;
   1436 	}
   1437 
   1438 	/* set the column width */
   1439 	proc_field[FIELD_USERNAME].width = username_length = namelength;
   1440     }
   1441 
   1442     /* walk thru fields and construct header */
   1443     /* are we worried about overflow??? */
   1444     p = p_header;
   1445     while (*fi != -1)
   1446     {
   1447 	fp = &(proc_field[*fi++]);
   1448 	if (fp->min_screenwidth <= cols)
   1449 	{
   1450 	    p += sprintf(p, fp->rjust ? "%*s" : "%-*s", fp->width, fp->name);
   1451 	    *p++ = ' ';
   1452 	}
   1453     }
   1454     *--p = '\0';
   1455 
   1456     return p_header;
   1457 }
   1458 
   1459 static char fmt[MAX_COLS];		/* static area where result is built */
   1460 
   1461 char *
   1462 format_next_process(caddr_t handle, char *(*get_userid)(int))
   1463 
   1464 {
   1465     struct kinfo_proc *pp;
   1466     struct handle *hp;
   1467     struct proc_field *fp;
   1468     int *fi;
   1469     int i;
   1470     int cols;
   1471     char *p;
   1472     int len;
   1473     int x;
   1474 
   1475     /* find and remember the next proc structure */
   1476     hp = (struct handle *)handle;
   1477     pp = *(hp->next_proc++);
   1478     hp->remaining--;
   1479 
   1480     /* mode & threads dictate format */
   1481     fi = display_fields;
   1482 
   1483     /* screen width is a consideration, too */
   1484     cols = display_columns();
   1485 
   1486     /* build output by field */
   1487     p = fmt;
   1488     len = MAX_COLS;
   1489     while ((i = *fi++) != -1)
   1490     {
   1491 	fp = &(proc_field[i]);
   1492 	if (len > 0 && fp->min_screenwidth <= cols)
   1493 	{
   1494 	    x = (*(fp->format))(p, len, pp);
   1495 	    if (x >= len)
   1496 	    {
   1497 		dprintf("format_next_process: formatter overflow: x %d, len %d, p %08x => %08x, fmt %08x - %08x\n",
   1498 			x, len, p, p + len, fmt, fmt + sizeof(fmt));
   1499 		p += len;
   1500 		len = 0;
   1501 	    }
   1502 	    else
   1503 	    {
   1504 		p += x;
   1505 		*p++ = ' ';
   1506 		len -= x + 1;
   1507 	    }
   1508 	}
   1509     }
   1510     *--p = '\0';
   1511 
   1512     /* return the result */
   1513     return(fmt);
   1514 }
   1515 
   1516 /* comparison routines for qsort */
   1517 
   1518 /*
   1519  *  proc_compare - comparison function for "qsort"
   1520  *	Compares the resource consumption of two processes using five
   1521  *  	distinct keys.  The keys (in descending order of importance) are:
   1522  *  	percent cpu, cpu ticks, state, resident set size, total virtual
   1523  *  	memory usage.  The process states are ordered as follows (from least
   1524  *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
   1525  *  	array declaration below maps a process state index into a number
   1526  *  	that reflects this ordering.
   1527  */
   1528 
   1529 static unsigned char sorted_state[] =
   1530 {
   1531     0,	/* not used		*/
   1532     3,	/* sleep		*/
   1533     1,	/* ABANDONED (WAIT)	*/
   1534     6,	/* run			*/
   1535     5,	/* start		*/
   1536     2,	/* zombie		*/
   1537     4	/* stop			*/
   1538 };
   1539 
   1540 
   1541 #define ORDERKEY_PCTCPU \
   1542   if (lresult = (long) PPCPU(p2) - (long) PPCPU(p1), \
   1543      (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
   1544 
   1545 #define ORDERKEY_CPTICKS \
   1546   if ((result = PP(p2, runtime) > PP(p1, runtime) ? 1 : \
   1547                 PP(p2, runtime) < PP(p1, runtime) ? -1 : 0) == 0)
   1548 
   1549 #define ORDERKEY_STATE \
   1550   if ((result = sorted_state[(unsigned char) PP(p2, stat)] - \
   1551                 sorted_state[(unsigned char) PP(p1, stat)]) == 0)
   1552 
   1553 #if OSMAJOR <= 4
   1554 #define ORDERKEY_PRIO \
   1555   if ((result = PP(p2, priority) - PP(p1, priority)) == 0)
   1556 #else
   1557 #define ORDERKEY_PRIO \
   1558   if ((result = PP(p2, pri.pri_level) - PP(p1, pri.pri_level)) == 0)
   1559 #endif
   1560 
   1561 #define ORDERKEY_RSSIZE \
   1562   if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
   1563 
   1564 #define ORDERKEY_MEM \
   1565   if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
   1566 
   1567 #define ORDERKEY_IO \
   1568   if ( (result = SP(p2, totalio) - SP(p1, totalio)) == 0)
   1569 
   1570 #define ORDERKEY_PID \
   1571   if ( (result = PP(p1, pid) - PP(p2, pid)) == 0)
   1572 
   1573 /* compare_cpu - the comparison function for sorting by cpu percentage */
   1574 
   1575 int
   1576 proc_compare(struct proc **pp1, struct proc **pp2)
   1577 
   1578 {
   1579     struct kinfo_proc *p1;
   1580     struct kinfo_proc *p2;
   1581     int result;
   1582     pctcpu lresult;
   1583 
   1584     /* remove one level of indirection */
   1585     p1 = *(struct kinfo_proc **) pp1;
   1586     p2 = *(struct kinfo_proc **) pp2;
   1587 
   1588     ORDERKEY_PCTCPU
   1589     ORDERKEY_CPTICKS
   1590     ORDERKEY_STATE
   1591     ORDERKEY_PRIO
   1592     ORDERKEY_RSSIZE
   1593     ORDERKEY_MEM
   1594     ;
   1595 
   1596     return(result);
   1597 }
   1598 
   1599 /* compare_size - the comparison function for sorting by total memory usage */
   1600 
   1601 int
   1602 compare_size(struct proc **pp1, struct proc **pp2)
   1603 
   1604 {
   1605     struct kinfo_proc *p1;
   1606     struct kinfo_proc *p2;
   1607     int result;
   1608     pctcpu lresult;
   1609 
   1610     /* remove one level of indirection */
   1611     p1 = *(struct kinfo_proc **) pp1;
   1612     p2 = *(struct kinfo_proc **) pp2;
   1613 
   1614     ORDERKEY_MEM
   1615     ORDERKEY_RSSIZE
   1616     ORDERKEY_PCTCPU
   1617     ORDERKEY_CPTICKS
   1618     ORDERKEY_STATE
   1619     ORDERKEY_PRIO
   1620     ;
   1621 
   1622     return(result);
   1623 }
   1624 
   1625 /* compare_res - the comparison function for sorting by resident set size */
   1626 
   1627 int
   1628 compare_res(struct proc **pp1, struct proc **pp2)
   1629 
   1630 {
   1631     struct kinfo_proc *p1;
   1632     struct kinfo_proc *p2;
   1633     int result;
   1634     pctcpu lresult;
   1635 
   1636     /* remove one level of indirection */
   1637     p1 = *(struct kinfo_proc **) pp1;
   1638     p2 = *(struct kinfo_proc **) pp2;
   1639 
   1640     ORDERKEY_RSSIZE
   1641     ORDERKEY_MEM
   1642     ORDERKEY_PCTCPU
   1643     ORDERKEY_CPTICKS
   1644     ORDERKEY_STATE
   1645     ORDERKEY_PRIO
   1646     ;
   1647 
   1648     return(result);
   1649 }
   1650 
   1651 /* compare_time - the comparison function for sorting by total cpu time */
   1652 
   1653 int
   1654 compare_time(struct proc **pp1, struct proc **pp2)
   1655 
   1656 {
   1657     struct kinfo_proc *p1;
   1658     struct kinfo_proc *p2;
   1659     int result;
   1660     pctcpu lresult;
   1661 
   1662     /* remove one level of indirection */
   1663     p1 = *(struct kinfo_proc **) pp1;
   1664     p2 = *(struct kinfo_proc **) pp2;
   1665 
   1666     ORDERKEY_CPTICKS
   1667     ORDERKEY_PCTCPU
   1668     ORDERKEY_STATE
   1669     ORDERKEY_PRIO
   1670     ORDERKEY_RSSIZE
   1671     ORDERKEY_MEM
   1672     ;
   1673 
   1674       return(result);
   1675   }
   1676 
   1677 /* compare_prio - the comparison function for sorting by priority */
   1678 
   1679 int
   1680 compare_prio(struct proc **pp1, struct proc **pp2)
   1681 
   1682 {
   1683     struct kinfo_proc *p1;
   1684     struct kinfo_proc *p2;
   1685     int result;
   1686     pctcpu lresult;
   1687 
   1688     /* remove one level of indirection */
   1689     p1 = *(struct kinfo_proc **) pp1;
   1690     p2 = *(struct kinfo_proc **) pp2;
   1691 
   1692     ORDERKEY_PRIO
   1693     ORDERKEY_CPTICKS
   1694     ORDERKEY_PCTCPU
   1695     ORDERKEY_STATE
   1696     ORDERKEY_RSSIZE
   1697     ORDERKEY_MEM
   1698     ;
   1699 
   1700     return(result);
   1701 }
   1702 
   1703 /* compare_io - the comparison function for sorting by io count */
   1704 
   1705 int
   1706 compare_io(struct proc **pp1, struct proc **pp2)
   1707 
   1708 {
   1709     struct kinfo_proc *p1;
   1710     struct kinfo_proc *p2;
   1711     int result;
   1712     pctcpu lresult;
   1713 
   1714     /* remove one level of indirection */
   1715     p1 = *(struct kinfo_proc **) pp1;
   1716     p2 = *(struct kinfo_proc **) pp2;
   1717 
   1718     ORDERKEY_IO
   1719     ORDERKEY_PCTCPU
   1720     ORDERKEY_CPTICKS
   1721     ORDERKEY_STATE
   1722     ORDERKEY_PRIO
   1723     ORDERKEY_RSSIZE
   1724     ORDERKEY_MEM
   1725     ;
   1726 
   1727     return(result);
   1728 }
   1729 
   1730 /* compare_pid - the comparison function for sorting by process id */
   1731 
   1732 int
   1733 compare_pid(struct proc **pp1, struct proc **pp2)
   1734 
   1735 {
   1736     struct kinfo_proc *p1;
   1737     struct kinfo_proc *p2;
   1738     int result;
   1739 
   1740     /* remove one level of indirection */
   1741     p1 = *(struct kinfo_proc **) pp1;
   1742     p2 = *(struct kinfo_proc **) pp2;
   1743 
   1744     ORDERKEY_PID
   1745     ;
   1746 
   1747     return(result);
   1748 }
   1749 
   1750 /*
   1751  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
   1752  *		the process does not exist.
   1753  *		It is EXTREMLY IMPORTANT that this function work correctly.
   1754  *		If top runs setuid root (as in SVR4), then this function
   1755  *		is the only thing that stands in the way of a serious
   1756  *		security problem.  It validates requests for the "kill"
   1757  *		and "renice" commands.
   1758  */
   1759 
   1760 int
   1761 proc_owner(int pid)
   1762 
   1763 {
   1764     int cnt;
   1765     struct kinfo_proc **prefp;
   1766     struct kinfo_proc *pp;
   1767 
   1768     prefp = pref;
   1769     cnt = pref_len;
   1770     while (--cnt >= 0)
   1771     {
   1772 	pp = *prefp++;
   1773 	if (PP(pp, pid) == (pid_t)pid)
   1774 	{
   1775 	    return((int)PRUID(pp));
   1776 	}
   1777     }
   1778     return(-1);
   1779 }
   1780 
   1781