From 8bde71eb1502a5cdf186769b47d470038f99bc95 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 6 Aug 2025 00:42:05 +0200 Subject: [PATCH] top: simplify command line reading function old new delta cmdline_to_line_buf_and_print - 48 +48 read_cmdline 326 327 +1 display_topmem_process_list 523 505 -18 display_process_list 1186 1161 -25 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 49/-43) Total: 6 bytes Signed-off-by: Denys Vlasenko --- libbb/procps.c | 21 ++++++++++++++------- procps/top.c | 23 ++++++++++++----------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/libbb/procps.c b/libbb/procps.c index 3256fafc5..fc31c075d 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -558,22 +558,29 @@ int FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) if (sz < 0) return sz; if (sz > 0) { - const char *base; + const char *program_basename; int comm_len; buf[sz] = '\0'; while (--sz >= 0 && buf[sz] == '\0') continue; - /* Prevent basename("process foo/bar") = "bar" */ - strchrnul(buf, ' ')[0] = '\0'; - base = bb_basename(buf); /* before we replace argv0's NUL with space */ + + /* Find "program" in "[-][/PATH/TO/]program" */ + strchrnul(buf, ' ')[0] = '\0'; /* prevent basename("program foo/bar") = "bar" */ + program_basename = bb_basename(buf[0] == '-' ? buf + 1 : buf); + /* ^^^ note: must do it *before* replacing argv0's NUL with space */ + + /* Prevent stuff like this: + * echo 'sleep 999; exit' >`printf '\ec'`; sh ?c + * messing up top and ps output (or worse). + * This also replaces NULs with spaces, converting + * list of NUL-strings into one string. + */ while (sz >= 0) { if ((unsigned char)(buf[sz]) < ' ') buf[sz] = ' '; sz--; } - if (base[0] == '-') /* "-sh" (login shell)? */ - base++; /* If comm differs from argv0, prepend "{comm} ". * It allows to see thread names set by prctl(PR_SET_NAME). @@ -587,7 +594,7 @@ int FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) * I prefer to still treat argv0 "process foo bar" * as 'equal' to comm "process". */ - if (strncmp(base, comm, comm_len) != 0) { + if (strncmp(program_basename, comm, comm_len) != 0) { comm_len += 3; if (col > comm_len) memmove(buf + comm_len, buf, col - comm_len); diff --git a/procps/top.c b/procps/top.c index bff9f7c4f..96b3e2d4e 100644 --- a/procps/top.c +++ b/procps/top.c @@ -602,6 +602,15 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX]) fclose(f); } +static void cmdline_to_line_buf_and_print(unsigned offset, unsigned pid, const char *comm) +{ + int width = G.scr_width - offset; + if (width > 1) /* wider than to fit just the NUL? */ + read_cmdline(G.line_buf + offset, width, pid, comm); +//TODO: read_cmdline() sanitizes control chars, but not chars above 0x7e + print_line_buf(); +} + static unsigned long display_header(void) { char *buf; @@ -789,9 +798,7 @@ static NOINLINE void display_process_list(void) IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) ); - if ((int)(G.scr_width - col) > 1) - read_cmdline(G.line_buf + col, G.scr_width - col, s->pid, s->comm); - print_line_buf(); + cmdline_to_line_buf_and_print(col, s->pid, s->comm); /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */ s++; @@ -910,14 +917,12 @@ static void ulltoa4_and_space(unsigned long long ul, char buf[5]) static NOINLINE void display_topmem_process_list(void) { -#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" -#define MIN_WIDTH sizeof(HDR_STR) const topmem_status_t *s = topmem + G_scroll_ofs; char *cp, ch; display_topmem_header(); - strcpy(G.line_buf, HDR_STR " COMMAND"); + strcpy(G.line_buf, " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK COMMAND"); /* Mark the ^FIELD^ we sort by */ cp = &G.line_buf[5 + sort_field * 6]; ch = "^_"[inverted]; @@ -949,13 +954,9 @@ static NOINLINE void display_topmem_process_list(void) ulltoa5_and_space(s->dirty_sh, &G.line_buf[6*6]); ulltoa5_and_space(s->stack , &G.line_buf[7*6]); G.line_buf[8*6] = '\0'; - if ((int)(G.scr_width - MIN_WIDTH) > 1) - read_cmdline(&G.line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm); - print_line_buf(); + cmdline_to_line_buf_and_print(8*6, s->pid, s->comm); s++; } -#undef HDR_STR -#undef MIN_WIDTH } #endif /* end TOPMEM support */