aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-19 14:46:14 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-19 14:46:14 +0000
commit516a0ca2dc92d9ea103535863102cc5425fe648e (patch)
tree4685bf59c11f898fad44f6e38cde3d16e43c723d
parentc34d35557b0eeb1971b65f7fb10b814295d61734 (diff)
downloadbusybox-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.h17
-rw-r--r--libbb/procps.c30
-rw-r--r--procps/ps.c79
-rw-r--r--shell/hush.c2
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};
839procps_status_t* alloc_procps_scan(int flags); 844procps_status_t* alloc_procps_scan(int flags);
840void free_procps_scan(procps_status_t* sp); 845void 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
35static void func_pid(char *buf, int size, const procps_status_t *ps) 35static 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
40static void func_ppid(char *buf, int size, const procps_status_t *ps) 40static 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
45static void func_pgid(char *buf, int size, const procps_status_t *ps) 45static 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
50static void func_vsz(char *buf, int size, const procps_status_t *ps) 50static 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
57static 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
64static 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/*
58void func_nice(char *buf, int size, const procps_status_t *ps) 69static void func_nice(char *buf, int size, const procps_status_t *ps)
59{ 70{
60 ps->??? 71 ps->???
61} 72}
62 73
63void func_etime(char *buf, int size, const procps_status_t *ps) 74static 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
68void func_time(char *buf, int size, const procps_status_t *ps) 79static 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
73void func_pcpu(char *buf, int size, const procps_status_t *ps) 84static void func_pcpu(char *buf, int size, const procps_status_t *ps)
74{
75}
76
77void func_tty(char *buf, int size, const procps_status_t *ps)
78{ 85{
79} 86}
80*/ 87*/
81 88
82typedef struct { 89typedef 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
90static const ps_out_t out_spec[] = { 97static 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: */