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
This commit is contained in:
parent
c34d35557b
commit
516a0ca2dc
@ -805,7 +805,7 @@ typedef struct {
|
|||||||
DIR *dir;
|
DIR *dir;
|
||||||
/* Fields are set to 0/NULL if failed to determine (or not requested) */
|
/* Fields are set to 0/NULL if failed to determine (or not requested) */
|
||||||
char *cmd;
|
char *cmd;
|
||||||
unsigned long vsz;
|
unsigned vsz, rss; /* we round it to kbytes */
|
||||||
unsigned long stime, utime;
|
unsigned long stime, utime;
|
||||||
unsigned pid;
|
unsigned pid;
|
||||||
unsigned ppid;
|
unsigned ppid;
|
||||||
@ -813,9 +813,10 @@ typedef struct {
|
|||||||
unsigned sid;
|
unsigned sid;
|
||||||
unsigned uid;
|
unsigned uid;
|
||||||
unsigned gid;
|
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 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];
|
char comm[COMM_LEN];
|
||||||
/* user/group? - use passwd/group parsing functions */
|
/* user/group? - use passwd/group parsing functions */
|
||||||
} procps_status_t;
|
} procps_status_t;
|
||||||
@ -829,12 +830,16 @@ enum {
|
|||||||
PSSCAN_CMD = 1 << 6,
|
PSSCAN_CMD = 1 << 6,
|
||||||
PSSCAN_STATE = 1 << 7,
|
PSSCAN_STATE = 1 << 7,
|
||||||
PSSCAN_VSZ = 1 << 8,
|
PSSCAN_VSZ = 1 << 8,
|
||||||
PSSCAN_STIME = 1 << 9,
|
PSSCAN_RSS = 1 << 9,
|
||||||
PSSCAN_UTIME = 1 << 10,
|
PSSCAN_STIME = 1 << 10,
|
||||||
|
PSSCAN_UTIME = 1 << 11,
|
||||||
|
PSSCAN_TTY = 1 << 12,
|
||||||
/* These are all retrieved from proc/NN/stat in one go: */
|
/* These are all retrieved from proc/NN/stat in one go: */
|
||||||
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
|
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
|
||||||
| PSSCAN_COMM | PSSCAN_STATE
|
| 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);
|
procps_status_t* alloc_procps_scan(int flags);
|
||||||
void free_procps_scan(procps_status_t* sp);
|
void free_procps_scan(procps_status_t* sp);
|
||||||
|
@ -144,6 +144,9 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags)
|
|||||||
|
|
||||||
if (flags & PSSCAN_STAT) {
|
if (flags & PSSCAN_STAT) {
|
||||||
char *cp;
|
char *cp;
|
||||||
|
unsigned long vsz, rss;
|
||||||
|
int tty;
|
||||||
|
|
||||||
/* see proc(5) for some details on this */
|
/* see proc(5) for some details on this */
|
||||||
strcpy(filename_tail, "/stat");
|
strcpy(filename_tail, "/stat");
|
||||||
n = read_to_buf(filename, buf);
|
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);
|
sscanf(buf, "%*s (%15c", sp->comm);
|
||||||
n = sscanf(cp+2,
|
n = sscanf(cp+2,
|
||||||
"%c %u " /* state, ppid */
|
"%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 */
|
"%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
|
||||||
"%lu %lu " /* utime, stime */
|
"%lu %lu " /* utime, stime */
|
||||||
"%*s %*s %*s " /* cutime, cstime, priority */
|
"%*s %*s %*s " /* cutime, cstime, priority */
|
||||||
"%ld " /* nice */
|
"%ld " /* nice */
|
||||||
"%*s %*s %*s " /* timeout, it_real_value, start_time */
|
"%*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->state, &sp->ppid,
|
||||||
&sp->pgid, &sp->sid,
|
&sp->pgid, &sp->sid, &tty,
|
||||||
&sp->utime, &sp->stime,
|
&sp->utime, &sp->stime,
|
||||||
&tasknice,
|
&tasknice,
|
||||||
&sp->vsz);
|
&vsz,
|
||||||
if (n != 8)
|
&rss);
|
||||||
|
if (n != 10)
|
||||||
break;
|
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')
|
if (sp->vsz == 0 && sp->state[0] != 'Z')
|
||||||
sp->state[1] = 'W';
|
sp->state[1] = 'W';
|
||||||
else
|
else
|
||||||
sp->state[1] = ' ';
|
sp->state[1] = ' ';
|
||||||
if (tasknice < 0)
|
if (tasknice < 0)
|
||||||
sp->state[2] = '<';
|
sp->state[2] = '<';
|
||||||
else if (tasknice > 0)
|
else if (tasknice) /* > 0 */
|
||||||
sp->state[2] = 'N';
|
sp->state[2] = 'N';
|
||||||
else
|
else
|
||||||
sp->state[2] = ' ';
|
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) {
|
if (flags & PSSCAN_CMD) {
|
||||||
|
79
procps/ps.c
79
procps/ps.c
@ -29,83 +29,90 @@ static void func_args(char *buf, int size, const procps_status_t *ps)
|
|||||||
if (ps->cmd)
|
if (ps->cmd)
|
||||||
safe_strncpy(buf, ps->cmd, size+1);
|
safe_strncpy(buf, ps->cmd, size+1);
|
||||||
else if (size >= 2)
|
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)
|
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)
|
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)
|
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)
|
static void func_vsz(char *buf, int size, const procps_status_t *ps)
|
||||||
{
|
{
|
||||||
char buf5[5];
|
char buf5[5];
|
||||||
smart_ulltoa5( ((unsigned long long)ps->vsz) << 10, buf5);
|
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->???
|
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
|
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
|
cumulative time [[dd-]hh:]mm:ss
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_pcpu(char *buf, int size, const procps_status_t *ps)
|
static void func_pcpu(char *buf, int size, const procps_status_t *ps)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_tty(char *buf, int size, const procps_status_t *ps)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char name[8];
|
uint16_t width;
|
||||||
|
char name[6];
|
||||||
const char *header;
|
const char *header;
|
||||||
void (*f)(char *buf, int size, const procps_status_t *ps);
|
void (*f)(char *buf, int size, const procps_status_t *ps);
|
||||||
int ps_flags;
|
int ps_flags;
|
||||||
int width;
|
|
||||||
} ps_out_t;
|
} ps_out_t;
|
||||||
|
|
||||||
static const ps_out_t out_spec[] = {
|
static const ps_out_t out_spec[] = {
|
||||||
// Mandated by POSIX:
|
// Mandated by POSIX:
|
||||||
{ "user" ,"USER" ,func_user ,PSSCAN_UIDGID,8 },
|
{ 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID },
|
||||||
{ "comm" ,"COMMAND",func_comm ,PSSCAN_COMM ,16 },
|
{ 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM },
|
||||||
{ "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM,256 },
|
{ 256 , "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM },
|
||||||
{ "pid" ,"PID" ,func_pid ,PSSCAN_PID ,5 },
|
{ 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID },
|
||||||
{ "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID ,5 },
|
{ 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID },
|
||||||
{ "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID ,5 },
|
{ 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID },
|
||||||
// { "etime" ,"ELAPSED",func_etime ,PSSCAN_ ,sizeof("ELAPSED")-1 },
|
// { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ },
|
||||||
// { "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID,sizeof("GROUP" )-1 },
|
// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
|
||||||
// { "nice" ,"NI" ,func_nice ,PSSCAN_ ,sizeof("NI" )-1 },
|
// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ },
|
||||||
// { "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ ,sizeof("%CPU" )-1 },
|
// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ },
|
||||||
// { "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID,sizeof("RGROUP" )-1 },
|
// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID },
|
||||||
// { "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID,sizeof("RUSER" )-1 },
|
// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID },
|
||||||
// { "time" ,"TIME" ,func_time ,PSSCAN_ ,sizeof("TIME" )-1 },
|
// { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ },
|
||||||
// { "tty" ,"TT" ,func_tty ,PSSCAN_ ,sizeof("TT" )-1 },
|
{ sizeof("TT" )-1, "tty" ,"TT" ,func_tty ,PSSCAN_TTY },
|
||||||
{ "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ ,4 },
|
{ 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ },
|
||||||
// Not mandated by POSIX:
|
// Not mandated by POSIX, but useful:
|
||||||
// { "rss" ,"RSS" ,func_rss ,PSSCAN_RSS ,4 },
|
{ 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) )
|
#define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) )
|
||||||
@ -152,6 +159,8 @@ static void parse_o(char* opt)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// opt points to last spec in comma separated list.
|
||||||
|
// This one can have =HEADER part.
|
||||||
new = new_out_t();
|
new = new_out_t();
|
||||||
if (equal)
|
if (equal)
|
||||||
*equal = '\0';
|
*equal = '\0';
|
||||||
@ -190,9 +199,11 @@ static void format_header(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
ps_out_t* op;
|
ps_out_t* op;
|
||||||
char *p = buffer;
|
char *p;
|
||||||
|
|
||||||
if (!print_header)
|
if (!print_header)
|
||||||
return;
|
return;
|
||||||
|
p = buffer;
|
||||||
i = 0;
|
i = 0;
|
||||||
if (out_cnt) {
|
if (out_cnt) {
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -248,7 +259,7 @@ int ps_main(int argc, char **argv)
|
|||||||
// -f Generate a full listing
|
// -f Generate a full listing
|
||||||
// -l Generate a long listing
|
// -l Generate a long listing
|
||||||
// -o col1,col2,col3=header
|
// -o col1,col2,col3=header
|
||||||
// Select which columns to distplay
|
// Select which columns to display
|
||||||
/* We allow (and ignore) most of the above. FIXME */
|
/* We allow (and ignore) most of the above. FIXME */
|
||||||
opt_complementary = "o::";
|
opt_complementary = "o::";
|
||||||
getopt32(argc, argv, "o:aAdefl", &opt_o);
|
getopt32(argc, argv, "o:aAdefl", &opt_o);
|
||||||
|
@ -306,7 +306,7 @@ static void __syntax(const char *file, int line)
|
|||||||
{
|
{
|
||||||
bb_error_msg("syntax error %s:%d", file, 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__)
|
#define syntax() __syntax("hush.c", __LINE__)
|
||||||
|
|
||||||
/* Index of subroutines: */
|
/* Index of subroutines: */
|
||||||
|
Loading…
Reference in New Issue
Block a user