aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-10-22 12:21:15 +0000
committerEric Andersen <andersen@codepoet.org>2002-10-22 12:21:15 +0000
commit44608e9693b03661fbab5e27650bb040c6871d11 (patch)
tree4555230653cdb82d998f076b29130d8fe18a6f7a
parent1887b0478f2743ce7808e8b37462e18d584611e1 (diff)
downloadbusybox-w32-44608e9693b03661fbab5e27650bb040c6871d11.tar.gz
busybox-w32-44608e9693b03661fbab5e27650bb040c6871d11.tar.bz2
busybox-w32-44608e9693b03661fbab5e27650bb040c6871d11.zip
Patch last_pach62 from vodz. This patch moves all the /proc parsing
code into libbb so it can be shared by ps, top, etc, saving over 1.5k.
-rw-r--r--include/libbb.h21
-rw-r--r--libbb/Makefile.in3
-rw-r--r--libbb/find_pid_by_name.c54
-rw-r--r--libbb/procps.c137
-rw-r--r--procps/kill.c6
-rw-r--r--procps/pidof.c13
-rw-r--r--procps/ps.c128
-rw-r--r--procps/top.c170
8 files changed, 220 insertions, 312 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 3b5f2979c..bc8112310 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -127,7 +127,7 @@ extern void write_mtab(char* blockDevice, char* directory,
127 char* filesystemType, long flags, char* string_flags); 127 char* filesystemType, long flags, char* string_flags);
128extern void erase_mtab(const char * name); 128extern void erase_mtab(const char * name);
129extern long atoi_w_units (const char *cp); 129extern long atoi_w_units (const char *cp);
130extern long* find_pid_by_name( char* pidName); 130extern long* find_pid_by_name( const char* pidName);
131extern char *find_real_root_device_name(const char* name); 131extern char *find_real_root_device_name(const char* name);
132extern char *get_line_from_file(FILE *file); 132extern char *get_line_from_file(FILE *file);
133extern void print_file(FILE *file); 133extern void print_file(FILE *file);
@@ -337,4 +337,23 @@ extern ssize_t xread_all_eof(int fd, void *buf, size_t count);
337extern void xread_all(int fd, void *buf, size_t count); 337extern void xread_all(int fd, void *buf, size_t count);
338extern unsigned char xread_char(int fd); 338extern unsigned char xread_char(int fd);
339 339
340typedef struct {
341 int pid;
342 char user[9];
343 char state[4];
344 unsigned long rss;
345 int ppid;
346#ifdef FEATURE_CPU_USAGE_PERCENTAGE
347 unsigned pcpu;
348 unsigned long stime, utime;
349#endif
350 char *cmd;
351
352 /* basename of executable file in call to exec(2),
353 size from kernel headers */
354 char short_cmd[16];
355} procps_status_t;
356
357extern procps_status_t * procps_scan(int save_user_arg0);
358
340#endif /* __LIBCONFIG_H__ */ 359#endif /* __LIBCONFIG_H__ */
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index f4ef0b868..6703cf1f7 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -43,7 +43,8 @@ LIBBB_SRC:= \
43 arith.c simplify_path.c inet_common.c inode_hash.c obscure.c \ 43 arith.c simplify_path.c inet_common.c inode_hash.c obscure.c \
44 pwd2spwd.c xfuncs.c correct_password.c change_identity.c \ 44 pwd2spwd.c xfuncs.c correct_password.c change_identity.c \
45 setup_environment.c run_shell.c pw_encrypt.c restricted_shell.c \ 45 setup_environment.c run_shell.c pw_encrypt.c restricted_shell.c \
46 xgethostbyname2.c create_icmp6_socket.c xconnect.c bb_asprintf.c 46 xgethostbyname2.c create_icmp6_socket.c xconnect.c bb_asprintf.c \
47 procps.c
47 48
48LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) 49LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC))
49 50
diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c
index 4eaee03e3..a648137e1 100644
--- a/libbb/find_pid_by_name.c
+++ b/libbb/find_pid_by_name.c
@@ -22,7 +22,6 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <ctype.h> 23#include <ctype.h>
24#include <string.h> 24#include <string.h>
25#include <dirent.h>
26#include <stdlib.h> 25#include <stdlib.h>
27#include "libbb.h" 26#include "libbb.h"
28 27
@@ -40,7 +39,7 @@
40 * 39 *
41 * Returns a list of all matching PIDs 40 * Returns a list of all matching PIDs
42 */ 41 */
43extern long* find_pid_by_name( char* pidName) 42extern long* find_pid_by_name( const char* pidName)
44{ 43{
45 int fd, i, j; 44 int fd, i, j;
46 char device[] = "/dev/ps"; 45 char device[] = "/dev/ps";
@@ -112,61 +111,28 @@ extern long* find_pid_by_name( char* pidName)
112 111
113/* find_pid_by_name() 112/* find_pid_by_name()
114 * 113 *
114 * Modified by Vladimir Oleynik for use with libbb/procps.c
115 * This finds the pid of the specified process. 115 * This finds the pid of the specified process.
116 * Currently, it's implemented by rummaging through 116 * Currently, it's implemented by rummaging through
117 * the proc filesystem. 117 * the proc filesystem.
118 * 118 *
119 * Returns a list of all matching PIDs 119 * Returns a list of all matching PIDs
120 */ 120 */
121extern long* find_pid_by_name( char* pidName) 121extern long* find_pid_by_name( const char* pidName)
122{ 122{
123 DIR *dir; 123 long* pidList;
124 struct dirent *next;
125 long* pidList=NULL;
126 int i=0; 124 int i=0;
125 procps_status_t * p;
127 126
128 dir = opendir("/proc"); 127 pidList = xmalloc(sizeof(long));
129 if (!dir) 128 while ((p = procps_scan(0)) != 0) {
130 perror_msg_and_die("Cannot open /proc"); 129 if (strcmp(p->short_cmd, pidName) == 0) {
131
132 while ((next = readdir(dir)) != NULL) {
133 FILE *status;
134 char filename[READ_BUF_SIZE];
135 char buffer[READ_BUF_SIZE];
136 char name[READ_BUF_SIZE];
137
138 /* Must skip ".." since that is outside /proc */
139 if (strcmp(next->d_name, "..") == 0)
140 continue;
141
142 /* If it isn't a number, we don't want it */
143 if (!isdigit(*next->d_name))
144 continue;
145
146 sprintf(filename, "/proc/%s/status", next->d_name);
147 if (! (status = fopen(filename, "r")) ) {
148 continue;
149 }
150 if (fgets(buffer, READ_BUF_SIZE-1, status) == NULL) {
151 fclose(status);
152 continue;
153 }
154 fclose(status);
155
156 /* Buffer should contain a string like "Name: binary_name" */
157 sscanf(buffer, "%*s %s", name);
158 if (strcmp(name, pidName) == 0) {
159 pidList=xrealloc( pidList, sizeof(long) * (i+2)); 130 pidList=xrealloc( pidList, sizeof(long) * (i+2));
160 pidList[i++]=strtol(next->d_name, NULL, 0); 131 pidList[i++]=p->pid;
161 } 132 }
162 } 133 }
163 134
164 if (pidList) { 135 pidList[i] = i==0 ? -1 : 0;
165 pidList[i]=0;
166 } else {
167 pidList=xrealloc( pidList, sizeof(long));
168 pidList[0]=-1;
169 }
170 return pidList; 136 return pidList;
171} 137}
172#endif /* CONFIG_FEATURE_USE_DEVPS_PATCH */ 138#endif /* CONFIG_FEATURE_USE_DEVPS_PATCH */
diff --git a/libbb/procps.c b/libbb/procps.c
new file mode 100644
index 000000000..9ac5be092
--- /dev/null
+++ b/libbb/procps.c
@@ -0,0 +1,137 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright 1998 by Albert Cahalan; all rights reserved.
6 * Copyright (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru>
7 * GNU Library General Public License Version 2, or any later version
8 *
9 */
10
11#include "libbb.h"
12
13#if ! defined CONFIG_FEATURE_USE_DEVPS_PATCH
14#include <dirent.h>
15#include <string.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <asm/page.h>
19
20
21extern procps_status_t * procps_scan(int save_user_arg0)
22{
23 static DIR *dir;
24 struct dirent *entry;
25 static procps_status_t ret_status;
26 char *name;
27 int n;
28 char status[32];
29 char buf[1024];
30 FILE *fp;
31 procps_status_t curstatus;
32 int pid;
33 long tasknice;
34 struct stat sb;
35
36 if (!dir) {
37 dir = opendir("/proc");
38 if(!dir)
39 error_msg_and_die("Can't open /proc");
40 }
41 for(;;) {
42 if((entry = readdir(dir)) == NULL) {
43 closedir(dir);
44 dir = 0;
45 return 0;
46 }
47 name = entry->d_name;
48 if (!(*name >= '0' && *name <= '9'))
49 continue;
50
51 memset(&curstatus, 0, sizeof(procps_status_t));
52 pid = atoi(name);
53 curstatus.pid = pid;
54
55 sprintf(status, "/proc/%d/stat", pid);
56 if((fp = fopen(status, "r")) == NULL)
57 continue;
58 if(fstat(fileno(fp), &sb))
59 continue;
60 my_getpwuid(curstatus.user, sb.st_uid);
61 name = fgets(buf, sizeof(buf), fp);
62 fclose(fp);
63 if(name == NULL)
64 continue;
65 name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
66 if(name == 0 || name[1] != ' ')
67 continue;
68 *name = 0;
69 sscanf(buf, "%*s (%15c", curstatus.short_cmd);
70 n = sscanf(name+2,
71 "%c %d "
72 "%*s %*s %*s %*s " /* pgrp, session, tty, tpgid */
73 "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
74#ifdef FEATURE_CPU_USAGE_PERCENTAGE
75 "%lu %lu "
76#else
77 "%*s %*s "
78#endif
79 "%*s %*s %*s " /* cutime, cstime, priority */
80 "%ld "
81 "%*s %*s %*s " /* timeout, it_real_value, start_time */
82 "%*s " /* vsize */
83 "%ld",
84 curstatus.state, &curstatus.ppid,
85#ifdef FEATURE_CPU_USAGE_PERCENTAGE
86 &curstatus.utime, &curstatus.stime,
87#endif
88 &tasknice,
89 &curstatus.rss);
90#ifdef FEATURE_CPU_USAGE_PERCENTAGE
91 if(n != 6)
92#else
93 if(n != 4)
94#endif
95 continue;
96
97 if (curstatus.rss == 0 && curstatus.state[0] != 'Z')
98 curstatus.state[1] = 'W';
99 else
100 curstatus.state[1] = ' ';
101 if (tasknice < 0)
102 curstatus.state[2] = '<';
103 else if (tasknice > 0)
104 curstatus.state[2] = 'N';
105 else
106 curstatus.state[2] = ' ';
107
108 curstatus.rss <<= (PAGE_SHIFT - 10); /* 2**10 = 1kb */
109
110 sprintf(status, "/proc/%d/cmdline", pid);
111 if(save_user_arg0) {
112 if((fp = fopen(status, "r")) == NULL)
113 continue;
114 if(fgets(buf, sizeof(buf), fp) != NULL) {
115 name = strchr(buf, '\n');
116 if(name != NULL)
117 *name = 0;
118 if(buf[0])
119 curstatus.cmd = strdup(buf);
120 /* if NULL it work true also */
121 }
122 fclose(fp);
123 }
124 return memcpy(&ret_status, &curstatus, sizeof(procps_status_t));
125 }
126}
127
128#endif /* CONFIG_FEATURE_USE_DEVPS_PATCH. Else this file is empty */
129
130/* END CODE */
131/*
132Local Variables:
133c-file-style: "linux"
134c-basic-offset: 4
135tab-width: 4
136End:
137*/
diff --git a/procps/kill.c b/procps/kill.c
index 2ef87aea6..cf5c412a8 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -127,7 +127,7 @@ do_it_now:
127 long* pidList; 127 long* pidList;
128 128
129 pidList = find_pid_by_name(*argv); 129 pidList = find_pid_by_name(*argv);
130 if (!pidList || *pidList<=0) { 130 if (*pidList <= 0) {
131 errors++; 131 errors++;
132 if (quiet==0) 132 if (quiet==0)
133 error_msg( "%s: no process killed", *argv); 133 error_msg( "%s: no process killed", *argv);
@@ -142,9 +142,7 @@ do_it_now:
142 } 142 }
143 } 143 }
144 } 144 }
145 /* Note that we don't bother to free the memory 145 free(pidList);
146 * allocated in find_pid_by_name(). It will be freed
147 * upon exit, so we can save a byte or two */
148 argv++; 146 argv++;
149 } 147 }
150 } 148 }
diff --git a/procps/pidof.c b/procps/pidof.c
index d0d65e0db..169a92007 100644
--- a/procps/pidof.c
+++ b/procps/pidof.c
@@ -54,21 +54,16 @@ extern int pidof_main(int argc, char **argv)
54 while(optind < argc) { 54 while(optind < argc) {
55 long* pidList; 55 long* pidList;
56 56
57 pidList = find_pid_by_name( argv[optind]); 57 pidList = find_pid_by_name(argv[optind]);
58 if (!pidList || *pidList<=0) { 58 for(; *pidList > 0; pidList++) {
59 break;
60 }
61
62 for(; pidList && *pidList!=0; pidList++) {
63 printf("%s%ld", (n++ ? " " : ""), (long)*pidList); 59 printf("%s%ld", (n++ ? " " : ""), (long)*pidList);
64 fail = 0; 60 fail = 0;
65 if (single_flag) 61 if (single_flag)
66 break; 62 break;
67 } 63 }
68 /* Note that we don't bother to free the memory 64 free(pidList);
69 * allocated in find_pid_by_name(). It will be freed
70 * upon exit, so we can save a byte or two */
71 optind++; 65 optind++;
66
72 } 67 }
73 printf("\n"); 68 printf("\n");
74 69
diff --git a/procps/ps.c b/procps/ps.c
index 6036ffc1e..cf2f2b0c4 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -44,82 +44,10 @@ static const int TERMINAL_WIDTH = 79; /* not 80 in case terminal has linefo
44 44
45#if ! defined CONFIG_FEATURE_USE_DEVPS_PATCH 45#if ! defined CONFIG_FEATURE_USE_DEVPS_PATCH
46 46
47/* The following is the first ps implementation --
48 * the one using the /proc virtual filesystem.
49 */
50
51typedef struct proc_s {
52 char cmd[16]; /* basename of executable file in call to exec(2) */
53 int ruid; /* real only (sorry) */
54 int pid; /* process id */
55 int ppid; /* pid of parent process */
56 char state; /* single-char code for process state (S=sleeping) */
57 unsigned int vmsize; /* size of process as far as the vm is concerned */
58} proc_t;
59
60
61
62static int file2str(char *filename, char *ret, int cap)
63{
64 int fd, num_read;
65
66 if ((fd = open(filename, O_RDONLY, 0)) == -1)
67 return -1;
68 if ((num_read = read(fd, ret, cap - 1)) <= 0)
69 return -1;
70 ret[num_read] = 0;
71 close(fd);
72 return num_read;
73}
74
75
76static void parse_proc_status(char *S, proc_t * P)
77{
78 char *tmp;
79
80 memset(P->cmd, 0, sizeof P->cmd);
81 sscanf(S, "Name:\t%15c", P->cmd);
82 tmp = strchr(P->cmd, '\n');
83 if (tmp)
84 *tmp = '\0';
85 tmp = strstr(S, "State");
86 sscanf(tmp, "State:\t%c", &P->state);
87
88 P->pid = 0;
89 P->ppid = 0;
90 tmp = strstr(S, "Pid:");
91 if (tmp)
92 sscanf(tmp, "Pid:\t%d\n" "PPid:\t%d\n", &P->pid, &P->ppid);
93 else
94 error_msg("Internal error!");
95
96 /* For busybox, ignoring effective, saved, etc. */
97 P->ruid = 0;
98 tmp = strstr(S, "Uid:");
99 if (tmp)
100 sscanf(tmp, "Uid:\t%d", &P->ruid);
101 else
102 error_msg("Internal error!");
103
104 P->vmsize = 0;
105 tmp = strstr(S, "VmSize:");
106 if (tmp)
107 sscanf(tmp, "VmSize:\t%d", &P->vmsize);
108#if 0
109 else
110 error_msg("Internal error!");
111#endif
112}
113
114extern int ps_main(int argc, char **argv) 47extern int ps_main(int argc, char **argv)
115{ 48{
116 proc_t p; 49 procps_status_t * p;
117 DIR *dir; 50 int i, len;
118 FILE *file;
119 struct dirent *entry;
120 char path[32], sbuf[512];
121 char uidName[9];
122 int len, i, c;
123#ifdef CONFIG_FEATURE_AUTOWIDTH 51#ifdef CONFIG_FEATURE_AUTOWIDTH
124 struct winsize win = { 0, 0, 0, 0 }; 52 struct winsize win = { 0, 0, 0, 0 };
125 int terminal_width = TERMINAL_WIDTH; 53 int terminal_width = TERMINAL_WIDTH;
@@ -128,11 +56,6 @@ extern int ps_main(int argc, char **argv)
128#endif 56#endif
129 57
130 58
131
132 dir = opendir("/proc");
133 if (!dir)
134 error_msg_and_die("Can't open /proc");
135
136#ifdef CONFIG_FEATURE_AUTOWIDTH 59#ifdef CONFIG_FEATURE_AUTOWIDTH
137 ioctl(fileno(stdout), TIOCGWINSZ, &win); 60 ioctl(fileno(stdout), TIOCGWINSZ, &win);
138 if (win.ws_col > 0) 61 if (win.ws_col > 0)
@@ -140,38 +63,31 @@ extern int ps_main(int argc, char **argv)
140#endif 63#endif
141 64
142 printf(" PID Uid VmSize Stat Command\n"); 65 printf(" PID Uid VmSize Stat Command\n");
143 while ((entry = readdir(dir)) != NULL) { 66 while ((p = procps_scan(1)) != 0) {
144 if (!isdigit(*entry->d_name)) 67 char *namecmd = p->cmd;
145 continue;
146 sprintf(path, "/proc/%s/status", entry->d_name);
147 if ((file2str(path, sbuf, sizeof sbuf)) != -1) {
148 parse_proc_status(sbuf, &p);
149 }
150 68
151 /* Make some adjustments as needed */ 69 if(p->rss == 0)
152 my_getpwuid(uidName, p.ruid); 70 len = printf("%5d %-8s %s ", p->pid, p->user, p->state);
71 else
72 len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state);
73 i = terminal_width-len;
153 74
154 sprintf(path, "/proc/%s/cmdline", entry->d_name); 75 if(namecmd != 0 && namecmd[0] != 0) {
155 file = fopen(path, "r"); 76 if(i < 0)
156 if (file == NULL)
157 continue;
158 i = 0; 77 i = 0;
159 if(p.vmsize == 0) 78 if(strlen(namecmd) > i)
160 len = printf("%5d %-8s %c ", p.pid, uidName, p.state); 79 namecmd[i] = 0;
161 else 80 printf("%s\n", namecmd);
162 len = printf("%5d %-8s %6d %c ", p.pid, uidName, p.vmsize, p.state); 81 } else {
163 while (((c = getc(file)) != EOF) && (i < (terminal_width-len))) { 82 namecmd = p->short_cmd;
164 i++; 83 if(i < 2)
165 if (c == '\0') 84 i = 2;
166 c = ' '; 85 if(strlen(namecmd) > (i-2))
167 putc(c, stdout); 86 namecmd[i-2] = 0;
87 printf("[%s]\n", namecmd);
168 } 88 }
169 fclose(file); 89 free(p->cmd);
170 if (i == 0)
171 printf("[%s]", p.cmd);
172 putchar('\n');
173 } 90 }
174 closedir(dir);
175 return EXIT_SUCCESS; 91 return EXIT_SUCCESS;
176} 92}
177 93
diff --git a/procps/top.c b/procps/top.c
index 06ae77119..4204deaf2 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -31,10 +31,8 @@
31#include <stdio.h> 31#include <stdio.h>
32#include <stdlib.h> 32#include <stdlib.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <dirent.h>
35#include <string.h> 34#include <string.h>
36#include <sys/ioctl.h> 35#include <sys/ioctl.h>
37#include <sys/stat.h>
38/* get page info */ 36/* get page info */
39#include <asm/page.h> 37#include <asm/page.h>
40#include "busybox.h" 38#include "busybox.h"
@@ -49,30 +47,13 @@
49#endif 47#endif
50 48
51 49
52typedef struct { 50typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
53 int pid;
54 char user[9];
55 char state[4];
56 unsigned long rss;
57 int ppid;
58#ifdef FEATURE_CPU_USAGE_PERCENTAGE
59 unsigned pcpu;
60 unsigned long stime, utime;
61#endif
62 char *cmd;
63
64 /* basename of executable file in call to exec(2),
65 size from kernel headers */
66 char short_cmd[16];
67} status_t;
68
69typedef int (*cmp_t)(status_t *P, status_t *Q);
70 51
71static status_t *top; /* Hehe */ 52static procps_status_t *top; /* Hehe */
72static int ntop; 53static int ntop;
73 54
74 55
75static int pid_sort (status_t *P, status_t *Q) 56static int pid_sort (procps_status_t *P, procps_status_t *Q)
76{ 57{
77 int p = P->pid; 58 int p = P->pid;
78 int q = Q->pid; 59 int q = Q->pid;
@@ -82,7 +63,7 @@ static int pid_sort (status_t *P, status_t *Q)
82 return 0; 63 return 0;
83} 64}
84 65
85static int mem_sort (status_t *P, status_t *Q) 66static int mem_sort (procps_status_t *P, procps_status_t *Q)
86{ 67{
87 long p = P->rss; 68 long p = P->rss;
88 long q = Q->rss; 69 long q = Q->rss;
@@ -97,7 +78,7 @@ static int mem_sort (status_t *P, status_t *Q)
97#define sort_depth 3 78#define sort_depth 3
98static cmp_t sort_function[sort_depth]; 79static cmp_t sort_function[sort_depth];
99 80
100static int pcpu_sort (status_t *P, status_t *Q) 81static int pcpu_sort (procps_status_t *P, procps_status_t *Q)
101{ 82{
102 int p = P->pcpu; 83 int p = P->pcpu;
103 int q = Q->pcpu; 84 int q = Q->pcpu;
@@ -107,7 +88,7 @@ static int pcpu_sort (status_t *P, status_t *Q)
107 return 0; 88 return 0;
108} 89}
109 90
110static int time_sort (status_t *P, status_t *Q) 91static int time_sort (procps_status_t *P, procps_status_t *Q)
111{ 92{
112 long p = P->stime; 93 long p = P->stime;
113 long q = Q->stime; 94 long q = Q->stime;
@@ -253,7 +234,7 @@ static void do_stats(void)
253 struct timezone timez; 234 struct timezone timez;
254 float elapsed_time; 235 float elapsed_time;
255 236
256 status_t *cur; 237 procps_status_t *cur;
257 int total_time, i, n; 238 int total_time, i, n;
258 static int prev_count; 239 static int prev_count;
259 int systime, usrtime, pid; 240 int systime, usrtime, pid;
@@ -317,7 +298,7 @@ static void do_stats(void)
317 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist, 298 save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,
318 sizeof(struct save_hist)*n); 299 sizeof(struct save_hist)*n);
319 prev_count = n; 300 prev_count = n;
320 qsort(top, n, sizeof(status_t), (void*)mult_lvl_cmp); 301 qsort(top, n, sizeof(procps_status_t), (void*)mult_lvl_cmp);
321} 302}
322#else 303#else
323static cmp_t sort_function; 304static cmp_t sort_function;
@@ -370,7 +351,7 @@ static unsigned long display_generic(void)
370/* display process statuses */ 351/* display process statuses */
371static void display_status(int count, int col) 352static void display_status(int count, int col)
372{ 353{
373 status_t *s = top; 354 procps_status_t *s = top;
374 char rss_str_buf[8]; 355 char rss_str_buf[8];
375 unsigned long total_memory = display_generic(); 356 unsigned long total_memory = display_generic();
376 357
@@ -382,7 +363,7 @@ static void display_status(int count, int col)
382#endif 363#endif
383 364
384 while (count--) { 365 while (count--) {
385 char *namecmd = s->cmd; 366 char *namecmd = s->short_cmd;
386 int pmem; 367 int pmem;
387 368
388 pmem = 1000.0 * s->rss / total_memory; 369 pmem = 1000.0 * s->rss / total_memory;
@@ -402,130 +383,17 @@ static void display_status(int count, int col)
402 s->pcpu/10, s->pcpu%10, 383 s->pcpu/10, s->pcpu%10,
403#endif 384#endif
404 pmem/10, pmem%10); 385 pmem/10, pmem%10);
405 if(namecmd != 0 && namecmd[0] != 0) {
406 if(strlen(namecmd) > col) 386 if(strlen(namecmd) > col)
407 namecmd[col] = 0; 387 namecmd[col] = 0;
408 printf("%s\n", namecmd); 388 printf("%s\n", namecmd);
409 } else {
410 namecmd = s->short_cmd;
411 if(strlen(namecmd) > (col-2))
412 namecmd[col-2] = 0;
413 printf("[%s]\n", namecmd);
414 }
415 s++; 389 s++;
416 } 390 }
417} 391}
418 392
419/* returns true for file names which are PID dirs 393static void clearmems(void)
420 * (i.e. start with number)
421 */
422static int filter_pids(const struct dirent *dir)
423{ 394{
424 char *name = dir->d_name;
425 int n;
426 char status[20];
427 char buf[1024];
428 FILE *fp;
429 status_t curstatus;
430 int pid;
431 long tasknice;
432 struct stat sb;
433
434 if (!(*name >= '0' && *name <= '9'))
435 return 0;
436 if(stat(name, &sb))
437 return 0;
438
439 memset(&curstatus, 0, sizeof(status_t));
440 pid = atoi(name);
441 curstatus.pid = pid;
442
443 my_getpwuid(curstatus.user, sb.st_uid);
444
445 sprintf(status, "%d/stat", pid);
446 if((fp = fopen(status, "r")) == NULL)
447 return 0;
448 name = fgets(buf, sizeof(buf), fp);
449 fclose(fp);
450 if(name == NULL)
451 return 0;
452 name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
453 if(name == 0 || name[1] != ' ')
454 return 0;
455 *name = 0;
456 sscanf(buf, "%*s (%15c", curstatus.short_cmd);
457 n = sscanf(name+2,
458 "%c %d "
459 "%*s %*s %*s %*s " /* pgrp, session, tty, tpgid */
460 "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
461#ifdef FEATURE_CPU_USAGE_PERCENTAGE
462 "%lu %lu "
463#else
464 "%*s %*s "
465#endif
466 "%*s %*s %*s " /* cutime, cstime, priority */
467 "%ld "
468 "%*s %*s %*s " /* timeout, it_real_value, start_time */
469 "%*s " /* vsize */
470 "%ld",
471 curstatus.state, &curstatus.ppid,
472#ifdef FEATURE_CPU_USAGE_PERCENTAGE
473 &curstatus.utime, &curstatus.stime,
474#endif
475 &tasknice,
476 &curstatus.rss);
477#ifdef FEATURE_CPU_USAGE_PERCENTAGE
478 if(n != 6)
479#else
480 if(n != 4)
481#endif
482 return 0;
483
484 if (curstatus.rss == 0 && curstatus.state[0] != 'Z')
485 curstatus.state[1] = 'W';
486 else
487 curstatus.state[1] = ' ';
488 if (tasknice < 0)
489 curstatus.state[2] = '<';
490 else if (tasknice > 0)
491 curstatus.state[2] = 'N';
492 else
493 curstatus.state[2] = ' ';
494
495 curstatus.rss <<= (PAGE_SHIFT - 10); /* 2**10 = 1kb */
496
497 sprintf(status, "%d/cmdline", pid);
498 if((fp = fopen(status, "r")) == NULL)
499 return 0;
500 if(fgets(buf, sizeof(buf), fp) != NULL) {
501 name = strchr(buf, '\n');
502 if(name != NULL)
503 *name = 0;
504 if(buf[0])
505 curstatus.cmd = strdup(buf); /* if NULL it work true also */
506 }
507 fclose(fp);
508
509 n = ntop;
510 top = xrealloc(top, (++ntop)*sizeof(status_t));
511 memcpy(top + n, &curstatus, sizeof(status_t));
512 return 1;
513}
514
515
516static struct dirent **namelist;
517
518static void clearmems(void) {
519 int i;
520
521 for(i = 0; i < ntop; i++) {
522 free(top[i].cmd);
523 free(namelist[i]);
524 }
525 free(top); 395 free(top);
526 free(namelist);
527 top = 0; 396 top = 0;
528 namelist = 0;
529 ntop = 0; 397 ntop = 0;
530} 398}
531 399
@@ -591,7 +459,7 @@ int top_main(int argc, char **argv)
591#else 459#else
592 col = 35; 460 col = 35;
593#endif 461#endif
594 /* change to proc */ 462 /* change to /proc */
595 if (chdir("/proc") < 0) { 463 if (chdir("/proc") < 0) {
596 perror_msg_and_die("chdir('/proc')"); 464 perror_msg_and_die("chdir('/proc')");
597 } 465 }
@@ -631,7 +499,15 @@ int top_main(int argc, char **argv)
631#endif 499#endif
632 while (1) { 500 while (1) {
633 /* read process IDs & status for all the processes */ 501 /* read process IDs & status for all the processes */
634 if (scandir(".", &namelist, filter_pids, 0) < 0) { 502 procps_status_t * p;
503
504 while ((p = procps_scan(0)) != 0) {
505 int n = ntop;
506
507 top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
508 memcpy(top + n, p, sizeof(procps_status_t));
509 }
510 if (ntop == 0) {
635 perror_msg_and_die("scandir('/proc')"); 511 perror_msg_and_die("scandir('/proc')");
636 } 512 }
637#ifdef FEATURE_CPU_USAGE_PERCENTAGE 513#ifdef FEATURE_CPU_USAGE_PERCENTAGE
@@ -644,7 +520,7 @@ int top_main(int argc, char **argv)
644 } 520 }
645 do_stats(); 521 do_stats();
646#else 522#else
647 qsort(top, ntop, sizeof(status_t), (void*)sort_function); 523 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
648#endif 524#endif
649 opt = lines; 525 opt = lines;
650 if (opt > ntop) { 526 if (opt > ntop) {