unsigned sid;
unsigned uid;
unsigned gid;
+#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
+ unsigned ruid;
+ unsigned rgid;
+ int niceness;
+#endif
unsigned tty_major,tty_minor;
#if ENABLE_FEATURE_TOPMEM
unsigned long mapped_rw;
int last_seen_on_cpu;
#endif
} procps_status_t;
+/* flag bits for procps_scan(xx, flags) calls */
enum {
PSSCAN_PID = 1 << 0,
PSSCAN_PPID = 1 << 1,
),
IF_SELINUX(PSSCAN_CONTEXT = 1 << 17,)
PSSCAN_START_TIME = 1 << 18,
- PSSCAN_CPU = 1 << 19,
+ PSSCAN_CPU = (1 << 19) * ENABLE_FEATURE_TOP_SMP_PROCESS,
+ PSSCAN_NICE = (1 << 20) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
+ PSSCAN_RUIDGID = (1 << 21) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
/* These are all retrieved from proc/NN/stat in one go: */
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
/**/ | PSSCAN_COMM | PSSCAN_STATE
/**/ | PSSCAN_VSZ | PSSCAN_RSS
/**/ | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
- /**/ | PSSCAN_TTY
-#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ /**/ | PSSCAN_TTY | PSSCAN_NICE
/**/ | PSSCAN_CPU
-#endif
};
//procps_status_t* alloc_procps_scan(void) FAST_FUNC;
void free_procps_scan(procps_status_t* sp) FAST_FUNC;
*endptr = str + 1; /* We skip trailing space! */
return n;
}
+
+static long fast_strtol_10(char **endptr)
+{
+ if (**endptr != '-')
+ return fast_strtoul_10(endptr);
+
+ (*endptr)++;
+ return - (long)fast_strtoul_10(endptr);
+}
+
static char *skip_fields(char *str, int count)
{
do {
if (flags & PSSCAN_UIDGID) {
if (stat(filename, &sb))
break;
- /* Need comment - is this effective or real UID/GID? */
+ /* Effective UID/GID, not real */
sp->uid = sb.st_uid;
sp->gid = sb.st_gid;
}
sp->utime = fast_strtoul_10(&cp);
sp->stime = fast_strtoul_10(&cp);
cp = skip_fields(cp, 3); /* cutime, cstime, priority */
- tasknice = fast_strtoul_10(&cp);
+ tasknice = fast_strtol_10(&cp);
cp = skip_fields(cp, 2); /* timeout, it_real_value */
sp->start_time = fast_strtoul_10(&cp);
/* vsz is in bytes and we want kb */
#endif
#endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */
+#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
+ sp->niceness = tasknice;
+#endif
+
if (sp->vsz == 0 && sp->state[0] != 'Z')
sp->state[1] = 'W';
else
fclose(file);
}
#endif /* TOPMEM */
+#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
+ if (flags & PSSCAN_RUIDGID) {
+ FILE *file;
+ strcpy(filename_tail, "/status");
+ file = fopen_for_read(filename);
+ if (!file)
+ break;
+ while (fgets(buf, sizeof(buf), file)) {
+ char *tp;
+#define SCAN_TWO(str, name, statement) \
+ if (strncmp(buf, str, sizeof(str)-1) == 0) { \
+ tp = skip_whitespace(buf + sizeof(str)-1); \
+ sscanf(tp, "%u", &sp->name); \
+ statement; \
+ }
+ SCAN_TWO("Uid:", ruid, continue);
+ SCAN_TWO("Gid:", rgid, break);
+#undef SCAN_TWO
+ }
+ fclose(file);
+ }
+#endif /* PS_ADDITIONAL_COLUMNS */
#if 0 /* PSSCAN_CMD is not used */
if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) {
free(sp->argv0);
ps gives a snapshot of the current processes.
config FEATURE_PS_WIDE
- bool "Enable argument for wide output (-w)"
+ bool "Enable wide output option (-w)"
default n
depends on PS
help
Support argument 'w' for wide output.
- If given once, 132 chars are printed and given more than
- one, the length is unlimited.
+ If given once, 132 chars are printed, and if given more
+ than once, the length is unlimited.
config FEATURE_PS_TIME
bool "Enable time and elapsed time output"
help
Support -o time and -o etime output specifiers.
+config FEATURE_PS_ADDITIONAL_COLUMNS
+ bool "Enable additional ps columns"
+ default n
+ depends on PS && DESKTOP
+ help
+ Support -o rgroup, -o ruser, -o nice output specifiers.
+
config FEATURE_PS_UNUSUAL_SYSTEMS
bool "Support Linux prior to 2.4.0 and non-ELF systems"
default n
typedef struct {
uint16_t width;
- char name[6];
+ char name6[6];
const char *header;
void (*f)(char *buf, int size, const procps_status_t *ps);
int ps_flags;
#endif
}
+static void func_group(char *buf, int size, const procps_status_t *ps)
+{
+ safe_strncpy(buf, get_cached_groupname(ps->gid), size+1);
+}
+
static void func_comm(char *buf, int size, const procps_status_t *ps)
{
safe_strncpy(buf, ps->comm, size+1);
snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
}
+
+#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 /* FEATURE_PS_ADDITIONAL_COLUMNS */
+
#if ENABLE_FEATURE_PS_TIME
static void func_etime(char *buf, int size, const procps_status_t *ps)
{
static const ps_out_t out_spec[] = {
// Mandated by POSIX:
{ 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID },
+ { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
{ 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM },
{ 256 , "args" ,"COMMAND",func_args ,PSSCAN_COMM },
{ 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID },
#if ENABLE_FEATURE_PS_TIME
{ sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME },
#endif
-// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
-// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ },
-// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ },
-// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID },
-// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID },
+#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
+ { 5 , "nice" ,"NI" ,func_nice ,PSSCAN_NICE },
+ { 8 , "rgroup","RGROUP" ,func_rgroup,PSSCAN_RUIDGID },
+ { 8 , "ruser" ,"RUSER" ,func_ruser ,PSSCAN_RUIDGID },
+// { 5 , "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ },
+#endif
#if ENABLE_FEATURE_PS_TIME
{ 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME },
#endif
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(out_spec); i++) {
- if (!strcmp(name, out_spec[i].name))
+ if (!strncmp(name, out_spec[i].name6, 6))
return &out_spec[i];
}
bb_error_msg_and_die("bad -o argument '%s'", name);