17 |
#if ENABLE_DESKTOP |
#if ENABLE_DESKTOP |
18 |
|
|
19 |
#include <sys/times.h> /* for times() */ |
#include <sys/times.h> /* for times() */ |
|
//#include <sys/sysinfo.h> /* for sysinfo() */ |
|
20 |
#ifndef AT_CLKTCK |
#ifndef AT_CLKTCK |
21 |
#define AT_CLKTCK 17 |
#define AT_CLKTCK 17 |
22 |
#endif |
#endif |
24 |
|
|
25 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
26 |
#define SELINUX_O_PREFIX "label," |
#define SELINUX_O_PREFIX "label," |
27 |
#define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" USE_FEATURE_PS_TIME(",time") ",args") |
#define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args") |
28 |
#else |
#else |
29 |
#define DEFAULT_O_STR ("pid,user" USE_FEATURE_PS_TIME(",time") ",args") |
#define DEFAULT_O_STR ("pid,user" IF_FEATURE_PS_TIME(",time") ",args") |
30 |
#endif |
#endif |
31 |
|
|
32 |
typedef struct { |
typedef struct { |
33 |
uint16_t width; |
uint16_t width; |
34 |
char name[6]; |
char name6[6]; |
35 |
const char *header; |
const char *header; |
36 |
void (*f)(char *buf, int size, const procps_status_t *ps); |
void (*f)(char *buf, int size, const procps_status_t *ps); |
37 |
int ps_flags; |
int ps_flags; |
60 |
#define kernel_HZ (G.kernel_HZ ) |
#define kernel_HZ (G.kernel_HZ ) |
61 |
#define seconds_since_boot (G.seconds_since_boot) |
#define seconds_since_boot (G.seconds_since_boot) |
62 |
#define default_o (G.default_o ) |
#define default_o (G.default_o ) |
63 |
|
#define INIT_G() do { } while (0) |
64 |
|
|
65 |
#if ENABLE_FEATURE_PS_TIME |
#if ENABLE_FEATURE_PS_TIME |
66 |
/* for ELF executables, notes are pushed before environment and args */ |
/* for ELF executables, notes are pushed before environment and args */ |
143 |
kernel_HZ = get_HZ_by_waiting(); |
kernel_HZ = get_HZ_by_waiting(); |
144 |
|
|
145 |
//if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0) |
//if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0) |
146 |
// bb_perror_msg_and_die("cannot read %s", "/proc/uptime"); |
// bb_perror_msg_and_die("can't read %s", "/proc/uptime"); |
147 |
//buf[sizeof(buf)-1] = '\0'; |
//buf[sizeof(buf)-1] = '\0'; |
148 |
///sscanf(buf, "%llu", &seconds_since_boot); |
///sscanf(buf, "%llu", &seconds_since_boot); |
149 |
sysinfo(&info); |
sysinfo(&info); |
174 |
#endif |
#endif |
175 |
} |
} |
176 |
|
|
177 |
|
static void func_group(char *buf, int size, const procps_status_t *ps) |
178 |
|
{ |
179 |
|
safe_strncpy(buf, get_cached_groupname(ps->gid), size+1); |
180 |
|
} |
181 |
|
|
182 |
static void func_comm(char *buf, int size, const procps_status_t *ps) |
static void func_comm(char *buf, int size, const procps_status_t *ps) |
183 |
{ |
{ |
184 |
safe_strncpy(buf, ps->comm, size+1); |
safe_strncpy(buf, ps->comm, size+1); |
186 |
|
|
187 |
static void func_args(char *buf, int size, const procps_status_t *ps) |
static void func_args(char *buf, int size, const procps_status_t *ps) |
188 |
{ |
{ |
189 |
read_cmdline(buf, size, ps->pid, ps->comm); |
read_cmdline(buf, size+1, ps->pid, ps->comm); |
190 |
} |
} |
191 |
|
|
192 |
static void func_pid(char *buf, int size, const procps_status_t *ps) |
static void func_pid(char *buf, int size, const procps_status_t *ps) |
232 |
snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor); |
snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor); |
233 |
} |
} |
234 |
|
|
235 |
|
|
236 |
|
#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS |
237 |
|
|
238 |
|
static void func_rgroup(char *buf, int size, const procps_status_t *ps) |
239 |
|
{ |
240 |
|
safe_strncpy(buf, get_cached_groupname(ps->rgid), size+1); |
241 |
|
} |
242 |
|
|
243 |
|
static void func_ruser(char *buf, int size, const procps_status_t *ps) |
244 |
|
{ |
245 |
|
safe_strncpy(buf, get_cached_username(ps->ruid), size+1); |
246 |
|
} |
247 |
|
|
248 |
|
static void func_nice(char *buf, int size, const procps_status_t *ps) |
249 |
|
{ |
250 |
|
sprintf(buf, "%*d", size, ps->niceness); |
251 |
|
} |
252 |
|
|
253 |
|
#endif /* FEATURE_PS_ADDITIONAL_COLUMNS */ |
254 |
|
|
255 |
#if ENABLE_FEATURE_PS_TIME |
#if ENABLE_FEATURE_PS_TIME |
256 |
static void func_etime(char *buf, int size, const procps_status_t *ps) |
static void func_etime(char *buf, int size, const procps_status_t *ps) |
257 |
{ |
{ |
301 |
static const ps_out_t out_spec[] = { |
static const ps_out_t out_spec[] = { |
302 |
// Mandated by POSIX: |
// Mandated by POSIX: |
303 |
{ 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, |
{ 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, |
304 |
|
{ 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, |
305 |
{ 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, |
{ 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, |
306 |
{ 256 , "args" ,"COMMAND",func_args ,PSSCAN_COMM }, |
{ MAX_WIDTH , "args" ,"COMMAND",func_args ,PSSCAN_COMM }, |
307 |
{ 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, |
{ 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, |
308 |
{ 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, |
{ 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, |
309 |
{ 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, |
{ 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, |
310 |
#if ENABLE_FEATURE_PS_TIME |
#if ENABLE_FEATURE_PS_TIME |
311 |
{ sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME }, |
{ sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME }, |
312 |
#endif |
#endif |
313 |
// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, |
#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS |
314 |
// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, |
{ 5 , "nice" ,"NI" ,func_nice ,PSSCAN_NICE }, |
315 |
// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, |
{ 8 , "rgroup","RGROUP" ,func_rgroup,PSSCAN_RUIDGID }, |
316 |
// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, |
{ 8 , "ruser" ,"RUSER" ,func_ruser ,PSSCAN_RUIDGID }, |
317 |
// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, |
// { 5 , "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, |
318 |
|
#endif |
319 |
#if ENABLE_FEATURE_PS_TIME |
#if ENABLE_FEATURE_PS_TIME |
320 |
{ 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME }, |
{ 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME }, |
321 |
#endif |
#endif |
338 |
{ |
{ |
339 |
unsigned i; |
unsigned i; |
340 |
for (i = 0; i < ARRAY_SIZE(out_spec); i++) { |
for (i = 0; i < ARRAY_SIZE(out_spec); i++) { |
341 |
if (!strcmp(name, out_spec[i].name)) |
if (!strncmp(name, out_spec[i].name6, 6)) |
342 |
return &out_spec[i]; |
return &out_spec[i]; |
343 |
} |
} |
344 |
bb_error_msg_and_die("bad -o argument '%s'", name); |
bb_error_msg_and_die("bad -o argument '%s'", name); |
383 |
print_header = 1; |
print_header = 1; |
384 |
} |
} |
385 |
|
|
386 |
static void post_process(void) |
static void alloc_line_buffer(void) |
387 |
{ |
{ |
388 |
int i; |
int i; |
389 |
int width = 0; |
int width = 0; |
393 |
print_header = 1; |
print_header = 1; |
394 |
} |
} |
395 |
width += out[i].width + 1; /* "FIELD " */ |
width += out[i].width + 1; /* "FIELD " */ |
396 |
|
if ((int)(width - terminal_width) > 0) { |
397 |
|
/* The rest does not fit on the screen */ |
398 |
|
//out[i].width -= (width - terminal_width - 1); |
399 |
|
out_cnt = i + 1; |
400 |
|
break; |
401 |
|
} |
402 |
} |
} |
403 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
404 |
if (!is_selinux_enabled()) |
if (!is_selinux_enabled()) |
458 |
{ |
{ |
459 |
procps_status_t *p; |
procps_status_t *p; |
460 |
llist_t* opt_o = NULL; |
llist_t* opt_o = NULL; |
461 |
USE_SELINUX(int opt;) |
int opt; |
462 |
|
enum { |
463 |
|
OPT_Z = (1 << 0), |
464 |
|
OPT_o = (1 << 1), |
465 |
|
OPT_a = (1 << 2), |
466 |
|
OPT_A = (1 << 3), |
467 |
|
OPT_d = (1 << 4), |
468 |
|
OPT_e = (1 << 5), |
469 |
|
OPT_f = (1 << 6), |
470 |
|
OPT_l = (1 << 7), |
471 |
|
OPT_T = (1 << 8) * ENABLE_FEATURE_SHOW_THREADS, |
472 |
|
}; |
473 |
|
|
474 |
|
INIT_G(); |
475 |
|
|
476 |
// POSIX: |
// POSIX: |
477 |
// -a Write information for all processes associated with terminals |
// -a Write information for all processes associated with terminals |
478 |
// Implementations may omit session leaders from this list |
// Implementations may omit session leaders from this list |
479 |
// -A Write information for all processes |
// -A Write information for all processes |
480 |
// -d Write information for all processes, except session leaders |
// -d Write information for all processes, except session leaders |
481 |
// -e Write information for all processes (equivalent to -A.) |
// -e Write information for all processes (equivalent to -A) |
482 |
// -f Generate a full listing |
// -f Generate a full listing |
483 |
// -l Generate a long listing |
// -l Generate a long listing |
484 |
// -o col1,col2,col3=header |
// -o col1,col2,col3=header |
485 |
// Select which columns to display |
// Select which columns to display |
486 |
/* We allow (and ignore) most of the above. FIXME */ |
/* We allow (and ignore) most of the above. FIXME. |
487 |
|
* -T is picked for threads (POSIX hasn't it standardized). |
488 |
|
* procps v3.2.7 supports -T and shows tids as SPID column, |
489 |
|
* it also supports -L where it shows tids as LWP column. |
490 |
|
*/ |
491 |
opt_complementary = "o::"; |
opt_complementary = "o::"; |
492 |
USE_SELINUX(opt =) getopt32(argv, "Zo:aAdefl", &opt_o); |
opt = getopt32(argv, "Zo:aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o); |
493 |
if (opt_o) { |
if (opt_o) { |
494 |
do { |
do { |
495 |
parse_o(llist_pop(&opt_o)); |
parse_o(llist_pop(&opt_o)); |
497 |
} else { |
} else { |
498 |
/* Below: parse_o() needs char*, NOT const char*... */ |
/* Below: parse_o() needs char*, NOT const char*... */ |
499 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
500 |
if (!(opt & 1) || !is_selinux_enabled()) { |
if (!(opt & OPT_Z) || !is_selinux_enabled()) { |
501 |
/* no -Z or no SELinux: do not show LABEL */ |
/* no -Z or no SELinux: do not show LABEL */ |
502 |
strcpy(default_o, DEFAULT_O_STR + sizeof(SELINUX_O_PREFIX)-1); |
strcpy(default_o, DEFAULT_O_STR + sizeof(SELINUX_O_PREFIX)-1); |
503 |
} else |
} else |
507 |
} |
} |
508 |
parse_o(default_o); |
parse_o(default_o); |
509 |
} |
} |
510 |
post_process(); |
#if ENABLE_FEATURE_SHOW_THREADS |
511 |
|
if (opt & OPT_T) |
512 |
|
need_flags |= PSSCAN_TASKS; |
513 |
|
#endif |
514 |
|
|
515 |
/* Was INT_MAX, but some libc's go belly up with printf("%.*s") |
/* Was INT_MAX, but some libc's go belly up with printf("%.*s") |
516 |
* and such large widths */ |
* and such large widths */ |
520 |
if (--terminal_width > MAX_WIDTH) |
if (--terminal_width > MAX_WIDTH) |
521 |
terminal_width = MAX_WIDTH; |
terminal_width = MAX_WIDTH; |
522 |
} |
} |
523 |
|
alloc_line_buffer(); |
524 |
format_header(); |
format_header(); |
525 |
|
|
526 |
p = NULL; |
p = NULL; |
527 |
while ((p = procps_scan(p, need_flags))) { |
while ((p = procps_scan(p, need_flags)) != NULL) { |
528 |
format_process(p); |
format_process(p); |
529 |
} |
} |
530 |
|
|
538 |
int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
539 |
int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
540 |
{ |
{ |
541 |
procps_status_t *p = NULL; |
procps_status_t *p; |
542 |
int len; |
int len; |
543 |
SKIP_SELINUX(const) int use_selinux = 0; |
int psscan_flags = PSSCAN_PID | PSSCAN_UIDGID |
544 |
USE_SELINUX(int i;) |
| PSSCAN_STATE | PSSCAN_VSZ | PSSCAN_COMM; |
545 |
#if !ENABLE_FEATURE_PS_WIDE |
#if !ENABLE_FEATURE_PS_WIDE |
546 |
enum { terminal_width = 79 }; |
enum { terminal_width = 79 }; |
547 |
#else |
#else |
548 |
unsigned terminal_width; |
unsigned terminal_width; |
|
int w_count = 0; |
|
549 |
#endif |
#endif |
550 |
|
|
551 |
#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX |
#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX |
552 |
#if ENABLE_FEATURE_PS_WIDE |
int opts; |
553 |
|
# if ENABLE_FEATURE_PS_WIDE |
554 |
|
int w_count = 0; |
555 |
opt_complementary = "-:ww"; |
opt_complementary = "-:ww"; |
556 |
USE_SELINUX(i =) getopt32(argv, USE_SELINUX("Z") "w", &w_count); |
opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")"w", &w_count); |
557 |
/* if w is given once, GNU ps sets the width to 132, |
/* if w is given once, GNU ps sets the width to 132, |
558 |
* if w is given more than once, it is "unlimited" |
* if w is given more than once, it is "unlimited" |
559 |
*/ |
*/ |
560 |
if (w_count) { |
if (w_count) { |
561 |
terminal_width = (w_count==1) ? 132 : MAX_WIDTH; |
terminal_width = (w_count == 1) ? 132 : MAX_WIDTH; |
562 |
} else { |
} else { |
563 |
get_terminal_width_height(0, &terminal_width, NULL); |
get_terminal_width_height(0, &terminal_width, NULL); |
564 |
/* Go one less... */ |
/* Go one less... */ |
565 |
if (--terminal_width > MAX_WIDTH) |
if (--terminal_width > MAX_WIDTH) |
566 |
terminal_width = MAX_WIDTH; |
terminal_width = MAX_WIDTH; |
567 |
} |
} |
568 |
#else /* only ENABLE_SELINUX */ |
# else /* only ENABLE_SELINUX */ |
569 |
i = getopt32(argv, "Z"); |
opts = getopt32(argv, "Z"IF_FEATURE_SHOW_THREADS("T")); |
570 |
#endif |
# endif |
571 |
#if ENABLE_SELINUX |
# if ENABLE_SELINUX |
572 |
if ((i & 1) && is_selinux_enabled()) |
if ((opts & 1) && is_selinux_enabled()) |
573 |
use_selinux = PSSCAN_CONTEXT; |
psscan_flags = PSSCAN_PID | PSSCAN_CONTEXT |
574 |
#endif |
| PSSCAN_STATE | PSSCAN_COMM; |
575 |
|
# endif |
576 |
|
# if ENABLE_FEATURE_SHOW_THREADS |
577 |
|
if (opts & (1 << ENABLE_SELINUX)) |
578 |
|
psscan_flags |= PSSCAN_TASKS; |
579 |
|
# endif |
580 |
#endif /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */ |
#endif /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */ |
581 |
|
|
582 |
if (use_selinux) |
if (psscan_flags & PSSCAN_CONTEXT) |
583 |
puts(" PID CONTEXT STAT COMMAND"); |
puts(" PID CONTEXT STAT COMMAND"); |
584 |
else |
else |
585 |
puts(" PID USER VSZ STAT COMMAND"); |
puts(" PID USER VSZ STAT COMMAND"); |
586 |
|
|
587 |
while ((p = procps_scan(p, 0 |
p = NULL; |
588 |
| PSSCAN_PID |
while ((p = procps_scan(p, psscan_flags)) != NULL) { |
|
| PSSCAN_UIDGID |
|
|
| PSSCAN_STATE |
|
|
| PSSCAN_VSZ |
|
|
| PSSCAN_COMM |
|
|
| use_selinux |
|
|
))) { |
|
589 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
590 |
if (use_selinux) { |
if (psscan_flags & PSSCAN_CONTEXT) { |
591 |
len = printf("%5u %-32.32s %s ", |
len = printf("%5u %-32.32s %s ", |
592 |
p->pid, |
p->pid, |
593 |
p->context ? p->context : "unknown", |
p->context ? p->context : "unknown", |