svn commit: trunk/busybox: include libbb procps

vda at busybox.net vda at busybox.net
Sun Nov 5 00:43:52 UTC 2006


Author: vda
Date: 2006-11-04 16:43:51 -0800 (Sat, 04 Nov 2006)
New Revision: 16509

Log:
replace /proc scanning code by more versatile one.
Use it where appropriate.
Stop scanning /etc/passwd *for every process*!!! (uid->username)
top: reduce memory usage - we won't save unneeded fields
from /proc info anymore. Downside: ~+250 bytes of code


Modified:
   trunk/busybox/include/libbb.h
   trunk/busybox/libbb/find_pid_by_name.c
   trunk/busybox/libbb/procps.c
   trunk/busybox/procps/kill.c
   trunk/busybox/procps/ps.c
   trunk/busybox/procps/top.c


Changeset:
Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/include/libbb.h	2006-11-05 00:43:51 UTC (rev 16509)
@@ -501,23 +501,47 @@
 #endif
 #endif
 typedef struct {
-	int pid, ppid;
-	char user[9];
-	char state[4];
+	DIR *dir;
+/* Fields are set to 0/NULL if failed to determine (or not requested) */
+	char *cmd;
 	unsigned long rss;
-#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
-	unsigned pcpu;
 	unsigned long stime, utime;
-#endif
-	char *cmd;
-
-	/* basename of executable file in call to exec(2),
-		size from kernel headers */
-	char short_cmd[COMM_LEN];
+	unsigned pid;
+	unsigned ppid;
+	unsigned pgid;
+	unsigned sid;
+	unsigned uid;
+	unsigned gid;
+	/* basename of executable file in call to exec(2), size from */
+	/* sizeof(task_struct.comm) in /usr/include/linux/sched.h */
+	char state[4];
+	char comm[COMM_LEN];
+//	user/group? - use passwd/group parsing functions
 } procps_status_t;
-procps_status_t* procps_scan(int save_user_arg0);
+enum {
+	PSSCAN_PID      = 1 << 0,
+	PSSCAN_PPID     = 1 << 1,
+	PSSCAN_PGID     = 1 << 2,
+	PSSCAN_SID      = 1 << 3,
+	PSSCAN_UIDGID   = 1 << 4,
+	PSSCAN_COMM     = 1 << 5,
+	PSSCAN_CMD      = 1 << 6,
+	PSSCAN_STATE    = 1 << 7,
+	PSSCAN_RSS      = 1 << 8,
+	PSSCAN_STIME    = 1 << 9,
+	PSSCAN_UTIME    = 1 << 10,
+	/* These are all retrieved from proc/NN/stat in one go: */
+	PSSCAN_STAT     = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
+	                | PSSCAN_COMM | PSSCAN_STATE
+	                | PSSCAN_RSS | PSSCAN_STIME | PSSCAN_UTIME,
+};
+procps_status_t* alloc_procps_scan(int flags);
+void free_procps_scan(procps_status_t* sp);
+procps_status_t* procps_scan(procps_status_t* sp, int flags);
 pid_t *find_pid_by_name(const char* procName);
 pid_t *pidlist_reverse(pid_t *pidList);
+void clear_username_cache(void);
+const char* get_cached_username(uid_t uid);
 
 
 extern const char bb_uuenc_tbl_base64[];

