* Licensed under GPLv2, see file LICENSE in this source tree.
*/
//config:config PS
-//config: bool "ps"
+//config: bool "ps (11 kb)"
//config: default y
//config: help
-//config: ps gives a snapshot of the current processes.
+//config: ps gives a snapshot of the current processes.
//config:
//config:config FEATURE_PS_WIDE
-//config: bool "Enable wide output option (-w)"
+//config: bool "Enable wide output (-w)"
//config: default y
//config: depends on PS && !DESKTOP
//config: help
-//config: Support argument 'w' for wide output.
-//config: If given once, 132 chars are printed, and if given more
-//config: than once, the length is unlimited.
+//config: Support argument 'w' for wide output.
+//config: If given once, 132 chars are printed, and if given more
+//config: than once, the length is unlimited.
//config:
//config:config FEATURE_PS_LONG
-//config: bool "Enable long output option (-l)"
+//config: bool "Enable long output (-l)"
//config: default y
//config: depends on PS && !DESKTOP
//config: help
-//config: Support argument 'l' for long output.
-//config: Adds fields PPID, RSS, START, TIME & TTY
+//config: Support argument 'l' for long output.
+//config: Adds fields PPID, RSS, START, TIME & TTY
//config:
//config:config FEATURE_PS_TIME
-//config: bool "Enable time and elapsed time output"
+//config: bool "Enable -o time and -o etime specifiers"
//config: default y
//config: depends on PS && DESKTOP
//config: select PLATFORM_LINUX
-//config: help
-//config: Support -o time and -o etime output specifiers.
//config:
//config:config FEATURE_PS_ADDITIONAL_COLUMNS
-//config: bool "Enable additional ps columns"
+//config: bool "Enable -o rgroup, -o ruser, -o nice specifiers"
//config: default y
//config: depends on PS && DESKTOP
-//config: help
-//config: Support -o rgroup, -o ruser, -o nice output specifiers.
//config:
//config:config FEATURE_PS_UNUSUAL_SYSTEMS
//config: bool "Support Linux prior to 2.4.0 and non-ELF systems"
//config: default n
//config: depends on FEATURE_PS_TIME
//config: help
-//config: Include support for measuring HZ on old kernels and non-ELF systems
-//config: (if you are on Linux 2.4.0+ and use ELF, you don't need this)
+//config: Include support for measuring HZ on old kernels and non-ELF systems
+//config: (if you are on Linux 2.4.0+ and use ELF, you don't need this)
//applet:IF_PS(APPLET(ps, BB_DIR_BIN, BB_SUID_DROP))
+/* can't be NOEXEC: uses ELF aux vector. To have it, we must be a normal, execed process */
//kbuild:lib-$(CONFIG_PS) += ps.o
#endif
#if ENABLE_DESKTOP
-
-#include <sys/times.h> /* for times() */
-#ifndef AT_CLKTCK
-# define AT_CLKTCK 17
-#endif
-
/* TODO:
* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
* specifies (for XSI-conformant systems) following default columns
char *buffer;
unsigned terminal_width;
#if ENABLE_FEATURE_PS_TIME
+# if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS || !defined(__linux__)
unsigned kernel_HZ;
+# endif
unsigned long seconds_since_boot;
#endif
} FIX_ALIASING;
#define need_flags (G.need_flags )
#define buffer (G.buffer )
#define terminal_width (G.terminal_width )
-#define kernel_HZ (G.kernel_HZ )
#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_PS_TIME
-/* for ELF executables, notes are pushed before environment and args */
-static uintptr_t find_elf_note(uintptr_t findme)
-{
- uintptr_t *ep = (uintptr_t *) environ;
-
- while (*ep++)
- continue;
- while (*ep) {
- if (ep[0] == findme) {
- return ep[1];
- }
- ep += 2;
- }
- return -1;
-}
-
-#if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS
-static unsigned get_HZ_by_waiting(void)
-{
- struct timeval tv1, tv2;
- unsigned t1, t2, r, hz;
- unsigned cnt = cnt; /* for compiler */
- int diff;
-
- r = 0;
-
- /* Wait for times() to reach new tick */
- t1 = times(NULL);
- do {
- t2 = times(NULL);
- } while (t2 == t1);
- gettimeofday(&tv2, NULL);
-
- do {
- t1 = t2;
- tv1.tv_usec = tv2.tv_usec;
-
- /* Wait exactly one times() tick */
- do {
- t2 = times(NULL);
- } while (t2 == t1);
- gettimeofday(&tv2, NULL);
-
- /* Calculate ticks per sec, rounding up to even */
- diff = tv2.tv_usec - tv1.tv_usec;
- if (diff <= 0) diff += 1000000;
- hz = 1000000u / (unsigned)diff;
- hz = (hz+1) & ~1;
-
- /* Count how many same hz values we saw */
- if (r != hz) {
- r = hz;
- cnt = 0;
- }
- cnt++;
- } while (cnt < 3); /* exit if saw 3 same values */
-
- return r;
-}
-#else
-static inline unsigned get_HZ_by_waiting(void)
-{
- /* Better method? */
- return 100;
-}
-#endif
-
-static unsigned get_kernel_HZ(void)
-{
- if (kernel_HZ)
- return kernel_HZ;
-
- /* Works for ELF only, Linux 2.4.0+ */
- kernel_HZ = find_elf_note(AT_CLKTCK);
- if (kernel_HZ == (unsigned)-1)
- kernel_HZ = get_HZ_by_waiting();
-
- G.seconds_since_boot = get_uptime();
-
- return kernel_HZ;
-}
+# if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS || !defined(__linux__)
+# define get_kernel_HZ() (G.kernel_HZ)
+# else
+ /* non-ancient Linux standardized on 100 for "times" freq */
+# define get_kernel_HZ() ((unsigned)100)
+# endif
#endif
/* Print value to buf, max size+1 chars (including trailing '\0') */
sprintf(buf, "%*u", size, ps->pgid);
}
+static void func_sid(char *buf, int size, const procps_status_t *ps)
+{
+ sprintf(buf, "%*u", size, ps->sid);
+}
+
static void put_lu(char *buf, int size, unsigned long u)
{
char buf4[5];
}
#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
-
static void func_rgroup(char *buf, int size, const procps_status_t *ps)
{
safe_strncpy(buf, get_cached_groupname(ps->rgid), size+1);
}
-
static void func_ruser(char *buf, int size, const procps_status_t *ps)
{
safe_strncpy(buf, get_cached_username(ps->ruid), size+1);
}
-
static void func_nice(char *buf, int size, const procps_status_t *ps)
{
sprintf(buf, "%*d", size, ps->niceness);
}
-
#endif
#if ENABLE_FEATURE_PS_TIME
-
static void func_etime(char *buf, int size, const procps_status_t *ps)
{
/* elapsed time [[dd-]hh:]mm:ss; here only mm:ss */
unsigned ss;
mm = ps->start_time / get_kernel_HZ();
- /* must be after get_kernel_HZ()! */
mm = G.seconds_since_boot - mm;
ss = mm % 60;
mm /= 60;
snprintf(buf, size+1, "%3lu:%02u", mm, ss);
}
-
static void func_time(char *buf, int size, const procps_status_t *ps)
{
/* cumulative time [[dd-]hh:]mm:ss; here only mm:ss */
mm /= 60;
snprintf(buf, size+1, "%3lu:%02u", mm, ss);
}
-
#endif
#if ENABLE_SELINUX
#endif
/*
-static void func_nice(char *buf, int size, const procps_status_t *ps)
-{
- ps->???
-}
-
static void func_pcpu(char *buf, int size, const procps_status_t *ps)
{
}
{ 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY },
{ 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ },
/* Not mandated, but useful: */
+ { 5 , "sid" ,"SID" ,func_sid ,PSSCAN_SID },
{ 4 , "stat" ,"STAT" ,func_state ,PSSCAN_STATE },
{ 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS },
#if ENABLE_SELINUX
procps_status_t *p;
llist_t* opt_o = NULL;
char default_o[sizeof(DEFAULT_O_STR)];
+#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
int opt;
+#endif
enum {
OPT_Z = (1 << 0),
OPT_o = (1 << 1),
};
INIT_G();
+ G.seconds_since_boot = get_uptime();
+#if ENABLE_FEATURE_PS_TIME && (ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS || !defined(__linux__))
+ G.kernel_HZ = bb_clk_tck(); /* this is sysconf(_SC_CLK_TCK) */
+#endif
// POSIX:
// -a Write information for all processes associated with terminals
* procps v3.2.7 supports -T and shows tids as SPID column,
* it also supports -L where it shows tids as LWP column.
*/
- opt = getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
+#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
+ opt =
+#endif
+ getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
+
if (opt_o) {
do {
parse_o(llist_pop(&opt_o));
# if ENABLE_FEATURE_PS_WIDE
/* -w is a bit complicated */
int w_count = 0;
- opt_complementary = "-:ww";
- opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l")
- "w", &w_count);
+ make_all_argv_opts(argv);
+ opts = getopt32(argv, "^"
+ IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l")"w"
+ "\0" "ww",
+ &w_count
+ );
/* if w is given once, GNU ps sets the width to 132,
* if w is given more than once, it is "unlimited"
*/
}
# else
/* -w is not supported, only -Z and/or -T */
- opt_complementary = "-";
+ make_all_argv_opts(argv);
opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l"));
# endif