diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-06 00:42:05 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-06 00:42:05 +0200 |
| commit | 8bde71eb1502a5cdf186769b47d470038f99bc95 (patch) | |
| tree | e5097b7f948d1d6be6d5d47d5f2a36886cf3c242 | |
| parent | 1bd8d714ca1889558b26ab8f29a0f199ffdd2bd9 (diff) | |
| download | busybox-w32-8bde71eb1502a5cdf186769b47d470038f99bc95.tar.gz busybox-w32-8bde71eb1502a5cdf186769b47d470038f99bc95.tar.bz2 busybox-w32-8bde71eb1502a5cdf186769b47d470038f99bc95.zip | |
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 <vda.linux@googlemail.com>
| -rw-r--r-- | libbb/procps.c | 21 | ||||
| -rw-r--r-- | 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) | |||
| 558 | if (sz < 0) | 558 | if (sz < 0) |
| 559 | return sz; | 559 | return sz; |
| 560 | if (sz > 0) { | 560 | if (sz > 0) { |
| 561 | const char *base; | 561 | const char *program_basename; |
| 562 | int comm_len; | 562 | int comm_len; |
| 563 | 563 | ||
| 564 | buf[sz] = '\0'; | 564 | buf[sz] = '\0'; |
| 565 | while (--sz >= 0 && buf[sz] == '\0') | 565 | while (--sz >= 0 && buf[sz] == '\0') |
| 566 | continue; | 566 | continue; |
| 567 | /* Prevent basename("process foo/bar") = "bar" */ | 567 | |
| 568 | strchrnul(buf, ' ')[0] = '\0'; | 568 | /* Find "program" in "[-][/PATH/TO/]program" */ |
| 569 | base = bb_basename(buf); /* before we replace argv0's NUL with space */ | 569 | strchrnul(buf, ' ')[0] = '\0'; /* prevent basename("program foo/bar") = "bar" */ |
| 570 | program_basename = bb_basename(buf[0] == '-' ? buf + 1 : buf); | ||
| 571 | /* ^^^ note: must do it *before* replacing argv0's NUL with space */ | ||
| 572 | |||
| 573 | /* Prevent stuff like this: | ||
| 574 | * echo 'sleep 999; exit' >`printf '\ec'`; sh ?c | ||
| 575 | * messing up top and ps output (or worse). | ||
| 576 | * This also replaces NULs with spaces, converting | ||
| 577 | * list of NUL-strings into one string. | ||
| 578 | */ | ||
| 570 | while (sz >= 0) { | 579 | while (sz >= 0) { |
| 571 | if ((unsigned char)(buf[sz]) < ' ') | 580 | if ((unsigned char)(buf[sz]) < ' ') |
| 572 | buf[sz] = ' '; | 581 | buf[sz] = ' '; |
| 573 | sz--; | 582 | sz--; |
| 574 | } | 583 | } |
| 575 | if (base[0] == '-') /* "-sh" (login shell)? */ | ||
| 576 | base++; | ||
| 577 | 584 | ||
| 578 | /* If comm differs from argv0, prepend "{comm} ". | 585 | /* If comm differs from argv0, prepend "{comm} ". |
| 579 | * It allows to see thread names set by prctl(PR_SET_NAME). | 586 | * 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) | |||
| 587 | * I prefer to still treat argv0 "process foo bar" | 594 | * I prefer to still treat argv0 "process foo bar" |
| 588 | * as 'equal' to comm "process". | 595 | * as 'equal' to comm "process". |
| 589 | */ | 596 | */ |
| 590 | if (strncmp(base, comm, comm_len) != 0) { | 597 | if (strncmp(program_basename, comm, comm_len) != 0) { |
| 591 | comm_len += 3; | 598 | comm_len += 3; |
| 592 | if (col > comm_len) | 599 | if (col > comm_len) |
| 593 | memmove(buf + comm_len, buf, col - comm_len); | 600 | 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]) | |||
| 602 | fclose(f); | 602 | fclose(f); |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | static void cmdline_to_line_buf_and_print(unsigned offset, unsigned pid, const char *comm) | ||
| 606 | { | ||
| 607 | int width = G.scr_width - offset; | ||
| 608 | if (width > 1) /* wider than to fit just the NUL? */ | ||
| 609 | read_cmdline(G.line_buf + offset, width, pid, comm); | ||
| 610 | //TODO: read_cmdline() sanitizes control chars, but not chars above 0x7e | ||
| 611 | print_line_buf(); | ||
| 612 | } | ||
| 613 | |||
| 605 | static unsigned long display_header(void) | 614 | static unsigned long display_header(void) |
| 606 | { | 615 | { |
| 607 | char *buf; | 616 | char *buf; |
| @@ -789,9 +798,7 @@ static NOINLINE void display_process_list(void) | |||
| 789 | IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) | 798 | IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) |
| 790 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) | 799 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) |
| 791 | ); | 800 | ); |
| 792 | if ((int)(G.scr_width - col) > 1) | 801 | cmdline_to_line_buf_and_print(col, s->pid, s->comm); |
| 793 | read_cmdline(G.line_buf + col, G.scr_width - col, s->pid, s->comm); | ||
| 794 | print_line_buf(); | ||
| 795 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, | 802 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, |
| 796 | cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */ | 803 | cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */ |
| 797 | s++; | 804 | s++; |
| @@ -910,14 +917,12 @@ static void ulltoa4_and_space(unsigned long long ul, char buf[5]) | |||
| 910 | 917 | ||
| 911 | static NOINLINE void display_topmem_process_list(void) | 918 | static NOINLINE void display_topmem_process_list(void) |
| 912 | { | 919 | { |
| 913 | #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" | ||
| 914 | #define MIN_WIDTH sizeof(HDR_STR) | ||
| 915 | const topmem_status_t *s = topmem + G_scroll_ofs; | 920 | const topmem_status_t *s = topmem + G_scroll_ofs; |
| 916 | char *cp, ch; | 921 | char *cp, ch; |
| 917 | 922 | ||
| 918 | display_topmem_header(); | 923 | display_topmem_header(); |
| 919 | 924 | ||
| 920 | strcpy(G.line_buf, HDR_STR " COMMAND"); | 925 | strcpy(G.line_buf, " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK COMMAND"); |
| 921 | /* Mark the ^FIELD^ we sort by */ | 926 | /* Mark the ^FIELD^ we sort by */ |
| 922 | cp = &G.line_buf[5 + sort_field * 6]; | 927 | cp = &G.line_buf[5 + sort_field * 6]; |
| 923 | ch = "^_"[inverted]; | 928 | ch = "^_"[inverted]; |
| @@ -949,13 +954,9 @@ static NOINLINE void display_topmem_process_list(void) | |||
| 949 | ulltoa5_and_space(s->dirty_sh, &G.line_buf[6*6]); | 954 | ulltoa5_and_space(s->dirty_sh, &G.line_buf[6*6]); |
| 950 | ulltoa5_and_space(s->stack , &G.line_buf[7*6]); | 955 | ulltoa5_and_space(s->stack , &G.line_buf[7*6]); |
| 951 | G.line_buf[8*6] = '\0'; | 956 | G.line_buf[8*6] = '\0'; |
| 952 | if ((int)(G.scr_width - MIN_WIDTH) > 1) | 957 | cmdline_to_line_buf_and_print(8*6, s->pid, s->comm); |
| 953 | read_cmdline(&G.line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm); | ||
| 954 | print_line_buf(); | ||
| 955 | s++; | 958 | s++; |
| 956 | } | 959 | } |
| 957 | #undef HDR_STR | ||
| 958 | #undef MIN_WIDTH | ||
| 959 | } | 960 | } |
| 960 | 961 | ||
| 961 | #endif /* end TOPMEM support */ | 962 | #endif /* end TOPMEM support */ |
