diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-19 14:46:14 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-19 14:46:14 +0000 |
commit | 516a0ca2dc92d9ea103535863102cc5425fe648e (patch) | |
tree | 4685bf59c11f898fad44f6e38cde3d16e43c723d | |
parent | c34d35557b0eeb1971b65f7fb10b814295d61734 (diff) | |
download | busybox-w32-516a0ca2dc92d9ea103535863102cc5425fe648e.tar.gz busybox-w32-516a0ca2dc92d9ea103535863102cc5425fe648e.tar.bz2 busybox-w32-516a0ca2dc92d9ea103535863102cc5425fe648e.zip |
ps: add -o tty and -o rss support
1373 14 24 1411 583 busybox.t1/procps/ps.o
1462 14 24 1500 5dc busybox.t2/procps/ps.o
-rw-r--r-- | include/libbb.h | 17 | ||||
-rw-r--r-- | libbb/procps.c | 30 | ||||
-rw-r--r-- | procps/ps.c | 79 | ||||
-rw-r--r-- | shell/hush.c | 2 |
4 files changed, 80 insertions, 48 deletions
diff --git a/include/libbb.h b/include/libbb.h index 77f1e0a44..31ded7e9c 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -805,7 +805,7 @@ typedef struct { | |||
805 | DIR *dir; | 805 | DIR *dir; |
806 | /* Fields are set to 0/NULL if failed to determine (or not requested) */ | 806 | /* Fields are set to 0/NULL if failed to determine (or not requested) */ |
807 | char *cmd; | 807 | char *cmd; |
808 | unsigned long vsz; | 808 | unsigned vsz, rss; /* we round it to kbytes */ |
809 | unsigned long stime, utime; | 809 | unsigned long stime, utime; |
810 | unsigned pid; | 810 | unsigned pid; |
811 | unsigned ppid; | 811 | unsigned ppid; |
@@ -813,9 +813,10 @@ typedef struct { | |||
813 | unsigned sid; | 813 | unsigned sid; |
814 | unsigned uid; | 814 | unsigned uid; |
815 | unsigned gid; | 815 | unsigned gid; |
816 | /* basename of executable file in call to exec(2), size from */ | ||
817 | /* sizeof(task_struct.comm) in /usr/include/linux/sched.h */ | ||
818 | char state[4]; | 816 | char state[4]; |
817 | char tty_str[8]; /* "maj,min" or "?" */ | ||
818 | /* basename of executable in exec(2), read from /proc/N/stat, */ | ||
819 | /* size from sizeof(task_struct.comm) in /usr/include/linux/sched.h */ | ||
819 | char comm[COMM_LEN]; | 820 | char comm[COMM_LEN]; |
820 | /* user/group? - use passwd/group parsing functions */ | 821 | /* user/group? - use passwd/group parsing functions */ |
821 | } procps_status_t; | 822 | } procps_status_t; |
@@ -829,12 +830,16 @@ enum { | |||
829 | PSSCAN_CMD = 1 << 6, | 830 | PSSCAN_CMD = 1 << 6, |
830 | PSSCAN_STATE = 1 << 7, | 831 | PSSCAN_STATE = 1 << 7, |
831 | PSSCAN_VSZ = 1 << 8, | 832 | PSSCAN_VSZ = 1 << 8, |
832 | PSSCAN_STIME = 1 << 9, | 833 | PSSCAN_RSS = 1 << 9, |
833 | PSSCAN_UTIME = 1 << 10, | 834 | PSSCAN_STIME = 1 << 10, |
835 | PSSCAN_UTIME = 1 << 11, | ||
836 | PSSCAN_TTY = 1 << 12, | ||
834 | /* These are all retrieved from proc/NN/stat in one go: */ | 837 | /* These are all retrieved from proc/NN/stat in one go: */ |
835 | PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID | 838 | PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID |
836 | | PSSCAN_COMM | PSSCAN_STATE | 839 | | PSSCAN_COMM | PSSCAN_STATE |
837 | | PSSCAN_VSZ | PSSCAN_STIME | PSSCAN_UTIME, | 840 | | PSSCAN_VSZ | PSSCAN_RSS |
841 | | PSSCAN_STIME | PSSCAN_UTIME | ||
842 | | PSSCAN_TTY, | ||
838 | }; | 843 | }; |
839 | procps_status_t* alloc_procps_scan(int flags); | 844 | procps_status_t* alloc_procps_scan(int flags); |
840 | void free_procps_scan(procps_status_t* sp); | 845 | void free_procps_scan(procps_status_t* sp); |
diff --git a/libbb/procps.c b/libbb/procps.c index c9dcfde0c..053f7d225 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -144,6 +144,9 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags) | |||
144 | 144 | ||
145 | if (flags & PSSCAN_STAT) { | 145 | if (flags & PSSCAN_STAT) { |
146 | char *cp; | 146 | char *cp; |
147 | unsigned long vsz, rss; | ||
148 | int tty; | ||
149 | |||
147 | /* see proc(5) for some details on this */ | 150 | /* see proc(5) for some details on this */ |
148 | strcpy(filename_tail, "/stat"); | 151 | strcpy(filename_tail, "/stat"); |
149 | n = read_to_buf(filename, buf); | 152 | n = read_to_buf(filename, buf); |
@@ -158,33 +161,46 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags) | |||
158 | sscanf(buf, "%*s (%15c", sp->comm); | 161 | sscanf(buf, "%*s (%15c", sp->comm); |
159 | n = sscanf(cp+2, | 162 | n = sscanf(cp+2, |
160 | "%c %u " /* state, ppid */ | 163 | "%c %u " /* state, ppid */ |
161 | "%u %u %*s %*s " /* pgid, sid, tty, tpgid */ | 164 | "%u %u %d %*s " /* pgid, sid, tty, tpgid */ |
162 | "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ | 165 | "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ |
163 | "%lu %lu " /* utime, stime */ | 166 | "%lu %lu " /* utime, stime */ |
164 | "%*s %*s %*s " /* cutime, cstime, priority */ | 167 | "%*s %*s %*s " /* cutime, cstime, priority */ |
165 | "%ld " /* nice */ | 168 | "%ld " /* nice */ |
166 | "%*s %*s %*s " /* timeout, it_real_value, start_time */ | 169 | "%*s %*s %*s " /* timeout, it_real_value, start_time */ |
167 | "%lu ", /* vsize */ | 170 | "%lu " /* vsize */ |
171 | "%lu " /* rss */ | ||
172 | /* "%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ | ||
173 | /* "%u %u %u %u " signal, blocked, sigignore, sigcatch */ | ||
174 | /* "%lu %lu %lu" wchan, nswap, cnswap */ | ||
175 | , | ||
168 | sp->state, &sp->ppid, | 176 | sp->state, &sp->ppid, |
169 | &sp->pgid, &sp->sid, | 177 | &sp->pgid, &sp->sid, &tty, |
170 | &sp->utime, &sp->stime, | 178 | &sp->utime, &sp->stime, |
171 | &tasknice, | 179 | &tasknice, |
172 | &sp->vsz); | 180 | &vsz, |
173 | if (n != 8) | 181 | &rss); |
182 | if (n != 10) | ||
174 | break; | 183 | break; |
175 | 184 | ||
185 | sp->tty_str[0] = '?'; | ||
186 | /* sp->tty_str[1] = '\0'; - done by memset */ | ||
187 | if (tty >= 0) /* tty field of "-1" means "no tty" */ | ||
188 | snprintf(sp->tty_str, sizeof(sp->tty_str), "%u,%u", | ||
189 | (tty >> 8) & 0xfff, /* major */ | ||
190 | (tty & 0xff) | ((tty >> 12) & 0xfff00)); | ||
176 | if (sp->vsz == 0 && sp->state[0] != 'Z') | 191 | if (sp->vsz == 0 && sp->state[0] != 'Z') |
177 | sp->state[1] = 'W'; | 192 | sp->state[1] = 'W'; |
178 | else | 193 | else |
179 | sp->state[1] = ' '; | 194 | sp->state[1] = ' '; |
180 | if (tasknice < 0) | 195 | if (tasknice < 0) |
181 | sp->state[2] = '<'; | 196 | sp->state[2] = '<'; |
182 | else if (tasknice > 0) | 197 | else if (tasknice) /* > 0 */ |
183 | sp->state[2] = 'N'; | 198 | sp->state[2] = 'N'; |
184 | else | 199 | else |
185 | sp->state[2] = ' '; | 200 | sp->state[2] = ' '; |
186 | 201 | ||
187 | sp->vsz >>= 10; /* vsize is in bytes and we want kb */ | 202 | sp->vsz = vsz >> 10; /* vsize is in bytes and we want kb */ |
203 | sp->rss = rss >> 10; | ||
188 | } | 204 | } |
189 | 205 | ||
190 | if (flags & PSSCAN_CMD) { | 206 | if (flags & PSSCAN_CMD) { |
diff --git a/procps/ps.c b/procps/ps.c index f8f5c1aa9..0c9b71e09 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -29,83 +29,90 @@ static void func_args(char *buf, int size, const procps_status_t *ps) | |||
29 | if (ps->cmd) | 29 | if (ps->cmd) |
30 | safe_strncpy(buf, ps->cmd, size+1); | 30 | safe_strncpy(buf, ps->cmd, size+1); |
31 | else if (size >= 2) | 31 | else if (size >= 2) |
32 | snprintf(buf, size+1, "[%.*s]", size-2, ps->comm); | 32 | sprintf(buf, "[%.*s]", size-2, ps->comm); |
33 | } | 33 | } |
34 | 34 | ||
35 | static void func_pid(char *buf, int size, const procps_status_t *ps) | 35 | static void func_pid(char *buf, int size, const procps_status_t *ps) |
36 | { | 36 | { |
37 | snprintf(buf, size+1, "%*u", size, ps->pid); | 37 | sprintf(buf, "%*u", size, ps->pid); |
38 | } | 38 | } |
39 | 39 | ||
40 | static void func_ppid(char *buf, int size, const procps_status_t *ps) | 40 | static void func_ppid(char *buf, int size, const procps_status_t *ps) |
41 | { | 41 | { |
42 | snprintf(buf, size+1, "%*u", size, ps->ppid); | 42 | sprintf(buf, "%*u", size, ps->ppid); |
43 | } | 43 | } |
44 | 44 | ||
45 | static void func_pgid(char *buf, int size, const procps_status_t *ps) | 45 | static void func_pgid(char *buf, int size, const procps_status_t *ps) |
46 | { | 46 | { |
47 | snprintf(buf, size+1, "%*u", size, ps->pgid); | 47 | sprintf(buf, "%*u", size, ps->pgid); |
48 | } | 48 | } |
49 | 49 | ||
50 | static void func_vsz(char *buf, int size, const procps_status_t *ps) | 50 | static void func_vsz(char *buf, int size, const procps_status_t *ps) |
51 | { | 51 | { |
52 | char buf5[5]; | 52 | char buf5[5]; |
53 | smart_ulltoa5( ((unsigned long long)ps->vsz) << 10, buf5); | 53 | smart_ulltoa5( ((unsigned long long)ps->vsz) << 10, buf5); |
54 | snprintf(buf, size+1, "%.*s", size, buf5); | 54 | sprintf(buf, "%.*s", size, buf5); |
55 | } | 55 | } |
56 | 56 | ||
57 | static void func_rss(char *buf, int size, const procps_status_t *ps) | ||
58 | { | ||
59 | char buf5[5]; | ||
60 | smart_ulltoa5( ((unsigned long long)ps->rss) << 10, buf5); | ||
61 | sprintf(buf, "%.*s", size, buf5); | ||
62 | } | ||
63 | |||
64 | static void func_tty(char *buf, int size, const procps_status_t *ps) | ||
65 | { | ||
66 | safe_strncpy(buf, ps->tty_str, size+1); | ||
67 | } | ||
57 | /* | 68 | /* |
58 | void func_nice(char *buf, int size, const procps_status_t *ps) | 69 | static void func_nice(char *buf, int size, const procps_status_t *ps) |
59 | { | 70 | { |
60 | ps->??? | 71 | ps->??? |
61 | } | 72 | } |
62 | 73 | ||
63 | void func_etime(char *buf, int size, const procps_status_t *ps) | 74 | static void func_etime(char *buf, int size, const procps_status_t *ps) |
64 | { | 75 | { |
65 | elapled time [[dd-]hh:]mm:ss | 76 | elapled time [[dd-]hh:]mm:ss |
66 | } | 77 | } |
67 | 78 | ||
68 | void func_time(char *buf, int size, const procps_status_t *ps) | 79 | static void func_time(char *buf, int size, const procps_status_t *ps) |
69 | { | 80 | { |
70 | cumulative time [[dd-]hh:]mm:ss | 81 | cumulative time [[dd-]hh:]mm:ss |
71 | } | 82 | } |
72 | 83 | ||
73 | void func_pcpu(char *buf, int size, const procps_status_t *ps) | 84 | static void func_pcpu(char *buf, int size, const procps_status_t *ps) |
74 | { | ||
75 | } | ||
76 | |||
77 | void func_tty(char *buf, int size, const procps_status_t *ps) | ||
78 | { | 85 | { |
79 | } | 86 | } |
80 | */ | 87 | */ |
81 | 88 | ||
82 | typedef struct { | 89 | typedef struct { |
83 | char name[8]; | 90 | uint16_t width; |
91 | char name[6]; | ||
84 | const char *header; | 92 | const char *header; |
85 | void (*f)(char *buf, int size, const procps_status_t *ps); | 93 | void (*f)(char *buf, int size, const procps_status_t *ps); |
86 | int ps_flags; | 94 | int ps_flags; |
87 | int width; | ||
88 | } ps_out_t; | 95 | } ps_out_t; |
89 | 96 | ||
90 | static const ps_out_t out_spec[] = { | 97 | static const ps_out_t out_spec[] = { |
91 | // Mandated by POSIX: | 98 | // Mandated by POSIX: |
92 | { "user" ,"USER" ,func_user ,PSSCAN_UIDGID,8 }, | 99 | { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, |
93 | { "comm" ,"COMMAND",func_comm ,PSSCAN_COMM ,16 }, | 100 | { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, |
94 | { "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM,256 }, | 101 | { 256 , "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM }, |
95 | { "pid" ,"PID" ,func_pid ,PSSCAN_PID ,5 }, | 102 | { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, |
96 | { "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID ,5 }, | 103 | { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, |
97 | { "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID ,5 }, | 104 | { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, |
98 | // { "etime" ,"ELAPSED",func_etime ,PSSCAN_ ,sizeof("ELAPSED")-1 }, | 105 | // { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, |
99 | // { "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID,sizeof("GROUP" )-1 }, | 106 | // { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, |
100 | // { "nice" ,"NI" ,func_nice ,PSSCAN_ ,sizeof("NI" )-1 }, | 107 | // { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, |
101 | // { "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ ,sizeof("%CPU" )-1 }, | 108 | // { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, |
102 | // { "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID,sizeof("RGROUP" )-1 }, | 109 | // { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, |
103 | // { "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID,sizeof("RUSER" )-1 }, | 110 | // { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, |
104 | // { "time" ,"TIME" ,func_time ,PSSCAN_ ,sizeof("TIME" )-1 }, | 111 | // { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, |
105 | // { "tty" ,"TT" ,func_tty ,PSSCAN_ ,sizeof("TT" )-1 }, | 112 | { sizeof("TT" )-1, "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, |
106 | { "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ ,4 }, | 113 | { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, |
107 | // Not mandated by POSIX: | 114 | // Not mandated by POSIX, but useful: |
108 | // { "rss" ,"RSS" ,func_rss ,PSSCAN_RSS ,4 }, | 115 | { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS }, |
109 | }; | 116 | }; |
110 | 117 | ||
111 | #define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) ) | 118 | #define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) ) |
@@ -152,6 +159,8 @@ static void parse_o(char* opt) | |||
152 | } | 159 | } |
153 | break; | 160 | break; |
154 | } | 161 | } |
162 | // opt points to last spec in comma separated list. | ||
163 | // This one can have =HEADER part. | ||
155 | new = new_out_t(); | 164 | new = new_out_t(); |
156 | if (equal) | 165 | if (equal) |
157 | *equal = '\0'; | 166 | *equal = '\0'; |
@@ -190,9 +199,11 @@ static void format_header(void) | |||
190 | { | 199 | { |
191 | int i; | 200 | int i; |
192 | ps_out_t* op; | 201 | ps_out_t* op; |
193 | char *p = buffer; | 202 | char *p; |
203 | |||
194 | if (!print_header) | 204 | if (!print_header) |
195 | return; | 205 | return; |
206 | p = buffer; | ||
196 | i = 0; | 207 | i = 0; |
197 | if (out_cnt) { | 208 | if (out_cnt) { |
198 | while (1) { | 209 | while (1) { |
@@ -248,7 +259,7 @@ int ps_main(int argc, char **argv) | |||
248 | // -f Generate a full listing | 259 | // -f Generate a full listing |
249 | // -l Generate a long listing | 260 | // -l Generate a long listing |
250 | // -o col1,col2,col3=header | 261 | // -o col1,col2,col3=header |
251 | // Select which columns to distplay | 262 | // Select which columns to display |
252 | /* We allow (and ignore) most of the above. FIXME */ | 263 | /* We allow (and ignore) most of the above. FIXME */ |
253 | opt_complementary = "o::"; | 264 | opt_complementary = "o::"; |
254 | getopt32(argc, argv, "o:aAdefl", &opt_o); | 265 | getopt32(argc, argv, "o:aAdefl", &opt_o); |
diff --git a/shell/hush.c b/shell/hush.c index 08357ca77..56f2728f5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -306,7 +306,7 @@ static void __syntax(const char *file, int line) | |||
306 | { | 306 | { |
307 | bb_error_msg("syntax error %s:%d", file, line); | 307 | bb_error_msg("syntax error %s:%d", file, line); |
308 | } | 308 | } |
309 | // NB: was __FILE__, but that produces full path sometimess, so... | 309 | // NB: was __FILE__, but that produces full path sometimes, so... |
310 | #define syntax() __syntax("hush.c", __LINE__) | 310 | #define syntax() __syntax("hush.c", __LINE__) |
311 | 311 | ||
312 | /* Index of subroutines: */ | 312 | /* Index of subroutines: */ |