Re: Build of ptop keeps failing
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:sthibault@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 <rth@tamu.edu>
+ * Order support added by Alexey Klimkin <kad@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;
+}
Reply to: