[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: