ps: conditionally support additional -o FIELDs
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Jul 2009 20:16:17 +0000 (22:16 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Jul 2009 20:16:17 +0000 (22:16 +0200)
function                                             old     new   delta
procps_scan                                         1409    1642    +233
out_spec                                             220     300     +80
func_ruser                                             -      36     +36
func_rgroup                                            -      36     +36
func_group                                            13      49     +36
func_nice                                              -      29     +29
buffer_fill_and_print                                179     196     +17
send_tree                                            355     360      +5
mkfs_vfat_main                                      1604    1609      +5
display_speed                                         85      90      +5
scriptreplay_main                                    194     197      +3
find_out_spec                                         55      58      +3
changepath                                           192     195      +3
sha1_process_block64                                 497     484     -13
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 10/1 up/down: 491/-13)          Total: 478 bytes

Signed-off-by: David Krakov <krakov@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
libbb/procps.c
procps/Config.in
procps/ps.c
procps/top.c

index e1c36a57b7db3e5ef4d15aa4cc5205328f44bb78..77674f8a20ff6b2947811f030d7c7bb4c5150982 100644 (file)
@@ -1276,6 +1276,11 @@ typedef struct procps_status_t {
        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;
@@ -1296,6 +1301,7 @@ typedef struct procps_status_t {
        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,
@@ -1322,16 +1328,16 @@ enum {
                                ),
        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;
index 445e709c8b9c8852b762741493950d80aa6f194e..6e122c4d569dd63083c315f675bce06735094c8e 100644 (file)
@@ -151,6 +151,16 @@ static unsigned long fast_strtoul_10(char **endptr)
        *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 {
@@ -208,7 +218,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
                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;
                }
@@ -293,7 +303,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
                        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 */
@@ -310,6 +320,10 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
 #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
@@ -372,7 +386,29 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
                        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);
index 702442a524fdaecf73ea9d216c9b22fa2802c437..9146ff6bf21c1600aa7972469eee7a29534ef24e 100644 (file)
@@ -91,13 +91,13 @@ config PS
          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"
@@ -106,6 +106,13 @@ config FEATURE_PS_TIME
        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
index b9a4aef15a7eab84c1ec81e6349038186888112e..4a6b60bdcebe59220e3d85f88d8cdfb9789232af 100644 (file)
@@ -32,7 +32,7 @@ enum { MAX_WIDTH = 2*1024 };
 
 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;
@@ -174,6 +174,11 @@ static void func_user(char *buf, int size, const procps_status_t *ps)
 #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);
@@ -227,6 +232,26 @@ static void func_tty(char *buf, int size, const procps_status_t *ps)
                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)
 {
@@ -276,6 +301,7 @@ static void func_pcpu(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     },
@@ -284,11 +310,12 @@ static const ps_out_t out_spec[] = {
 #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
@@ -311,7 +338,7 @@ static const ps_out_t* find_out_spec(const char *name)
 {
        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);
index 8738156e1bee4db783a39a002929683e1f77cb44..62b9c1e1b4c717c2d182b528def310e94421fe2d 100644 (file)
@@ -871,9 +871,7 @@ enum {
                | PSSCAN_UTIME
                | PSSCAN_STATE
                | PSSCAN_COMM
-#if ENABLE_FEATURE_TOP_SMP_PROCESS
                | PSSCAN_CPU
-#endif
                | PSSCAN_UIDGID,
        TOPMEM_MASK = 0
                | PSSCAN_PID