aboutsummaryrefslogtreecommitdiff
path: root/procps/ps.c
diff options
context:
space:
mode:
Diffstat (limited to 'procps/ps.c')
-rw-r--r--procps/ps.c216
1 files changed, 171 insertions, 45 deletions
diff --git a/procps/ps.c b/procps/ps.c
index 08922ebb6..a6c35f101 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -16,6 +16,143 @@ enum { MAX_WIDTH = 2*1024 };
16 16
17#if ENABLE_DESKTOP 17#if ENABLE_DESKTOP
18 18
19#include <sys/times.h> /* for times() */
20//#include <sys/sysinfo.h> /* for sysinfo() */
21#ifndef AT_CLKTCK
22#define AT_CLKTCK 17
23#endif
24
25
26#if ENABLE_SELINUX
27#define SELINIX_O_PREFIX "label,"
28#define DEFAULT_O_STR (SELINIX_O_PREFIX "pid,user" USE_FEATURE_PS_TIME(",time"))
29#else
30#define DEFAULT_O_STR ("pid,user" USE_FEATURE_PS_TIME(",time"))
31#endif
32
33typedef struct {
34 uint16_t width;
35 char name[6];
36 const char *header;
37 void (*f)(char *buf, int size, const procps_status_t *ps);
38 int ps_flags;
39} ps_out_t;
40
41struct globals {
42 ps_out_t* out;
43 int out_cnt;
44 int print_header;
45 int need_flags;
46 char *buffer;
47 unsigned terminal_width;
48#if ENABLE_FEATURE_PS_TIME
49 unsigned kernel_HZ;
50 unsigned long long seconds_since_boot;
51#endif
52 char default_o[sizeof(DEFAULT_O_STR)];
53};
54#define G (*(struct globals*)&bb_common_bufsiz1)
55#define out (G.out )
56#define out_cnt (G.out_cnt )
57#define print_header (G.print_header )
58#define need_flags (G.need_flags )
59#define buffer (G.buffer )
60#define terminal_width (G.terminal_width )
61#define kernel_HZ (G.kernel_HZ )
62#define seconds_since_boot (G.seconds_since_boot)
63#define default_o (G.default_o )
64
65#if ENABLE_FEATURE_PS_TIME
66/* for ELF executables, notes are pushed before environment and args */
67static ptrdiff_t find_elf_note(ptrdiff_t findme)
68{
69 ptrdiff_t *ep = (ptrdiff_t *) environ;
70
71 while (*ep++);
72 while (*ep) {
73 if (ep[0] == findme) {
74 return ep[1];
75 }
76 ep += 2;
77 }
78 return -1;
79}
80
81#if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS
82static unsigned get_HZ_by_waiting(void)
83{
84 struct timeval tv1, tv2;
85 unsigned t1, t2, r, hz;
86 unsigned cnt = cnt; /* for compiler */
87 int diff;
88
89 r = 0;
90
91 /* Wait for times() to reach new tick */
92 t1 = times(NULL);
93 do {
94 t2 = times(NULL);
95 } while (t2 == t1);
96 gettimeofday(&tv2, NULL);
97
98 do {
99 t1 = t2;
100 tv1.tv_usec = tv2.tv_usec;
101
102 /* Wait exactly one times() tick */
103 do {
104 t2 = times(NULL);
105 } while (t2 == t1);
106 gettimeofday(&tv2, NULL);
107
108 /* Calculate ticks per sec, rounding up to even */
109 diff = tv2.tv_usec - tv1.tv_usec;
110 if (diff <= 0) diff += 1000000;
111 hz = 1000000u / (unsigned)diff;
112 hz = (hz+1) & ~1;
113
114 /* Count how many same hz values we saw */
115 if (r != hz) {
116 r = hz;
117 cnt = 0;
118 }
119 cnt++;
120 } while (cnt < 3); /* exit if saw 3 same values */
121
122 return r;
123}
124#else
125static inline unsigned get_HZ_by_waiting(void)
126{
127 /* Better method? */
128 return 100;
129}
130#endif
131
132static unsigned get_kernel_HZ(void)
133{
134 //char buf[64];
135 struct sysinfo info;
136
137 if (kernel_HZ)
138 return kernel_HZ;
139
140 /* Works for ELF only, Linux 2.4.0+ */
141 kernel_HZ = find_elf_note(AT_CLKTCK);
142 if (kernel_HZ == (unsigned)-1)
143 kernel_HZ = get_HZ_by_waiting();
144
145 //if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0)
146 // bb_perror_msg_and_die("cannot read %s", "/proc/uptime");
147 //buf[sizeof(buf)-1] = '\0';
148 ///sscanf(buf, "%llu", &seconds_since_boot);
149 sysinfo(&info);
150 seconds_since_boot = info.uptime;
151
152 return kernel_HZ;
153}
154#endif
155
19/* Print value to buf, max size+1 chars (including trailing '\0') */ 156/* Print value to buf, max size+1 chars (including trailing '\0') */
20 157
21static void func_user(char *buf, int size, const procps_status_t *ps) 158static void func_user(char *buf, int size, const procps_status_t *ps)
@@ -73,6 +210,34 @@ static void func_tty(char *buf, int size, const procps_status_t *ps)
73 snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor); 210 snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
74} 211}
75 212
213#if ENABLE_FEATURE_PS_TIME
214static void func_etime(char *buf, int size, const procps_status_t *ps)
215{
216 /* elapsed time [[dd-]hh:]mm:ss; here only mm:ss */
217 unsigned long mm;
218 unsigned ss;
219
220 mm = ps->start_time / get_kernel_HZ();
221 /* must be after get_kernel_HZ()! */
222 mm = seconds_since_boot - mm;
223 ss = mm % 60;
224 mm /= 60;
225 snprintf(buf, size+1, "%3lu:%02u", mm, ss);
226}
227
228static void func_time(char *buf, int size, const procps_status_t *ps)
229{
230 /* cumulative time [[dd-]hh:]mm:ss; here only mm:ss */
231 unsigned long mm;
232 unsigned ss;
233
234 mm = (ps->utime + ps->stime) / get_kernel_HZ();
235 ss = mm % 60;
236 mm /= 60;
237 snprintf(buf, size+1, "%3lu:%02u", mm, ss);
238}
239#endif
240
76#if ENABLE_SELINUX 241#if ENABLE_SELINUX
77static void func_label(char *buf, int size, const procps_status_t *ps) 242static void func_label(char *buf, int size, const procps_status_t *ps)
78{ 243{
@@ -86,29 +251,11 @@ static void func_nice(char *buf, int size, const procps_status_t *ps)
86 ps->??? 251 ps->???
87} 252}
88 253
89static void func_etime(char *buf, int size, const procps_status_t *ps)
90{
91 elapled time [[dd-]hh:]mm:ss
92}
93
94static void func_time(char *buf, int size, const procps_status_t *ps)
95{
96 cumulative time [[dd-]hh:]mm:ss
97}
98
99static void func_pcpu(char *buf, int size, const procps_status_t *ps) 254static void func_pcpu(char *buf, int size, const procps_status_t *ps)
100{ 255{
101} 256}
102*/ 257*/
103 258
104typedef struct {
105 uint16_t width;
106 char name[6];
107 const char *header;
108 void (*f)(char *buf, int size, const procps_status_t *ps);
109 int ps_flags;
110} ps_out_t;
111
112static const ps_out_t out_spec[] = { 259static const ps_out_t out_spec[] = {
113// Mandated by POSIX: 260// Mandated by POSIX:
114 { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, 261 { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID },
@@ -117,13 +264,17 @@ static const ps_out_t out_spec[] = {
117 { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, 264 { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID },
118 { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, 265 { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID },
119 { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, 266 { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID },
120// { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, 267#if ENABLE_FEATURE_PS_TIME
268 { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME },
269#endif
121// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, 270// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
122// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, 271// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ },
123// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, 272// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ },
124// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, 273// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID },
125// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, 274// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID },
126// { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, 275#if ENABLE_FEATURE_PS_TIME
276 { 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME },
277#endif
127 { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, 278 { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY },
128 { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, 279 { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ },
129// Not mandated by POSIX, but useful: 280// Not mandated by POSIX, but useful:
@@ -133,31 +284,6 @@ static const ps_out_t out_spec[] = {
133#endif 284#endif
134}; 285};
135 286
136#if ENABLE_SELINUX
137#define SELINIX_O_PREFIX "label,"
138#define DEFAULT_O_STR SELINIX_O_PREFIX "pid,user" /* TODO: ,vsz,stat */ ",args"
139#else
140#define DEFAULT_O_STR "pid,user" /* TODO: ,vsz,stat */ ",args"
141#endif
142
143struct globals {
144 ps_out_t* out;
145 int out_cnt;
146 int print_header;
147 int need_flags;
148 char *buffer;
149 unsigned terminal_width;
150 char default_o[sizeof(DEFAULT_O_STR)];
151};
152#define G (*(struct globals*)&bb_common_bufsiz1)
153#define out (G.out )
154#define out_cnt (G.out_cnt )
155#define print_header (G.print_header )
156#define need_flags (G.need_flags )
157#define buffer (G.buffer )
158#define terminal_width (G.terminal_width)
159#define default_o (G.default_o )
160
161static ps_out_t* new_out_t(void) 287static ps_out_t* new_out_t(void)
162{ 288{
163 int i = out_cnt++; 289 int i = out_cnt++;