Modified: trunk/busybox/libbb/find_pid_by_name.c
===================================================================
--- trunk/busybox/libbb/find_pid_by_name.c	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/libbb/find_pid_by_name.c	2006-11-05 00:43:51 UTC (rev 16509)
@@ -23,11 +23,11 @@
 {
 	pid_t* pidList;
 	int i = 0;
-	procps_status_t* p;
+	procps_status_t* p = NULL;
 
 	pidList = xmalloc(sizeof(*pidList));
-	while ((p = procps_scan(0)) != 0) {
-		if (strncmp(p->short_cmd, procName, COMM_LEN-1) == 0) {
+	while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM))) {
+		if (strncmp(p->comm, procName, sizeof(p->comm)-1) == 0) {
 			pidList = xrealloc(pidList, sizeof(*pidList) * (i+2));
 			pidList[i++] = p->pid;
 		}

Modified: trunk/busybox/libbb/procps.c
===================================================================
--- trunk/busybox/libbb/procps.c	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/libbb/procps.c	2006-11-05 00:43:51 UTC (rev 16509)
@@ -11,6 +11,35 @@
 #include "libbb.h"
 
 
+typedef struct {
+	uid_t uid;
+	char username[12];
+} user_map_t;
+
+static user_map_t *username_cache;
+static int username_cache_size;
+
+void clear_username_cache(void)
+{
+	free(username_cache);
+	username_cache = NULL;
+	username_cache_size = 0;
+}
+
+const char* get_cached_username(uid_t uid)
+{
+	int i;
+	for (i = 0; i < username_cache_size; i++)
+		if (username_cache[i].uid == uid)
+			return username_cache[i].username;
+	i = username_cache_size++;
+	username_cache = xrealloc(username_cache, username_cache_size * sizeof(*username_cache));
+	username_cache[i].uid = uid;
+	bb_getpwuid(username_cache[i].username, uid, sizeof(username_cache[i].username));
+	return username_cache[i].username;
+}
+
+
 #define PROCPS_BUFSIZE 1024
 
 static int read_to_buf(const char *filename, void *buf)
@@ -21,119 +50,171 @@
 	return ret;
 }
 
+procps_status_t* alloc_procps_scan(int flags)
+{
+	procps_status_t* sp = xzalloc(sizeof(procps_status_t));
+	sp->dir = xopendir("/proc");
+	return sp;
+}
 
-procps_status_t * procps_scan(int save_user_arg0)
+void free_procps_scan(procps_status_t* sp)
 {
-	static DIR *dir;
-	static procps_status_t ret_status;
+	closedir(sp->dir);
+	free(sp->cmd);
+	free(sp);
+}
 
