diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-10-22 12:21:15 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-10-22 12:21:15 +0000 |
commit | 44608e9693b03661fbab5e27650bb040c6871d11 (patch) | |
tree | 4555230653cdb82d998f076b29130d8fe18a6f7a | |
parent | 1887b0478f2743ce7808e8b37462e18d584611e1 (diff) | |
download | busybox-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.h | 21 | ||||
-rw-r--r-- | libbb/Makefile.in | 3 | ||||
-rw-r--r-- | libbb/find_pid_by_name.c | 54 | ||||
-rw-r--r-- | libbb/procps.c | 137 | ||||
-rw-r--r-- | procps/kill.c | 6 | ||||
-rw-r--r-- | procps/pidof.c | 13 | ||||
-rw-r--r-- | procps/ps.c | 128 | ||||
-rw-r--r-- | procps/top.c | 170 |
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); |
128 | extern void erase_mtab(const char * name); | 128 | extern void erase_mtab(const char * name); |
129 | extern long atoi_w_units (const char *cp); | 129 | extern long atoi_w_units (const char *cp); |
130 | extern long* find_pid_by_name( char* pidName); | 130 | extern long* find_pid_by_name( const char* pidName); |
131 | extern char *find_real_root_device_name(const char* name); | 131 | extern char *find_real_root_device_name(const char* name); |
132 | extern char *get_line_from_file(FILE *file); | 132 | extern char *get_line_from_file(FILE *file); |
133 | extern void print_file(FILE *file); | 133 | extern void print_file(FILE *file); |
@@ -337,4 +337,23 @@ extern ssize_t xread_all_eof(int fd, void *buf, size_t count); | |||
337 | extern void xread_all(int fd, void *buf, size_t count); | 337 | extern void xread_all(int fd, void *buf, size_t count); |
338 | extern unsigned char xread_char(int fd); | 338 | extern unsigned char xread_char(int fd); |
339 | 339 | ||
340 | typedef 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 | |||
357 | extern 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 | ||
48 | LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) | 49 | LIBBB_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 | */ |
43 | extern long* find_pid_by_name( char* pidName) | 42 | extern 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 | */ |
121 | extern long* find_pid_by_name( char* pidName) | 121 | extern 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 | |||
21 | extern 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 | /* | ||
132 | Local Variables: | ||
133 | c-file-style: "linux" | ||
134 | c-basic-offset: 4 | ||
135 | tab-width: 4 | ||
136 | End: | ||
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 | |||
51 | typedef 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 | |||
62 | static 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 | |||
76 | static 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 | |||
114 | extern int ps_main(int argc, char **argv) | 47 | extern 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 | ||
52 | typedef struct { | 50 | typedef 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 | |||
69 | typedef int (*cmp_t)(status_t *P, status_t *Q); | ||
70 | 51 | ||
71 | static status_t *top; /* Hehe */ | 52 | static procps_status_t *top; /* Hehe */ |
72 | static int ntop; | 53 | static int ntop; |
73 | 54 | ||
74 | 55 | ||
75 | static int pid_sort (status_t *P, status_t *Q) | 56 | static 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 | ||
85 | static int mem_sort (status_t *P, status_t *Q) | 66 | static 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 |
98 | static cmp_t sort_function[sort_depth]; | 79 | static cmp_t sort_function[sort_depth]; |
99 | 80 | ||
100 | static int pcpu_sort (status_t *P, status_t *Q) | 81 | static 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 | ||
110 | static int time_sort (status_t *P, status_t *Q) | 91 | static 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 |
323 | static cmp_t sort_function; | 304 | static cmp_t sort_function; |
@@ -370,7 +351,7 @@ static unsigned long display_generic(void) | |||
370 | /* display process statuses */ | 351 | /* display process statuses */ |
371 | static void display_status(int count, int col) | 352 | static 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 | 393 | static void clearmems(void) |
420 | * (i.e. start with number) | ||
421 | */ | ||
422 | static 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 | |||
516 | static struct dirent **namelist; | ||
517 | |||
518 | static 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) { |