Bas, Here is an untested patch but should at least give you an idea of what you need to do...
Barry deFreese On 6/3/2012 6:19 AM, Bas van den Dikkenberg wrote: > Can you help me with that don´t know how to do that > > -----Oorspronkelijk bericht----- > Van: Samuel Thibault [mailto:sthiba...@debian.org] > Verzonden: zondag 3 juni 2012 11:49 > Aan: Bas van den Dikkenberg > CC: debian-hurd@lists.debian.org > Onderwerp: Re: Build of ptop keeps failing > > Bas van den Dikkenberg, le Sun 03 Jun 2012 07:58:56 +0000, a écrit : >> The build of ptop keeps failing on hurd can some help me? >> >> See also bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=675757 > > whose important line is: > > configure: error: System type gnu unrecognized > > you need to fix configure.ac to define the "gnu" system, and then create a > machine/m_gnu.c file, most probably by copying the existing machine/m_linux.c > and dropping what doesn't work. > > Samuel > >
Index: ptop-3.6.2/configure =================================================================== --- ptop-3.6.2.orig/configure 2012-06-03 08:55:31.000000000 +0000 +++ ptop-3.6.2/configure 2012-06-03 08:55:54.000000000 +0000 @@ -6633,6 +6633,7 @@ sysv4*) MODULE=svr4;; sysv5*) MODULE=svr5;; darwin*) MODULE=macosx;; + gnu*) MODULE=gnu;; *) echo "none" echo "Configure doesn't recognize this system and doesn't know" echo "what module to assign to it. Help the cause and run the" Index: ptop-3.6.2/machine/m_gnu.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ptop-3.6.2/machine/m_gnu.c 2012-06-03 08:55:55.000000000 +0000 @@ -0,0 +1,1132 @@ +/* + * pg_top - a top PostgreSQL users display for Unix + * + * SYNOPSIS: Linux 1.2.x, 1.3.x, 2.x, using the /proc filesystem + * + * DESCRIPTION: + * This is the machine-dependent module for Linux 1.2.x, 1.3.x or 2.x. + * + * LIBS: + * + * CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER + * + * TERMCAP: -lcurses + * + * AUTHOR: Richard Henderson <r...@tamu.edu> + * Order support added by Alexey Klimkin <k...@klon.tme.mcst.ru> + * Ported to 2.4 by William LeFebvre + */ + +#include "config.h" + +#include <sys/types.h> +#include <time.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <dirent.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/vfs.h> + +#include <sys/param.h> /* for HZ */ + +#if 0 +#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */ +#else +#define PROC_SUPER_MAGIC 0x9fa0 +#endif + +#include "machine.h" +#include "utils.h" + +#define PROCFS "/proc" +extern char *myname; + +/*=PROCESS INFORMATION==================================================*/ + +struct top_proc +{ + pid_t pid; + uid_t uid; + char *name; + int pri, + nice; + unsigned long size, + rss; /* in k */ + int state; + unsigned long time; + unsigned long start_time; + double pcpu, + wcpu; + struct top_proc *next; +}; + + +/*=STATE IDENT STRINGS==================================================*/ + +#define NPROCSTATES 7 +static char *state_abbrev[NPROCSTATES + 1] = +{ + "", "run", "sleep", "disk", "zomb", "stop", "swap", + NULL +}; + +static char *procstatenames[NPROCSTATES + 1] = +{ + "", " running, ", " sleeping, ", " uninterruptable, ", + " zombie, ", " stopped, ", " swapping, ", + NULL +}; + +#define NCPUSTATES 5 +static char *cpustatenames[NCPUSTATES + 1] = +{ + "user", "nice", "system", "idle", "iowait", + NULL +}; +static int show_iowait = 0; + +#define MEMUSED 0 +#define MEMFREE 1 +#define MEMSHARED 2 +#define MEMBUFFERS 3 +#define MEMCACHED 4 +#define NMEMSTATS 5 +static char *memorynames[NMEMSTATS + 1] = +{ + "K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached", + NULL +}; + +#define SWAPUSED 0 +#define SWAPFREE 1 +#define SWAPCACHED 2 +#define NSWAPSTATS 3 +static char *swapnames[NSWAPSTATS + 1] = +{ + "K used, ", "K free, ", "K cached", + NULL +}; + +static char fmt_header[] = +" PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; + +/* these are names given to allowed sorting orders -- first is default */ +static char *ordernames[] = {"cpu", "size", "res", "time", "command", NULL}; + +/* forward definitions for comparison functions */ +int compare_cpu(); +int compare_size(); +int compare_res(); +int compare_time(); +int compare_cmd(); + +int (*proc_compares[]) () = +{ + compare_cpu, + compare_size, + compare_res, + compare_time, + compare_cmd, + NULL +}; + +/*=SYSTEM STATE INFO====================================================*/ + +/* these are for calculating cpu state percentages */ + +static int64_t cp_time[NCPUSTATES]; +static int64_t cp_old[NCPUSTATES]; +static int64_t cp_diff[NCPUSTATES]; + +/* for calculating the exponential average */ + +static struct timeval lasttime; + +/* these are for keeping track of processes */ + +#define HASH_SIZE (1003) +#define INITIAL_ACTIVE_SIZE (256) +#define PROCBLOCK_SIZE (32) +static struct top_proc *ptable[HASH_SIZE]; +static struct top_proc **pactive; +static struct top_proc **nextactive; +static unsigned int activesize = 0; +static time_t boottime = -1; + +/* these are for passing data back to the machine independant portion */ + +static int64_t cpu_states[NCPUSTATES]; +static int process_states[NPROCSTATES]; +static long memory_stats[NMEMSTATS]; +static long swap_stats[NSWAPSTATS]; + +/* usefull macros */ +#define bytetok(x) (((x) + 512) >> 10) +#define pagetok(x) ((x) * sysconf(_SC_PAGESIZE) >> 10) +#define HASH(x) (((x) * 1686629713U) % HASH_SIZE) + +/*======================================================================*/ + +static inline char * +skip_ws(const char *p) +{ + while (isspace(*p)) + p++; + return (char *) p; +} + +static inline char * +skip_token(const char *p) +{ + while (isspace(*p)) + p++; + while (*p && !isspace(*p)) + p++; + return (char *) p; +} + +static void +xfrm_cmdline(char *p, int len) +{ + while (--len > 0) + { + if (*p == '\0') + { + *p = ' '; + } + p++; + } +} + +static void +update_procname(struct top_proc * proc, char *cmd) + +{ + printable(cmd); + + if (proc->name == NULL) + { + proc->name = strdup(cmd); + } + else if (strcmp(proc->name, cmd) != 0) + { + free(proc->name); + proc->name = strdup(cmd); + } +} + +/* + * Process structures are allocated and freed as needed. Here we + * keep big pools of them, adding more pool as needed. When a + * top_proc structure is freed, it is added to a freelist and reused. + */ + +static struct top_proc *freelist = NULL; +static struct top_proc *procblock = NULL; +static struct top_proc *procmax = NULL; + +static struct top_proc * +new_proc() +{ + struct top_proc *p; + + if (freelist) + { + p = freelist; + freelist = freelist->next; + } + else if (procblock) + { + p = procblock; + if (++procblock >= procmax) + { + procblock = NULL; + } + } + else + { + p = procblock = (struct top_proc *) calloc(PROCBLOCK_SIZE, + sizeof(struct top_proc)); + procmax = procblock++ + PROCBLOCK_SIZE; + } + + /* initialization */ + if (p->name != NULL) + { + free(p->name); + p->name = NULL; + } + + return p; +} + +static void +free_proc(struct top_proc * proc) +{ + proc->next = freelist; + freelist = proc; +} + + +int +machine_init(struct statics * statics) + +{ + /* make sure the proc filesystem is mounted */ + { + struct statfs sb; + + if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC) + { + fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n", + myname); + return -1; + } + } + + /* chdir to the proc filesystem to make things easier */ + chdir(PROCFS); + + /* a few preliminary checks */ + { + int fd; + char buff[128]; + char *p; + int cnt; + unsigned long uptime; + struct timeval tv; + + /* get a boottime */ + if ((fd = open("uptime", 0)) != -1) + { + if (read(fd, buff, sizeof(buff)) > 0) + { + uptime = strtoul(buff, &p, 10); + gettimeofday(&tv, 0); + boottime = tv.tv_sec - uptime; + } + close(fd); + } + + /* see how many states we get from stat */ + if ((fd = open("stat", 0)) != -1) + { + if (read(fd, buff, sizeof(buff)) > 0) + { + if ((p = strchr(buff, '\n')) != NULL) + { + *p = '\0'; + p = buff; + cnt = 0; + while (*p != '\0') + { + if (*p++ == ' ') + { + cnt++; + } + } + } + } + + close(fd); + } + if (cnt > 5) + { + /* we have iowait */ + show_iowait = 1; + } + } + + /* if we aren't showing iowait, then we have to tweak cpustatenames */ + if (!show_iowait) + { + cpustatenames[4] = NULL; + } + + /* fill in the statics information */ + statics->procstate_names = procstatenames; + statics->cpustate_names = cpustatenames; + statics->memory_names = memorynames; + statics->swap_names = swapnames; + statics->order_names = ordernames; + statics->boottime = boottime; + statics->flags.fullcmds = 1; + statics->flags.warmup = 1; + + /* allocate needed space */ + pactive = (struct top_proc **) malloc(sizeof(struct top_proc *) * INITIAL_ACTIVE_SIZE); + activesize = INITIAL_ACTIVE_SIZE; + + /* make sure the hash table is empty */ + memset(ptable, 0, HASH_SIZE * sizeof(struct top_proc *)); + + /* all done! */ + return 0; +} + + +void +get_system_info(struct system_info * info) + +{ + char buffer[4096 + 1]; + int fd, + len; + char *p; + + /* get load averages */ + + if ((fd = open("loadavg", O_RDONLY)) != -1) + { + if ((len = read(fd, buffer, sizeof(buffer) - 1)) > 0) + { + buffer[len] = '\0'; + info->load_avg[0] = strtod(buffer, &p); + info->load_avg[1] = strtod(p, &p); + info->load_avg[2] = strtod(p, &p); + p = skip_token(p); /* skip running/tasks */ + p = skip_ws(p); + if (*p) + { + info->last_pid = atoi(p); + } + else + { + info->last_pid = -1; + } + } + close(fd); + } + + /* get the cpu time info */ + if ((fd = open("stat", O_RDONLY)) != -1) + { + if ((len = read(fd, buffer, sizeof(buffer) - 1)) > 0) + { + buffer[len] = '\0'; + p = skip_token(buffer); /* "cpu" */ + cp_time[0] = strtoul(p, &p, 0); + cp_time[1] = strtoul(p, &p, 0); + cp_time[2] = strtoul(p, &p, 0); + cp_time[3] = strtoul(p, &p, 0); + if (show_iowait) + { + cp_time[4] = strtoul(p, &p, 0); + } + + /* convert cp_time counts to percentages */ + percentages(NCPUSTATES, cpu_states, cp_time, cp_old, cp_diff); + } + close(fd); + } + + /* get system wide memory usage */ + if ((fd = open("meminfo", O_RDONLY)) != -1) + { + char *p; + int mem = 0; + int swap = 0; + unsigned long memtotal = 0; + unsigned long memfree = 0; + unsigned long swaptotal = 0; + + if ((len = read(fd, buffer, sizeof(buffer) - 1)) > 0) + { + buffer[len] = '\0'; + p = buffer - 1; + + /* iterate thru the lines */ + while (p != NULL) + { + p++; + if (p[0] == ' ' || p[0] == '\t') + { + /* skip */ + } + else if (strncmp(p, "Mem:", 4) == 0) + { + p = skip_token(p); /* "Mem:" */ + p = skip_token(p); /* total memory */ + memory_stats[MEMUSED] = strtoul(p, &p, 10); + memory_stats[MEMFREE] = strtoul(p, &p, 10); + memory_stats[MEMSHARED] = strtoul(p, &p, 10); + memory_stats[MEMBUFFERS] = strtoul(p, &p, 10); + memory_stats[MEMCACHED] = strtoul(p, &p, 10); + memory_stats[MEMUSED] = bytetok(memory_stats[MEMUSED]); + memory_stats[MEMFREE] = bytetok(memory_stats[MEMFREE]); + memory_stats[MEMSHARED] = bytetok(memory_stats[MEMSHARED]); + memory_stats[MEMBUFFERS] = bytetok(memory_stats[MEMBUFFERS]); + memory_stats[MEMCACHED] = bytetok(memory_stats[MEMCACHED]); + mem = 1; + } + else if (strncmp(p, "Swap:", 5) == 0) + { + p = skip_token(p); /* "Swap:" */ + p = skip_token(p); /* total swap */ + swap_stats[SWAPUSED] = strtoul(p, &p, 10); + swap_stats[SWAPFREE] = strtoul(p, &p, 10); + swap_stats[SWAPUSED] = bytetok(swap_stats[SWAPUSED]); + swap_stats[SWAPFREE] = bytetok(swap_stats[SWAPFREE]); + swap = 1; + } + else if (!mem && strncmp(p, "MemTotal:", 9) == 0) + { + p = skip_token(p); + memtotal = strtoul(p, &p, 10); + } + else if (!mem && memtotal > 0 && strncmp(p, "MemFree:", 8) == 0) + { + p = skip_token(p); + memfree = strtoul(p, &p, 10); + memory_stats[MEMUSED] = memtotal - memfree; + memory_stats[MEMFREE] = memfree; + } + else if (!mem && strncmp(p, "MemShared:", 10) == 0) + { + p = skip_token(p); + memory_stats[MEMSHARED] = strtoul(p, &p, 10); + } + else if (!mem && strncmp(p, "Buffers:", 8) == 0) + { + p = skip_token(p); + memory_stats[MEMBUFFERS] = strtoul(p, &p, 10); + } + else if (!mem && strncmp(p, "Cached:", 7) == 0) + { + p = skip_token(p); + memory_stats[MEMCACHED] = strtoul(p, &p, 10); + } + else if (!swap && strncmp(p, "SwapTotal:", 10) == 0) + { + p = skip_token(p); + swaptotal = strtoul(p, &p, 10); + } + else if (!swap && swaptotal > 0 && strncmp(p, "SwapFree:", 9) == 0) + { + p = skip_token(p); + memfree = strtoul(p, &p, 10); + swap_stats[SWAPUSED] = swaptotal - memfree; + swap_stats[SWAPFREE] = memfree; + } + else if (!mem && strncmp(p, "SwapCached:", 11) == 0) + { + p = skip_token(p); + swap_stats[SWAPCACHED] = strtoul(p, &p, 10); + } + + /* move to the next line */ + p = strchr(p, '\n'); + } + } + close(fd); + } + + /* set arrays and strings */ + info->cpustates = cpu_states; + info->memory = memory_stats; + info->swap = swap_stats; +} + + +static void +read_one_proc_stat(pid_t pid, struct top_proc * proc, struct process_select * sel) +{ + char buffer[4096], + *p, + *q; + int fd, + len; + int fullcmd; + + /* if anything goes wrong, we return with proc->state == 0 */ + proc->state = 0; + + /* full cmd handling */ + fullcmd = sel->fullcmd; + if (fullcmd) + { + sprintf(buffer, "%d/cmdline", pid); + if ((fd = open(buffer, O_RDONLY)) != -1) + { + /* read command line data */ + /* (theres no sense in reading more than we can fit) */ + if ((len = read(fd, buffer, MAX_COLS)) > 1) + { + buffer[len] = '\0'; + xfrm_cmdline(buffer, len); + update_procname(proc, buffer); + } + else + { + fullcmd = 0; + } + close(fd); + } + else + { + fullcmd = 0; + } + } + + /* grab the proc stat info in one go */ + sprintf(buffer, "%d/stat", pid); + + fd = open(buffer, O_RDONLY); + len = read(fd, buffer, sizeof(buffer) - 1); + close(fd); + + buffer[len] = '\0'; + + proc->uid = (uid_t) proc_owner((int) pid); + + /* parse out the status, described in 'man proc' */ + + /* skip pid and locate command, which is in parentheses */ + if ((p = strchr(buffer, '(')) == NULL) + { + return; + } + if ((q = strrchr(++p, ')')) == NULL) + { + return; + } + + /* set the procname */ + *q = '\0'; + if (!fullcmd) + { + update_procname(proc, p); + } + + /* scan the rest of the line */ + p = q + 1; + p = skip_ws(p); + switch (*p++) /* state */ + { + case 'R': + proc->state = 1; + break; + case 'S': + proc->state = 2; + break; + case 'D': + proc->state = 3; + break; + case 'Z': + proc->state = 4; + break; + case 'T': + proc->state = 5; + break; + case 'W': + proc->state = 6; + break; + case '\0': + return; + } + + p = skip_token(p); /* skip ppid */ + p = skip_token(p); /* skip pgrp */ + p = skip_token(p); /* skip session */ + p = skip_token(p); /* skip tty nr */ + p = skip_token(p); /* skip tty pgrp */ + p = skip_token(p); /* skip flags */ + p = skip_token(p); /* skip min flt */ + p = skip_token(p); /* skip cmin flt */ + p = skip_token(p); /* skip maj flt */ + p = skip_token(p); /* skip cmaj flt */ + + proc->time = strtoul(p, &p, 10); /* utime */ + proc->time += strtoul(p, &p, 10); /* stime */ + + p = skip_token(p); /* skip cutime */ + p = skip_token(p); /* skip cstime */ + + proc->pri = strtol(p, &p, 10); /* priority */ + proc->nice = strtol(p, &p, 10); /* nice */ + p = skip_token(p); /* skip num_threads */ + p = skip_token(p); /* skip itrealvalue, 0 */ + proc->start_time = strtoul(p, &p, 10); /* start_time */ + proc->size = bytetok(strtoul(p, &p, 10)); /* vsize */ + proc->rss = pagetok(strtoul(p, &p, 10)); /* rss */ + + +#if 0 + /* for the record, here are the rest of the fields */ + p = skip_token(p); /* skip rlim */ + p = skip_token(p); /* skip start_code */ + p = skip_token(p); /* skip end_code */ + p = skip_token(p); /* skip start_stack */ + p = skip_token(p); /* skip esp */ + p = skip_token(p); /* skip eip */ + p = skip_token(p); /* skip signal */ + p = skip_token(p); /* skip sigblocked */ + p = skip_token(p); /* skip sigignore */ + p = skip_token(p); /* skip sigcatch */ + p = skip_token(p); /* skip wchan */ + p = skip_token(p); /* skip nswap, not maintained */ + p = skip_token(p); /* exit signal */ + p = skip_token(p); /* processor */ + p = skip_token(p); /* rt_priority */ + p = skip_token(p); /* policy */ + p = skip_token(p); /* delayacct_blkio_ticks */ +#endif + +} + + +caddr_t +get_process_info(struct system_info * si, + struct process_select * sel, + int compare_index, char *conninfo) +{ + struct timeval thistime; + double timediff, + alpha, + beta; + struct top_proc *proc; + pid_t pid; + unsigned long now; + unsigned long elapsed; + int i; + + /* calculate the time difference since our last check */ + gettimeofday(&thistime, 0); + if (lasttime.tv_sec) + { + timediff = ((thistime.tv_sec - lasttime.tv_sec) + + (thistime.tv_usec - lasttime.tv_usec) * 1e-6); + } + else + { + timediff = 0; + } + lasttime = thistime; + + /* round current time to a second */ + now = (unsigned long) thistime.tv_sec; + if (thistime.tv_usec >= 500000) + { + now++; + } + + /* calculate constants for the exponental average */ + if (timediff > 0.0 && timediff < 30.0) + { + alpha = 0.5 * (timediff / 30.0); + beta = 1.0 - alpha; + } + else + { + alpha = beta = 0.5; + } + timediff *= HZ; /* convert to ticks */ + + /* mark all hash table entries as not seen */ + for (i = 0; i < HASH_SIZE; ++i) + { + for (proc = ptable[i]; proc; proc = proc->next) + { + proc->state = 0; + } + } + + /* read the process information */ + { + int total_procs = 0; + struct top_proc **active; + + int show_idle = sel->idle; + int show_uid = sel->uid != -1; + + int i; + int rows; + PGconn *pgconn; + PGresult *pgresult = NULL; + + memset(process_states, 0, sizeof(process_states)); + + pgconn = connect_to_db(conninfo); + if (pgconn != NULL) + { + pgresult = PQexec(pgconn, QUERY_PROCESSES); + rows = PQntuples(pgresult); + } + else + { + rows = 0; + } + for (i = 0; i < rows; i++) + { + char *procpid = PQgetvalue(pgresult, i, 0); + struct top_proc *pp; + unsigned long otime; + + pid = atoi(procpid); + + /* look up hash table entry */ + proc = pp = ptable[HASH(pid)]; + while (proc && proc->pid != pid) + { + proc = proc->next; + } + + /* if we came up empty, create a new entry */ + if (proc == NULL) + { + proc = new_proc(); + proc->pid = pid; + proc->next = pp; + ptable[HASH(pid)] = proc; + proc->time = 0; + proc->wcpu = 0; + } + + otime = proc->time; + + read_one_proc_stat(pid, proc, sel); + + if (proc->state == 0) + continue; + + total_procs++; + process_states[proc->state]++; + + if (timediff > 0.0) + { + if ((proc->pcpu = (proc->time - otime) / timediff) < 0.0001) + { + proc->pcpu = 0; + } + proc->wcpu = proc->pcpu * alpha + proc->wcpu * beta; + } + else if ((elapsed = (now - boottime) * HZ - proc->start_time) > 0) + { + /* + * What's with the noop statement? if ((proc->pcpu = + * (double)proc->time / (double)elapsed) < 0.0001) { + * proc->pcpu; } + */ + proc->wcpu = proc->pcpu; + } + else + { + proc->wcpu = proc->pcpu = 0.0; + } + } + if (pgresult != NULL) + PQclear(pgresult); + PQfinish(pgconn); + + /* make sure we have enough slots for the active procs */ + if (activesize < total_procs) + { + pactive = (struct top_proc **) realloc(pactive, + sizeof(struct top_proc *) * total_procs); + activesize = total_procs; + } + + /* set up the active procs and flush dead entries */ + active = pactive; + for (i = 0; i < HASH_SIZE; i++) + { + struct top_proc *last; + struct top_proc *ptmp; + + last = NULL; + proc = ptable[i]; + while (proc != NULL) + { + if (proc->state == 0) + { + ptmp = proc; + if (last) + { + proc = last->next = proc->next; + } + else + { + proc = ptable[i] = proc->next; + } + free_proc(ptmp); + } + else + { + if ((show_idle || proc->state == 1 || proc->pcpu) && + (!show_uid || proc->uid == sel->uid)) + { + *active++ = proc; + last = proc; + } + proc = proc->next; + } + } + } + + si->p_active = active - pactive; + si->p_total = total_procs; + si->procstates = process_states; + } + + /* if requested, sort the "active" procs */ + if (si->p_active) + qsort(pactive, si->p_active, sizeof(struct top_proc *), + proc_compares[compare_index]); + + /* don't even pretend that the return value thing here isn't bogus */ + nextactive = pactive; + return (caddr_t) 0; +} + + +char * +format_header(char *uname_field) + +{ + int uname_len = strlen(uname_field); + + if (uname_len > 8) + uname_len = 8; + + memcpy(strchr(fmt_header, 'X'), uname_field, uname_len); + + return fmt_header; +} + + +char * +format_next_process(caddr_t handle, char *(*get_userid) (uid_t)) +{ + static char fmt[MAX_COLS]; /* static area where result is built */ + struct top_proc *p = *nextactive++; + + snprintf(fmt, sizeof(fmt), + "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %s", + p->pid, + (*get_userid) (p->uid), + p->pri < -99 ? -99 : p->pri, + p->nice, + format_k(p->size), + format_k(p->rss), + state_abbrev[p->state], + format_time(p->time / HZ), + p->wcpu * 100.0, + p->pcpu * 100.0, + p->name); + + /* return the result */ + return (fmt); +} + +/* comparison routines for qsort */ + +/* + * There are currently four possible comparison routines. main selects + * one of these by indexing in to the array proc_compares. + * + * Possible keys are defined as macros below. Currently these keys are + * defined: percent cpu, cpu ticks, process state, resident set size, + * total virtual memory usage. The process states are ordered as follows + * (from least to most important): WAIT, zombie, sleep, stop, start, run. + * The array declaration below maps a process state index into a number + * that reflects this ordering. + */ + +/* First, the possible comparison keys. These are defined in such a way + that they can be merely listed in the source code to define the actual + desired ordering. + */ + +#define ORDERKEY_PCTCPU if (dresult = p2->pcpu - p1->pcpu,\ + (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0) +#define ORDERKEY_CPTICKS if ((result = (long)p2->time - (long)p1->time) == 0) +#define ORDERKEY_STATE if ((result = (sort_state[p2->state] - \ + sort_state[p1->state])) == 0) +#define ORDERKEY_PRIO if ((result = p2->pri - p1->pri) == 0) +#define ORDERKEY_RSSIZE if ((result = p2->rss - p1->rss) == 0) +#define ORDERKEY_MEM if ((result = p2->size - p1->size) == 0) +#define ORDERKEY_NAME if ((result = strcmp(p1->name, p2->name)) == 0) + +/* Now the array that maps process state to a weight */ + +unsigned char sort_state[] = +{ + 0, /* empty */ + 6, /* run */ + 3, /* sleep */ + 5, /* disk wait */ + 1, /* zombie */ + 2, /* stop */ + 4 /* swap */ +}; + + +/* compare_cpu - the comparison function for sorting by cpu percentage */ + +int +compare_cpu( + struct top_proc ** pp1, + struct top_proc ** pp2) +{ + register struct top_proc *p1; + register struct top_proc *p2; + register long result; + double dresult; + + /* remove one level of indirection */ + p1 = *pp1; + p2 = *pp2; + + ORDERKEY_PCTCPU + ORDERKEY_CPTICKS + ORDERKEY_STATE + ORDERKEY_PRIO + ORDERKEY_RSSIZE + ORDERKEY_MEM + ; + + return result == 0 ? 0 : result < 0 ? -1 : 1; +} + +/* compare_size - the comparison function for sorting by total memory usage */ + +int +compare_size( + struct top_proc ** pp1, + struct top_proc ** pp2) +{ + register struct top_proc *p1; + register struct top_proc *p2; + register long result; + double dresult; + + /* remove one level of indirection */ + p1 = *pp1; + p2 = *pp2; + + ORDERKEY_MEM + ORDERKEY_RSSIZE + ORDERKEY_PCTCPU + ORDERKEY_CPTICKS + ORDERKEY_STATE + ORDERKEY_PRIO + ; + + return result == 0 ? 0 : result < 0 ? -1 : 1; +} + +/* compare_res - the comparison function for sorting by resident set size */ + +int +compare_res( + struct top_proc ** pp1, + struct top_proc ** pp2) +{ + register struct top_proc *p1; + register struct top_proc *p2; + register long result; + double dresult; + + /* remove one level of indirection */ + p1 = *pp1; + p2 = *pp2; + + ORDERKEY_RSSIZE + ORDERKEY_MEM + ORDERKEY_PCTCPU + ORDERKEY_CPTICKS + ORDERKEY_STATE + ORDERKEY_PRIO + ; + + return result == 0 ? 0 : result < 0 ? -1 : 1; +} + +/* compare_time - the comparison function for sorting by total cpu time */ + +int +compare_time( + struct top_proc ** pp1, + struct top_proc ** pp2) +{ + register struct top_proc *p1; + register struct top_proc *p2; + register long result; + double dresult; + + /* remove one level of indirection */ + p1 = *pp1; + p2 = *pp2; + + ORDERKEY_CPTICKS + ORDERKEY_PCTCPU + ORDERKEY_STATE + ORDERKEY_PRIO + ORDERKEY_MEM + ORDERKEY_RSSIZE + ; + + return result == 0 ? 0 : result < 0 ? -1 : 1; +} + + +/* compare_cmd - the comparison function for sorting by command name */ + +int +compare_cmd( + struct top_proc ** pp1, + struct top_proc ** pp2) +{ + register struct top_proc *p1; + register struct top_proc *p2; + register long result; + double dresult; + + /* remove one level of indirection */ + p1 = *pp1; + p2 = *pp2; + + ORDERKEY_NAME + ORDERKEY_PCTCPU + ORDERKEY_CPTICKS + ORDERKEY_STATE + ORDERKEY_PRIO + ORDERKEY_RSSIZE + ORDERKEY_MEM + ; + + return result == 0 ? 0 : result < 0 ? -1 : 1; +} + + +/* + * proc_owner(pid) - returns the uid that owns process "pid", or -1 if + * the process does not exist. + * It is EXTREMLY IMPORTANT that this function work correctly. + * If pg_top runs setuid root (as in SVR4), then this function + * is the only thing that stands in the way of a serious + * security problem. It validates requests for the "kill" + * and "renice" commands. + */ + +uid_t +proc_owner(pid_t pid) + +{ + struct stat sb; + char buffer[32]; + + sprintf(buffer, "%d", pid); + + if (stat(buffer, &sb) < 0) + return -1; + else + return (int) sb.st_uid; +}