← Commit list

236393888

Denys Vlasenko
Denys Vlasenko
2025-08-05
SUCCESS Duration: 154s

Subject

top: consistently NOT use the last column of the display

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

procps/top.c+51 -56
@@ -172,7 +172,8 @@ struct globals {
#if ENABLE_FEATURE_TOP_SMP_CPU
smallint smp_cpu_info; /* one/many cpu info lines? */
#endif
- unsigned lines; /* screen height */
+ unsigned lines; /* screen height */
+ unsigned scr_width; /* width, clamped <= LINE_BUF_SIZE-2 */
#if ENABLE_FEATURE_TOP_INTERACTIVE
struct termios initial_settings;
int scroll_ofs;
@@ -438,7 +439,7 @@ static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total)
#endif
#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
-static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
+static void display_cpus(char *scrbuf, int *lines_rem_p)
{
/*
* xxx% = (cur_jif.xxx - prev_jif.xxx) / (cur_jif.total - prev_jif.total) * 100%
@@ -493,7 +494,7 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
CALC_STAT(softirq);
/*CALC_STAT(steal);*/
- snprintf(scrbuf, scr_width,
+ snprintf(scrbuf, G.scr_width,
/* Barely fits in 79 chars when in "decimals" mode. */
# if ENABLE_FEATURE_TOP_SMP_CPU
"CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
@@ -515,7 +516,7 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
*lines_rem_p -= i;
}
#else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */
-# define display_cpus(scr_width, scrbuf, lines_rem) ((void)0)
+# define display_cpus(scrbuf, lines_rem) ((void)0)
#endif
enum {
@@ -569,18 +570,18 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX])
fclose(f);
}
-static unsigned long display_header(int scr_width, int *lines_rem_p)
+static unsigned long display_header(int *lines_rem_p)
{
char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */
char *buf;
+ unsigned width;
unsigned long meminfo[MI_MAX];
parse_meminfo(meminfo);
/* Output memory info */
- if (scr_width > (int)sizeof(scrbuf))
- scr_width = sizeof(scrbuf);
- snprintf(scrbuf, scr_width,
+ width = (G.scr_width > sizeof(scrbuf)) ? sizeof(scrbuf) : G.scr_width;
+ snprintf(scrbuf, width,
"Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE],
meminfo[MI_MEMFREE],
@@ -594,27 +595,26 @@ static unsigned long display_header(int scr_width, int *lines_rem_p)
/* Display CPU time split as percentage of total time.
* This displays either a cumulative line or one line per CPU.
*/
- display_cpus(scr_width, scrbuf, lines_rem_p);
+ display_cpus(scrbuf, lines_rem_p);
/* Read load average as a string */
buf = stpcpy(scrbuf, "Load average: ");
open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: "));
- scrbuf[scr_width - 1] = '\0';
strchrnul(buf, '\n')[0] = '\0';
- printf(OPT_BATCH_MODE ? "%s\n" : "%s"CLREOL"\n", scrbuf);
+ printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", width - 1, scrbuf);
(*lines_rem_p)--;
return meminfo[MI_MEMTOTAL];
}
-static NOINLINE void display_process_list(int lines_rem, int scr_width)
+static NOINLINE void display_process_list(int lines_rem)
{
enum {
BITS_PER_INT = sizeof(int) * 8
};
top_status_t *s;
- unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_memsize? */
+ unsigned long total_memory = display_header(&lines_rem); /* or use total_memsize? */
/* xxx_shift and xxx_scale variables allow us to replace
* expensive divides with multiply and shift */
unsigned pmem_shift, pmem_scale, pmem_half;
@@ -645,7 +645,7 @@ typedef struct { unsigned quot, rem; } bb_div_t;
#endif
/* what info of the processes is shown */
- printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, scr_width,
+ printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1,
" PID PPID USER STAT RSS %RSS"
IF_FEATURE_TOP_SMP_PROCESS(" CPU")
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU")
@@ -702,11 +702,10 @@ typedef struct { unsigned quot, rem; } bb_div_t;
pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS ? 20 : 2);
/* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
#endif
-
- /* Ok, all preliminary data is ready, go through the list */
- scr_width += 2; /* account for leading '\n' and trailing NUL */
if (lines_rem > ntop - G_scroll_ofs)
lines_rem = ntop - G_scroll_ofs;
+
+ /* Ok, all preliminary data is ready, go through the list */
s = top + G_scroll_ofs;
while (--lines_rem >= 0) {
int n;
@@ -754,8 +753,8 @@ typedef struct { unsigned quot, rem; } bb_div_t;
ppu[6+6+8] = '\0'; /* truncate USER */
}
shortened:
- col = snprintf(line_buf, scr_width,
- "\n" "%s %s %.5s" FMT
+ col = snprintf(line_buf, G.scr_width,
+ "%s %s %.5s" FMT
IF_FEATURE_TOP_SMP_PROCESS(" %3d")
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT)
" ",
@@ -765,17 +764,15 @@ typedef struct { unsigned quot, rem; } bb_div_t;
IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu)
IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu))
);
- if ((int)(scr_width - col) > 1)
- read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm);
- fputs_stdout(line_buf);
- if (!OPT_BATCH_MODE)
- printf(CLREOL);
+ if ((int)(G.scr_width - col) > 1)
+ read_cmdline(line_buf + col, G.scr_width - col, s->pid, s->comm);
+ printf(OPT_BATCH_MODE ? "\n""%s" : "\n""%s"CLREOL, line_buf);
/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */
s++;
}
/* printf(" %d", hist_iterations); */
- printf(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
+ fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
}
#undef UPSCALE
#undef SHOW_STAT
@@ -847,7 +844,7 @@ static int topmem_sort(char *a, char *b)
}
/* display header info (meminfo / loadavg) */
-static void display_topmem_header(int scr_width, int *lines_rem_p)
+static void display_topmem_header(int *lines_rem_p)
{
unsigned long meminfo[MI_MAX];
@@ -859,7 +856,7 @@ static void display_topmem_header(int scr_width, int *lines_rem_p)
meminfo[MI_ANONPAGES],
meminfo[MI_MAPPED],
meminfo[MI_MEMFREE]);
- printf(OPT_BATCH_MODE ? "%.*s\n" : HOME"%.*s"CLREOL"\n", scr_width, line_buf);
+ printf(OPT_BATCH_MODE ? "%.*s\n" : HOME"%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
snprintf(line_buf, LINE_BUF_SIZE,
" slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu",
@@ -868,13 +865,13 @@ static void display_topmem_header(int scr_width, int *lines_rem_p)
meminfo[MI_CACHED],
meminfo[MI_DIRTY],
meminfo[MI_WRITEBACK]);
- printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", scr_width, line_buf);
+ printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
snprintf(line_buf, LINE_BUF_SIZE,
"Swap total:%lu free:%lu", // TODO: % used?
meminfo[MI_SWAPTOTAL],
meminfo[MI_SWAPFREE]);
- printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", scr_width, line_buf);
+ printf(OPT_BATCH_MODE ? "%.*s\n" : "%.*s"CLREOL"\n", G.scr_width - 1, line_buf);
(*lines_rem_p) -= 3;
}
@@ -889,14 +886,14 @@ static void ulltoa4_and_space(unsigned long long ul, char buf[5])
smart_ulltoa4(ul, buf, " mgtpezy")[0] = ' ';
}
-static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
+static NOINLINE void display_topmem_process_list(int lines_rem)
{
#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(scr_width, &lines_rem);
+ display_topmem_header(&lines_rem);
strcpy(line_buf, HDR_STR " COMMAND");
/* Mark the ^FIELD^ we sort by */
@@ -905,7 +902,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
cp[6] = ch;
do *cp++ = ch; while (*cp == ' ');
- printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, scr_width, line_buf);
+ printf(OPT_BATCH_MODE ? "%.*s" : REVERSE"%.*s"NORMAL CLREOL, G.scr_width - 1, line_buf);
lines_rem--;
if (lines_rem > ntop - G_scroll_ofs)
@@ -932,20 +929,19 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
ulltoa5_and_space(s->dirty_sh, &line_buf[6*6]);
ulltoa5_and_space(s->stack , &line_buf[7*6]);
line_buf[8*6] = '\0';
- if (scr_width > (int)MIN_WIDTH) {
- read_cmdline(&line_buf[8*6], scr_width - MIN_WIDTH, s->pid, s->comm);
- }
- printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL, scr_width, line_buf);
+ if ((int)(G.scr_width - MIN_WIDTH) > 1)
+ read_cmdline(&line_buf[8*6], G.scr_width - MIN_WIDTH, s->pid, s->comm);
+ printf(OPT_BATCH_MODE ? "\n""%.*s" : "\n""%.*s"CLREOL, G.scr_width, line_buf);
s++;
}
- printf(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
+ fputs_stdout(OPT_BATCH_MODE ? "\n" : CLREOS"\r");
#undef HDR_STR
#undef MIN_WIDTH
}
#else
-void display_topmem_process_list(int lines_rem, int scr_width);
-int topmem_sort(char *a, char *b);
+//void display_topmem_process_list(int lines_rem);
+//int topmem_sort(char *a, char *b);
#endif /* TOPMEM */
/*
@@ -1189,7 +1185,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
{
duration_t interval;
int iterations;
- unsigned col;
+ unsigned opt;
char *str_interval, *str_iterations;
unsigned scan_mask = TOP_MASK;
@@ -1206,13 +1202,13 @@ int top_main(int argc UNUSED_PARAM, char **argv)
/* all args are options; -n NUM */
make_all_argv_opts(argv); /* options can be specified w/o dash */
- col = getopt32(argv, "d:n:bHm", &str_interval, &str_iterations);
+ opt = getopt32(argv, "d:n:bHm", &str_interval, &str_iterations);
/* NB: -m and -H are accepted even if not configured */
#if ENABLE_FEATURE_TOPMEM
- if (col & OPT_m) /* -m (busybox specific) */
+ if (opt & OPT_m) /* -m (busybox specific) */
scan_mask = TOPMEM_MASK;
#endif
- if (col & OPT_d) {
+ if (opt & OPT_d) {
/* work around for "-d 1" -> "-d -1" done by make_all_argv_opts() */
if (str_interval[0] == '-')
str_interval++;
@@ -1221,13 +1217,13 @@ int top_main(int argc UNUSED_PARAM, char **argv)
if (interval > INT_MAX / 1000)
interval = INT_MAX / 1000;
}
- if (col & OPT_n) {
+ if (opt & OPT_n) {
if (str_iterations[0] == '-')
str_iterations++;
iterations = xatou(str_iterations);
}
#if ENABLE_FEATURE_SHOW_THREADS
- if (col & OPT_H) {
+ if (opt & OPT_H) {
scan_mask |= PSSCAN_TASKS;
}
#endif
@@ -1263,20 +1259,19 @@ int top_main(int argc UNUSED_PARAM, char **argv)
IF_FEATURE_TOP_INTERACTIVE(unsigned new_mask = scan_mask;)
procps_status_t *p = NULL;
- if (OPT_BATCH_MODE) {
- G.lines = INT_MAX;
- col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
- } else {
+ G.lines = INT_MAX;
+ G.scr_width = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
+ if (!OPT_BATCH_MODE) {
G.lines = 24; /* default */
- col = 79;
+ G.scr_width = 80;
/* We output to stdout, we need size of stdout (not stdin)! */
- get_terminal_width_height(STDOUT_FILENO, &col, &G.lines);
- if (G.lines < 5 || col < 10) {
+ get_terminal_width_height(STDOUT_FILENO, &G.scr_width, &G.lines);
+ if (G.lines < 5 || G.scr_width < 10) {
sleep_for_duration(interval);
continue;
}
- if (col > LINE_BUF_SIZE - 2)
- col = LINE_BUF_SIZE - 2;
+ if (G.scr_width > LINE_BUF_SIZE - 2)
+ G.scr_width = LINE_BUF_SIZE - 2;
}
/* read process IDs & status for all the processes */
@@ -1346,11 +1341,11 @@ int top_main(int argc UNUSED_PARAM, char **argv)
#endif
IF_FEATURE_TOP_INTERACTIVE(redraw:)
IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
- display_process_list(G.lines, col);
+ display_process_list(G.lines);
}
#if ENABLE_FEATURE_TOPMEM
else { /* TOPMEM */
- display_topmem_process_list(G.lines, col);
+ display_topmem_process_list(G.lines);
}
#endif
fflush_all();