From 516a0ca2dc92d9ea103535863102cc5425fe648e Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 19 Apr 2007 14:46:14 +0000 Subject: [PATCH] ps: add -o tty and -o rss support 1373 14 24 1411 583 busybox.t1/procps/ps.o 1462 14 24 1500 5dc busybox.t2/procps/ps.o --- include/libbb.h | 17 +++++++---- libbb/procps.c | 30 ++++++++++++++----- procps/ps.c | 79 ++++++++++++++++++++++++++++--------------------- shell/hush.c | 2 +- 4 files changed, 80 insertions(+), 48 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 77f1e0a44..31ded7e9c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -805,7 +805,7 @@ typedef struct { DIR *dir; /* Fields are set to 0/NULL if failed to determine (or not requested) */ char *cmd; - unsigned long vsz; + unsigned vsz, rss; /* we round it to kbytes */ unsigned long stime, utime; unsigned pid; unsigned ppid; @@ -813,9 +813,10 @@ typedef struct { unsigned sid; unsigned uid; unsigned gid; - /* basename of executable file in call to exec(2), size from */ - /* sizeof(task_struct.comm) in /usr/include/linux/sched.h */ char state[4]; + char tty_str[8]; /* "maj,min" or "?" */ + /* basename of executable in exec(2), read from /proc/N/stat, */ + /* size from sizeof(task_struct.comm) in /usr/include/linux/sched.h */ char comm[COMM_LEN]; /* user/group? - use passwd/group parsing functions */ } procps_status_t; @@ -829,12 +830,16 @@ enum { PSSCAN_CMD = 1 << 6, PSSCAN_STATE = 1 << 7, PSSCAN_VSZ = 1 << 8, - PSSCAN_STIME = 1 << 9, - PSSCAN_UTIME = 1 << 10, + PSSCAN_RSS = 1 << 9, + PSSCAN_STIME = 1 << 10, + PSSCAN_UTIME = 1 << 11, + PSSCAN_TTY = 1 << 12, /* 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_STIME | PSSCAN_UTIME, + | PSSCAN_VSZ | PSSCAN_RSS + | PSSCAN_STIME | PSSCAN_UTIME + | PSSCAN_TTY, }; procps_status_t* alloc_procps_scan(int flags); void free_procps_scan(procps_status_t* sp); diff --git a/libbb/procps.c b/libbb/procps.c index c9dcfde0c..053f7d225 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -144,6 +144,9 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags) if (flags & PSSCAN_STAT) { char *cp; + unsigned long vsz, rss; + int tty; + /* see proc(5) for some details on this */ strcpy(filename_tail, "/stat"); n = read_to_buf(filename, buf); @@ -158,33 +161,46 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags) sscanf(buf, "%*s (%15c", sp->comm); n = sscanf(cp+2, "%c %u " /* state, ppid */ - "%u %u %*s %*s " /* pgid, sid, tty, tpgid */ + "%u %u %d %*s " /* pgid, sid, tty, tpgid */ "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ "%lu %lu " /* utime, stime */ "%*s %*s %*s " /* cutime, cstime, priority */ "%ld " /* nice */ "%*s %*s %*s " /* timeout, it_real_value, start_time */ - "%lu ", /* vsize */ + "%lu " /* vsize */ + "%lu " /* rss */ + /* "%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ + /* "%u %u %u %u " signal, blocked, sigignore, sigcatch */ + /* "%lu %lu %lu" wchan, nswap, cnswap */ + , sp->state, &sp->ppid, - &sp->pgid, &sp->sid, + &sp->pgid, &sp->sid, &tty, &sp->utime, &sp->stime, &tasknice, - &sp->vsz); - if (n != 8) + &vsz, + &rss); + if (n != 10) break; + sp->tty_str[0] = '?'; + /* sp->tty_str[1] = '\0'; - done by memset */ + if (tty >= 0) /* tty field of "-1" means "no tty" */ + snprintf(sp->tty_str, sizeof(sp->tty_str), "%u,%u", + (tty >> 8) & 0xfff, /* major */ + (tty & 0xff) | ((tty >> 12) & 0xfff00)); if (sp->vsz == 0 && sp->state[0] != 'Z') sp->state[1] = 'W'; else sp->state[1] = ' '; if (tasknice < 0) sp->state[2] = '<'; - else if (tasknice > 0) + else if (tasknice) /* > 0 */ sp->state[2] = 'N'; else sp->state[2] = ' '; - sp->vsz >>= 10; /* vsize is in bytes and we want kb */ + sp->vsz = vsz >> 10; /* vsize is in bytes and we want kb */ + sp->rss = rss >> 10; } if (flags & PSSCAN_CMD) { diff --git a/procps/ps.c b/procps/ps.c index f8f5c1aa9..0c9b71e09 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -29,83 +29,90 @@ static void func_args(char *buf, int size, const procps_status_t *ps) if (ps->cmd) safe_strncpy(buf, ps->cmd, size+1); else if (size >= 2) - snprintf(buf, size+1, "[%.*s]", size-2, ps->comm); + sprintf(buf, "[%.*s]", size-2, ps->comm); } static void func_pid(char *buf, int size, const procps_status_t *ps) { - snprintf(buf, size+1, "%*u", size, ps->pid); + sprintf(buf, "%*u", size, ps->pid); } static void func_ppid(char *buf, int size, const procps_status_t *ps) { - snprintf(buf, size+1, "%*u", size, ps->ppid); + sprintf(buf, "%*u", size, ps->ppid); } static void func_pgid(char *buf, int size, const procps_status_t *ps) { - snprintf(buf, size+1, "%*u", size, ps->pgid); + sprintf(buf, "%*u", size, ps->pgid); } static void func_vsz(char *buf, int size, const procps_status_t *ps) { char buf5[5]; smart_ulltoa5( ((unsigned long long)ps->vsz) << 10, buf5); - snprintf(buf, size+1, "%.*s", size, buf5); + sprintf(buf, "%.*s", size, buf5); } +static void func_rss(char *buf, int size, const procps_status_t *ps) +{ + char buf5[5]; + smart_ulltoa5( ((unsigned long long)ps->rss) << 10, buf5); + sprintf(buf, "%.*s", size, buf5); +} + +static void func_tty(char *buf, int size, const procps_status_t *ps) +{ + safe_strncpy(buf, ps->tty_str, size+1); +} /* -void func_nice(char *buf, int size, const procps_status_t *ps) +static void func_nice(char *buf, int size, const procps_status_t *ps) { ps->??? } -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) { elapled time [[dd-]hh:]mm:ss } -void func_time(char *buf, int size, const procps_status_t *ps) +static void func_time(char *buf, int size, const procps_status_t *ps) { cumulative time [[dd-]hh:]mm:ss } -void func_pcpu(char *buf, int size, const procps_status_t *ps) -{ -} - -void func_tty(char *buf, int size, const procps_status_t *ps) +static void func_pcpu(char *buf, int size, const procps_status_t *ps) { } */ typedef struct { - char name[8]; + uint16_t width; + char name[6]; const char *header; void (*f)(char *buf, int size, const procps_status_t *ps); int ps_flags; - int width; } ps_out_t; static const ps_out_t out_spec[] = { // Mandated by POSIX: - { "user" ,"USER" ,func_user ,PSSCAN_UIDGID,8 }, - { "comm" ,"COMMAND",func_comm ,PSSCAN_COMM ,16 }, - { "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM,256 }, - { "pid" ,"PID" ,func_pid ,PSSCAN_PID ,5 }, - { "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID ,5 }, - { "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID ,5 }, -// { "etime" ,"ELAPSED",func_etime ,PSSCAN_ ,sizeof("ELAPSED")-1 }, -// { "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID,sizeof("GROUP" )-1 }, -// { "nice" ,"NI" ,func_nice ,PSSCAN_ ,sizeof("NI" )-1 }, -// { "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ ,sizeof("%CPU" )-1 }, -// { "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID,sizeof("RGROUP" )-1 }, -// { "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID,sizeof("RUSER" )-1 }, -// { "time" ,"TIME" ,func_time ,PSSCAN_ ,sizeof("TIME" )-1 }, -// { "tty" ,"TT" ,func_tty ,PSSCAN_ ,sizeof("TT" )-1 }, - { "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ ,4 }, -// Not mandated by POSIX: -// { "rss" ,"RSS" ,func_rss ,PSSCAN_RSS ,4 }, + { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, + { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, + { 256 , "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM }, + { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, + { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, + { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, +// { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, +// { 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 }, +// { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, + { sizeof("TT" )-1, "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, + { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, +// Not mandated by POSIX, but useful: + { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS }, }; #define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) ) @@ -152,6 +159,8 @@ static void parse_o(char* opt) } break; } + // opt points to last spec in comma separated list. + // This one can have =HEADER part. new = new_out_t(); if (equal) *equal = '\0'; @@ -190,9 +199,11 @@ static void format_header(void) { int i; ps_out_t* op; - char *p = buffer; + char *p; + if (!print_header) return; + p = buffer; i = 0; if (out_cnt) { while (1) { @@ -248,7 +259,7 @@ int ps_main(int argc, char **argv) // -f Generate a full listing // -l Generate a long listing // -o col1,col2,col3=header - // Select which columns to distplay + // Select which columns to display /* We allow (and ignore) most of the above. FIXME */ opt_complementary = "o::"; getopt32(argc, argv, "o:aAdefl", &opt_o); diff --git a/shell/hush.c b/shell/hush.c index 08357ca77..56f2728f5 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -306,7 +306,7 @@ static void __syntax(const char *file, int line) { bb_error_msg("syntax error %s:%d", file, line); } -// NB: was __FILE__, but that produces full path sometimess, so... +// NB: was __FILE__, but that produces full path sometimes, so... #define syntax() __syntax("hush.c", __LINE__) /* Index of subroutines: */