+void BUG_comm_size(void);
+procps_status_t* procps_scan(procps_status_t* sp, int flags)
+{
 	struct dirent *entry;
-	char *name;
 	char buf[PROCPS_BUFSIZE];
-	char status[sizeof("/proc//cmdline") + sizeof(int)*3];
-	char *status_tail;
-	procps_status_t curstatus;
+	char filename[sizeof("/proc//cmdline") + sizeof(int)*3];
+	char *filename_tail;
 	long tasknice;
-	int pid;
+	unsigned pid;
 	int n;
 	struct stat sb;
 
-	if (!dir) {
-		dir = xopendir("/proc");
-	}
+	if (!sp)
+		sp = alloc_procps_scan(flags);
+
 	for (;;) {
-		entry = readdir(dir);
+		entry = readdir(sp->dir);
 		if (entry == NULL) {
-			closedir(dir);
-			dir = 0;
-			return 0;
+			free_procps_scan(sp);
+			return NULL;
 		}
-		name = entry->d_name;
-		if (!(*name >= '0' && *name <= '9'))
+		if (safe_strtou(entry->d_name, &pid))
 			continue;
 
-		memset(&curstatus, 0, sizeof(procps_status_t));
-		pid = atoi(name);
-		curstatus.pid = pid;
+		/* After this point we have to break, not continue
+		 * ("continue" would mean that current /proc/NNN
+		 * is not a valid process info) */
 
-		status_tail = status + sprintf(status, "/proc/%d", pid);
-		if (stat(status, &sb))
-			continue;
-		bb_getpwuid(curstatus.user, sb.st_uid, sizeof(curstatus.user));
+		memset(&sp->rss, 0, sizeof(*sp) - offsetof(procps_status_t, rss));
 
-		/* see proc(5) for some details on this */
-		strcpy(status_tail, "/stat");
-		n = read_to_buf(status, buf);
-		if (n < 0)
-			continue;
-		name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
-		if (name == 0 || name[1] != ' ')
-			continue;
-		*name = 0;
-		sscanf(buf, "%*s (%15c", curstatus.short_cmd);
-		n = sscanf(name+2,
-		"%c %d "
-		"%*s %*s %*s %*s "     /* pgrp, session, tty, tpgid */
-		"%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
-#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
-		"%lu %lu "             /* utime, stime */
-#else
-		"%*s %*s "             /* utime, stime */
-#endif
-		"%*s %*s %*s "         /* cutime, cstime, priority */
-		"%ld "                 /* nice */
-		"%*s %*s %*s "         /* timeout, it_real_value, start_time */
-		"%*s "                 /* vsize */
-		"%ld",                 /* rss */
-		curstatus.state, &curstatus.ppid,
-#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
-		&curstatus.utime, &curstatus.stime,
-#endif
-		&tasknice,
-		&curstatus.rss);
-#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
-		if (n != 6)
-#else
-		if (n != 4)
-#endif
-			continue;
+		sp->pid = pid;
+		if (!(flags & ~PSSCAN_PID)) break;
 
-		if (curstatus.rss == 0 && curstatus.state[0] != 'Z')
-			curstatus.state[1] = 'W';
-		else
-			curstatus.state[1] = ' ';
-		if (tasknice < 0)
-			curstatus.state[2] = '<';
-		else if (tasknice > 0)
-			curstatus.state[2] = 'N';
-		else
-			curstatus.state[2] = ' ';
+		filename_tail = filename + sprintf(filename, "/proc/%d", pid);
 
+		if (flags & PSSCAN_UIDGID) {
+			if (stat(filename, &sb))
+				break;
+			/* Need comment - is this effective or read UID/GID? */
+			sp->uid = sb.st_uid;
+			sp->gid = sb.st_gid;
+		}
+	
+		if (flags & PSSCAN_STAT) {
+			char *cp;
+			/* see proc(5) for some details on this */
+			strcpy(filename_tail, "/stat");
+			n = read_to_buf(filename, buf);
+			if (n < 0)
+				break;
+			cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
+			if (!cp || cp[1] != ' ')
+				break;
+			cp[0] = '\0';
+			if (sizeof(sp->comm) < 16)
+				BUG_comm_size();
+			sscanf(buf, "%*s (%15c", sp->comm);
+			n = sscanf(cp+2,
+				"%c %u "               /* state, ppid */
+				"%u %u %*s %*s "       /* pgid, sid, tty, tpgid */
+				"%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
+				"%lu %lu "             /* utime, stime */
+				"%*s %*s %*s "         /* cutime, cstime, priority */
+				"%ld "                 /* nice */
+				"%*s %*s %*s "         /* timeout, it_real_value, start_time */
+				"%*s "                 /* vsize */
+				"%lu",                 /* rss */
+				sp->state, &sp->ppid,
+				&sp->pgid, &sp->sid,
+				&sp->utime, &sp->stime,
+				&tasknice,
+				&sp->rss);
+			if (n != 8)
+				break;
+
+			if (sp->rss == 0 && sp->state[0] != 'Z')
+				sp->state[1] = 'W';
+			else
+				sp->state[1] = ' ';
+			if (tasknice < 0)
+				sp->state[2] = '<';
+			else if (tasknice > 0)
+				sp->state[2] = 'N';
+			else
+				sp->state[2] = ' ';
+
 #ifdef PAGE_SHIFT
-		curstatus.rss <<= (PAGE_SHIFT - 10);     /* 2**10 = 1kb */
+			sp->rss <<= (PAGE_SHIFT - 10);     /* 2**10 = 1kb */
 #else
-		curstatus.rss *= (getpagesize() >> 10);     /* 2**10 = 1kb */
+			sp->rss *= (getpagesize() >> 10);     /* 2**10 = 1kb */
 #endif
+		}
 
-		if (save_user_arg0) {
-			strcpy(status_tail, "/cmdline");
-			n = read_to_buf(status, buf);
-			if (n > 0) {
-				if (buf[n-1]=='\n')
-					buf[--n] = 0;
-				name = buf;
-				while (n) {
-					if (((unsigned char)*name) < ' ')
-						*name = ' ';
-					name++;
-					n--;
-				}
-				*name = 0;
-				if (buf[0])
-					curstatus.cmd = strdup(buf);
-				/* if NULL it work true also */
+		if (flags & PSSCAN_CMD) {
+			free(sp->cmd);
+			sp->cmd = NULL;
+			strcpy(filename_tail, "/cmdline");
+			n = read_to_buf(filename, buf);
+			if (n <= 0)
+				break;
+			if (buf[n-1] == '\n') {
+				if (!--n)
+					break;
+				buf[n] = '\0';
 			}
+			do {
+				n--;
+				if ((unsigned char)(buf[n]) < ' ')
+					buf[n] = ' ';
+			} while (n);
+			sp->cmd = strdup(buf);
 		}
-		return memcpy(&ret_status, &curstatus, sizeof(procps_status_t));
+		break;
 	}
+	return sp;
 }
+/* from kernel:
+	//             pid comm S ppid pgid sid tty_nr tty_pgrp flg
+        sprintf(buffer,"%d (%s) %c %d  %d   %d  %d     %d       %lu %lu \
+%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu\n",
+                task->pid,
+                tcomm,
+                state,
+                ppid,
+                pgid,
+                sid,
+                tty_nr,
+                tty_pgrp,
+                task->flags,
+                min_flt,
+
+                cmin_flt,
+                maj_flt,
+                cmaj_flt,
+                cputime_to_clock_t(utime),
+                cputime_to_clock_t(stime),
+                cputime_to_clock_t(cutime),
+                cputime_to_clock_t(cstime),
+                priority,
+                nice,
+                num_threads,
+	// 0,
+                start_time,
+                vsize,
+                mm ? get_mm_rss(mm) : 0,
+                rsslim,
+                mm ? mm->start_code : 0,
+                mm ? mm->end_code : 0,
+                mm ? mm->start_stack : 0,
+                esp,
+                eip,
+the rest is some obsolete cruft
+*/

Modified: trunk/busybox/procps/kill.c
===================================================================
--- trunk/busybox/procps/kill.c	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/procps/kill.c	2006-11-05 00:43:51 UTC (rev 16509)
@@ -82,7 +82,7 @@
 
 	if (killall5) {
 		pid_t sid;
-		procps_status_t* p;
+		procps_status_t* p = NULL;
 
 // Cannot happen anyway? We don't TERM ourself, we STOP
 //		/* kill(-1, sig) on Linux (at least 2.1.x)
@@ -94,8 +94,8 @@
 		pid = getpid();
 		sid = getsid(pid);
 		/* Now kill all processes except our session */
-        	while ((p = procps_scan(0))!=0) {
-			if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1)
+        	while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
+			if (p->sid != sid && p->pid != pid && p->pid != 1)
 				kill(p->pid, signo);
 		}
 		/* And let them continue */

Modified: trunk/busybox/procps/ps.c
===================================================================
--- trunk/busybox/procps/ps.c	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/procps/ps.c	2006-11-05 00:43:51 UTC (rev 16509)
@@ -11,7 +11,7 @@
 
 int ps_main(int argc, char **argv)
 {
-	procps_status_t * p;
+	procps_status_t *p = NULL;
 	int i, len;
 	SKIP_SELINUX(const) int use_selinux = 0;
 	USE_SELINUX(security_context_t sid = NULL;)
@@ -50,7 +50,13 @@
 	else
 		puts("  PID  Uid     VmSize Stat Command");
 
-	while ((p = procps_scan(1)) != 0)  {
+	while ((p = procps_scan(p, 0
+			| PSSCAN_PID
+			| PSSCAN_UIDGID
+			| PSSCAN_STATE
+			| PSSCAN_RSS
+			| PSSCAN_CMD
+	))) {
 		char *namecmd = p->cmd;
 #if ENABLE_SELINUX
 		if (use_selinux) {
@@ -71,13 +77,18 @@
 			} else {
 				safe_strncpy(sbuf, "unknown", 7);
 			}
-			len = printf("%5u %-32s %s ", (unsigned)p->pid, sbuf, p->state);
+			len = printf("%5u %-32s %s ", p->pid, sbuf, p->state);
 		} else
 #endif
+		{
+			const char *user = get_cached_username(p->uid);
 			if (p->rss == 0)
-				len = printf("%5u %-8s        %s ", (unsigned)p->pid, p->user, p->state);
+				len = printf("%5u %-8s        %s ",
+					p->pid, user, p->state);
 			else
-				len = printf("%5u %-8s %6ld %s ", (unsigned)p->pid, p->user, p->rss, p->state);
+				len = printf("%5u %-8s %6ld %s ",
+					p->pid, user, p->rss, p->state);
+		}
 
 		i = terminal_width-len;
 
@@ -88,16 +99,15 @@
 				namecmd[i] = 0;
 			puts(namecmd);
 		} else {
-			namecmd = p->short_cmd;
+			namecmd = p->comm;
 			if (i < 2)
 				i = 2;
 			if (strlen(namecmd) > ((size_t)i-2))
 				namecmd[i-2] = 0;
 			printf("[%s]\n", namecmd);
 		}
-		/* no check needed, but to make valgrind happy.. */
-		if (ENABLE_FEATURE_CLEAN_UP && p->cmd)
-			free(p->cmd);
 	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		clear_username_cache();
 	return EXIT_SUCCESS;
 }

Modified: trunk/busybox/procps/top.c
===================================================================
--- trunk/busybox/procps/top.c	2006-11-05 00:38:51 UTC (rev 16508)
+++ trunk/busybox/procps/top.c	2006-11-05 00:43:51 UTC (rev 16509)
@@ -30,37 +30,76 @@
 
 #include "busybox.h"
 
-typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
 
-static procps_status_t *top;   /* Hehe */
+typedef struct {
+	unsigned long rss;
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	unsigned long ticks;
+	unsigned pcpu; /* delta of ticks */
+#endif
+	unsigned pid, ppid;
+	unsigned uid;
+	char state[4];
+	char comm[COMM_LEN];
+} top_status_t;
+static top_status_t *top;
 static int ntop;
+/* This structure stores some critical information from one frame to
+   the next. Used for finding deltas. */
+struct save_hist {
+	unsigned long ticks;
+	unsigned pid;
+};
+static struct save_hist *prev_hist;
+static int prev_hist_count;
+/* static int hist_iterations; */
+static unsigned total_pcpu;
+/* static unsigned long total_rss; */
+
+
 #define OPT_BATCH_MODE (option_mask32 & 0x4)
 
 #if ENABLE_FEATURE_USE_TERMIOS
-static int pid_sort(procps_status_t *P, procps_status_t *Q)
+static int pid_sort(top_status_t *P, top_status_t *Q)
 {
+	/* Buggy wrt pids with high bit set */
+	/* (linux pids are in [1..2^15-1]) */
 	return (Q->pid - P->pid);
 }
 #endif
 
-static int mem_sort(procps_status_t *P, procps_status_t *Q)
+static int mem_sort(top_status_t *P, top_status_t *Q)
 {
-	return (int)(Q->rss - P->rss);
+	/* We want to avoid unsigned->signed and truncation errors */
+	if (Q->rss < P->rss) return -1;
+	return Q->rss != P->rss; /* 0 if ==, 1 if > */
 }
 
-#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
 
+typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
+
+#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+
+static cmp_funcp sort_function;
+
+#else
+
 enum { SORT_DEPTH = 3 };
-static cmp_t sort_function[SORT_DEPTH];
 
-static int pcpu_sort(procps_status_t *P, procps_status_t *Q)
+static cmp_funcp sort_function[SORT_DEPTH];
+
+static int pcpu_sort(top_status_t *P, top_status_t *Q)
 {
-	return (Q->pcpu - P->pcpu);
+	/* Buggy wrt ticks with high bit set */
+	/* Affects only processes for which ticks overflow */
+	return (int)Q->pcpu - (int)P->pcpu;
 }
 
-static int time_sort(procps_status_t *P, procps_status_t *Q)
+static int time_sort(top_status_t *P, top_status_t *Q)
 {
-	return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
+	/* We want to avoid unsigned->signed and truncation errors */
+	if (Q->ticks < P->ticks) return -1;
+	return Q->ticks != P->ticks; /* 0 if ==, 1 if > */
 }
 
 static int mult_lvl_cmp(void* a, void* b) {
@@ -74,25 +113,7 @@
 	return 0;
 }
 
-/* This structure stores some critical information from one frame to
-   the next. Mostly used for sorting. */
-struct save_hist {
-	int ticks;
-	pid_t pid;
-};
 
-/*
- * Calculates percent cpu usage for each task.
- */
-
-static struct save_hist *prev_hist;
-static int prev_hist_count;
-/* static int hist_iterations; */
-
-
-static unsigned total_pcpu;
-/* static unsigned long total_rss; */
-
 typedef struct {
 	unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
 	unsigned long long total;
@@ -115,11 +136,12 @@
 	jif.busy = jif.total - jif.idle - jif.iowait;
 }
 
+
 static void do_stats(void)
 {
-	procps_status_t *cur;
+	top_status_t *cur;
 	pid_t pid;
-	int total_time, i, last_i, n;
+	int i, last_i, n;
 	struct save_hist *new_hist;
 
 	get_jiffy_counts();
@@ -139,8 +161,7 @@
 		 * and system time
 		 */
 		pid = cur->pid;
-		total_time = cur->stime + cur->utime;
-		new_hist[n].ticks = total_time;
+		new_hist[n].ticks = cur->ticks;
 		new_hist[n].pid = pid;
 
 		/* find matching entry from previous pass */
@@ -150,13 +171,13 @@
 		last_i = i;
 		if (prev_hist_count) do {
 			if (prev_hist[i].pid == pid) {
-				cur->pcpu = total_time - prev_hist[i].ticks;
+				cur->pcpu = cur->ticks - prev_hist[i].ticks;
+				total_pcpu += cur->pcpu;
 				break;
 			}
 			i = (i+1) % prev_hist_count;
 			/* hist_iterations++; */
 		} while (i != last_i);
-		total_pcpu += cur->pcpu;
 		/* total_rss += cur->rss; */
 	}
 
@@ -167,10 +188,9 @@
 	prev_hist = new_hist;
 	prev_hist_count = ntop;
 }
-#else
-static cmp_t sort_function;
 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
 
+
 /* display generic info (meminfo / loadavg) */
 static unsigned long display_generic(int scr_width)
 {
@@ -265,7 +285,7 @@
 		bits_per_int = sizeof(int)*8
 	};
 
-	procps_status_t *s = top;
+	top_status_t *s = top;
 	char rss_str_buf[8];
 	unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
 	unsigned pmem_shift, pmem_scale;
@@ -333,14 +353,19 @@
 			sprintf(rss_str_buf, "%6ldM", s->rss/1024);
 		else
 			sprintf(rss_str_buf, "%7ld", s->rss);
-		USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);)
-		col -= printf("\n%5u %-8s %s  %s%6u%3u.%c" \
-				USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ",
-				(unsigned)s->pid, s->user, s->state, rss_str_buf, (unsigned)s->ppid,
+		USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(
+		pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);
+		)
+		col -= printf("\n%5u %-8s %s  "
+				"%s%6u"
+				USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c")
+				"%3u.%c ",
+				s->pid, get_cached_username(s->uid), s->state,
+				rss_str_buf, s->ppid,
 				USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
 				pmem.quot, '0'+pmem.rem);
 		if (col > 0)
-			printf("%.*s", col, s->short_cmd);
+			printf("%.*s", col, s->comm);
 		/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
 			jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
 		s++;
@@ -350,18 +375,20 @@
 	fflush(stdout);
 }
 
+
 static void clearmems(void)
 {
+	clear_username_cache();
 	free(top);
 	top = 0;
 	ntop = 0;
 }
 
+
 #if ENABLE_FEATURE_USE_TERMIOS
 #include <termios.h>
 #include <signal.h>
 
-
 static struct termios initial_settings;
 
 static void reset_term(void)
@@ -427,7 +454,7 @@
 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
 
 	while (1) {
-		procps_status_t *p;
+		procps_status_t *p = NULL;
 
 		/* Default to 25 lines - 5 lines for status */
 		lines = 24 - 3;
@@ -442,11 +469,26 @@
 #endif /* FEATURE_USE_TERMIOS */
 
 		/* read process IDs & status for all the processes */
-		while ((p = procps_scan(0)) != 0) {
+		while ((p = procps_scan(p, 0
+				| PSSCAN_PID
+				| PSSCAN_PPID
+				| PSSCAN_RSS
+				| PSSCAN_STIME
+				| PSSCAN_UTIME
+				| PSSCAN_STATE
+				| PSSCAN_COMM
+				| PSSCAN_SID
+				| PSSCAN_UIDGID
+		))) {
 			int n = ntop;
-
-			top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
-			memcpy(top + n, p, sizeof(procps_status_t));
+			top = xrealloc(top, (++ntop)*sizeof(top_status_t));
+			top[n].pid = p->pid;
+			top[n].ppid = p->ppid;
+			top[n].rss = p->rss;
+			top[n].ticks = p->stime + p->utime;
+			top[n].uid = p->uid;
+			strcpy(top[n].state, p->state);
+			strcpy(top[n].comm, p->comm);
 		}
 		if (ntop == 0) {
 			bb_error_msg_and_die("can't find process info in /proc");
@@ -459,9 +501,9 @@
 			continue;
 		}
 		do_stats();
-		qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp);
+		qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
 #else
-		qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
+		qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);
 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
 		count = lines;
 		if (OPT_BATCH_MODE || count > ntop) {




More information about the busybox-cvs mailing list