top(1): reimplement header formatting as sbuf
The current header formatting is a giant format string that changes global state during the format process. Make the following changes: - use sbuf to build up the header rather than use the above pseudo-dynamic one - Change name length to 10 - Reduce size of RES and SIZE by making humanize more aggressive - Restore a version number line to the copyright. This may be required by the copyright (and may not be; its unclear) This is also a pre-req to implementing TOPCOLOR from newer versions of top(1) Discussed with: allanjude, rpolka, danfe, rgrimes Differential Revision: https://reviews.freebsd.org/D15801
This commit is contained in:
parent
9e86e7ede7
commit
df25a45659
@ -16,5 +16,5 @@ NO_WERROR=
|
|||||||
.endif
|
.endif
|
||||||
CFLAGS.clang=-Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=cast-qual
|
CFLAGS.clang=-Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=cast-qual
|
||||||
|
|
||||||
LIBADD= ncursesw m kvm jail util
|
LIBADD= ncursesw m kvm jail util sbuf
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Top users/processes display for Unix
|
* Top users/processes display for Unix
|
||||||
|
* Version 3
|
||||||
*
|
*
|
||||||
* This program may be freely redistributed,
|
* This program may be freely redistributed,
|
||||||
* but this entire comment MUST remain intact.
|
* but this entire comment MUST remain intact.
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <sys/priority.h>
|
#include <sys/priority.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
@ -49,18 +50,14 @@
|
|||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
|
||||||
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
|
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
|
||||||
#define SMPUNAMELEN 13
|
|
||||||
#define UPUNAMELEN 15
|
|
||||||
|
|
||||||
extern struct timeval timeout;
|
extern struct timeval timeout;
|
||||||
static int smpmode;
|
static int smpmode;
|
||||||
enum displaymodes displaymode;
|
enum displaymodes displaymode;
|
||||||
static int namelength = 8;
|
static const int namelength = 10;
|
||||||
/* TOP_JID_LEN based on max of 999999 */
|
/* TOP_JID_LEN based on max of 999999 */
|
||||||
#define TOP_JID_LEN 7
|
#define TOP_JID_LEN 6
|
||||||
#define TOP_SWAP_LEN 6
|
#define TOP_SWAP_LEN 5
|
||||||
static int jidlength;
|
|
||||||
static int swaplength;
|
|
||||||
static int cmdlengthdelta;
|
static int cmdlengthdelta;
|
||||||
|
|
||||||
/* get_process_info passes back a handle. This is what it looks like: */
|
/* get_process_info passes back a handle. This is what it looks like: */
|
||||||
@ -92,23 +89,11 @@ static const char io_header[] =
|
|||||||
static const char io_Proc_format[] =
|
static const char io_Proc_format[] =
|
||||||
"%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s";
|
"%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s";
|
||||||
|
|
||||||
/* XXX: build up header instead of statically defining them.
|
|
||||||
* This will also allow for a "format string" to be supplied
|
|
||||||
* as an argument to top(1) instead of having predefined options */
|
|
||||||
static const char smp_header_thr_and_pid[] =
|
|
||||||
" %s%*s %-*.*s THR PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
|
|
||||||
static const char smp_header_id_only[] =
|
|
||||||
" %s%*s %-*.*s PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
|
|
||||||
static const char smp_Proc_format[] =
|
static const char smp_Proc_format[] =
|
||||||
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s";
|
"%5d%*s %-*.*s %s%3d %4s%6s %5s%*.*s %-6.6s %2d%7s %6.2f%% %.*s";
|
||||||
|
|
||||||
static char up_header_thr_and_pid[] =
|
|
||||||
" %s%*s %-*.*s THR PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
|
|
||||||
static char up_header_id_only[] =
|
|
||||||
" %s%*s %-*.*s PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
|
|
||||||
static char up_Proc_format[] =
|
static char up_Proc_format[] =
|
||||||
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s";
|
"%5d%*s %-*.*s %s%3d %4s%6s %5s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s";
|
||||||
|
|
||||||
|
|
||||||
/* process state names for the "STATE" column of the display */
|
/* process state names for the "STATE" column of the display */
|
||||||
/* the extra nulls in the string "run" are for adding a slash and
|
/* the extra nulls in the string "run" are for adding a slash and
|
||||||
@ -325,12 +310,6 @@ machine_init(struct statics *statics)
|
|||||||
NULL, 0) == 0 && carc_en == 1)
|
NULL, 0) == 0 && carc_en == 1)
|
||||||
carc_enabled = 1;
|
carc_enabled = 1;
|
||||||
|
|
||||||
namelength = MAXLOGNAME;
|
|
||||||
if (smpmode && namelength > SMPUNAMELEN)
|
|
||||||
namelength = SMPUNAMELEN;
|
|
||||||
else if (namelength > UPUNAMELEN)
|
|
||||||
namelength = UPUNAMELEN;
|
|
||||||
|
|
||||||
kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
|
kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
|
||||||
if (kd == NULL)
|
if (kd == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -407,63 +386,46 @@ machine_init(struct statics *statics)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
char *
|
||||||
format_header(const char *uname_field)
|
format_header(const char *uname_field)
|
||||||
{
|
{
|
||||||
static char Header[128];
|
static struct sbuf* header = NULL;
|
||||||
const char *prehead;
|
|
||||||
|
|
||||||
if (ps.jail)
|
/* clean up from last time. */
|
||||||
jidlength = TOP_JID_LEN + 1; /* +1 for extra left space. */
|
if (header != NULL) {
|
||||||
else
|
sbuf_delete(header);
|
||||||
jidlength = 0;
|
}
|
||||||
|
header = sbuf_new_auto();
|
||||||
if (ps.swap)
|
|
||||||
swaplength = TOP_SWAP_LEN + 1; /* +1 for extra left space */
|
|
||||||
else
|
|
||||||
swaplength = 0;
|
|
||||||
|
|
||||||
switch (displaymode) {
|
switch (displaymode) {
|
||||||
case DISP_CPU:
|
case DISP_CPU: {
|
||||||
/*
|
sbuf_printf(header, " %s", ps.thread_id ? " THR" : "PID");
|
||||||
* The logic of picking the right header is confusing, and
|
sbuf_printf(header, "%*s", ps.jail ? TOP_JID_LEN : 0,
|
||||||
* depends on too much. We should instead have a struct of
|
ps.jail ? " JID" : "");
|
||||||
* "header name", and "header format" which we build up.
|
sbuf_printf(header, " %-*.*s", namelength, namelength, uname_field);
|
||||||
* This would also fix the duplicate of effort into up vs smp
|
sbuf_cat(header, " THR PRI NICE SIZE RES");
|
||||||
* mode.
|
sbuf_printf(header, "%*s", ps.swap ? TOP_SWAP_LEN : 0,
|
||||||
*/
|
ps.swap ? " SWAP" : "");
|
||||||
if (smpmode) {
|
sbuf_printf(header, "%s", smpmode ? " STATE C " : " STATE ");
|
||||||
prehead = ps.thread ?
|
sbuf_cat(header, "TIME");
|
||||||
smp_header_id_only : smp_header_thr_and_pid;
|
sbuf_printf(header, " %7s", ps.wcpu ? "WCPU" : "CPU");
|
||||||
snprintf(Header, sizeof(Header), prehead,
|
sbuf_cat(header, " COMMAND");
|
||||||
ps.thread_id ? " THR" : "PID",
|
sbuf_finish(header);
|
||||||
jidlength, ps.jail ? " JID" : "",
|
|
||||||
namelength, namelength, uname_field,
|
|
||||||
swaplength, ps.swap ? " SWAP" : "",
|
|
||||||
ps.wcpu ? "WCPU" : "CPU");
|
|
||||||
} else {
|
|
||||||
prehead = ps.thread ?
|
|
||||||
up_header_id_only : up_header_thr_and_pid;
|
|
||||||
snprintf(Header, sizeof(Header), prehead,
|
|
||||||
ps.thread_id ? " THR" : "PID",
|
|
||||||
jidlength, ps.jail ? " JID" : "",
|
|
||||||
namelength, namelength, uname_field,
|
|
||||||
swaplength, ps.swap ? " SWAP" : "",
|
|
||||||
ps.wcpu ? "WCPU" : "CPU");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DISP_IO:
|
}
|
||||||
prehead = io_header;
|
case DISP_IO: {
|
||||||
snprintf(Header, sizeof(Header), prehead,
|
sbuf_printf(header, io_header,
|
||||||
ps.thread_id ? " THR" : "PID",
|
ps.thread_id ? " THR" : "PID",
|
||||||
jidlength, ps.jail ? " JID" : "",
|
ps.jail ? TOP_JID_LEN : 0, ps.jail ? " JID" : "",
|
||||||
namelength, namelength, uname_field);
|
namelength, namelength, uname_field);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case DISP_MAX:
|
case DISP_MAX:
|
||||||
assert("displaymode must not be set to DISP_MAX");
|
assert("displaymode must not be set to DISP_MAX");
|
||||||
}
|
}
|
||||||
cmdlengthdelta = strlen(Header) - 7;
|
|
||||||
return (Header);
|
cmdlengthdelta = sbuf_len(header) - 7;
|
||||||
|
return sbuf_data(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int swappgsin = -1;
|
static int swappgsin = -1;
|
||||||
@ -923,7 +885,7 @@ format_next_process(void* xhandle, char *(*get_userid)(int), int flags)
|
|||||||
long p_tot, s_tot;
|
long p_tot, s_tot;
|
||||||
const char *proc_fmt;
|
const char *proc_fmt;
|
||||||
char thr_buf[6];
|
char thr_buf[6];
|
||||||
char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1];
|
char jid_buf[TOP_JID_LEN], swap_buf[TOP_SWAP_LEN];
|
||||||
char *cmdbuf = NULL;
|
char *cmdbuf = NULL;
|
||||||
char **args;
|
char **args;
|
||||||
const int cmdlen = 128;
|
const int cmdlen = 128;
|
||||||
@ -1081,13 +1043,13 @@ format_next_process(void* xhandle, char *(*get_userid)(int), int flags)
|
|||||||
jid_buf[0] = '\0';
|
jid_buf[0] = '\0';
|
||||||
else
|
else
|
||||||
snprintf(jid_buf, sizeof(jid_buf), "%*d",
|
snprintf(jid_buf, sizeof(jid_buf), "%*d",
|
||||||
jidlength - 1, pp->ki_jid);
|
TOP_JID_LEN - 1, pp->ki_jid);
|
||||||
|
|
||||||
if (ps.swap == 0)
|
if (ps.swap == 0)
|
||||||
swap_buf[0] = '\0';
|
swap_buf[0] = '\0';
|
||||||
else
|
else
|
||||||
snprintf(swap_buf, sizeof(swap_buf), "%*s",
|
snprintf(swap_buf, sizeof(swap_buf), "%*s",
|
||||||
swaplength - 1,
|
TOP_SWAP_LEN - 1,
|
||||||
format_k(pagetok(ki_swap(pp)))); /* XXX */
|
format_k(pagetok(ki_swap(pp)))); /* XXX */
|
||||||
|
|
||||||
if (displaymode == DISP_IO) {
|
if (displaymode == DISP_IO) {
|
||||||
@ -1109,7 +1071,7 @@ format_next_process(void* xhandle, char *(*get_userid)(int), int flags)
|
|||||||
|
|
||||||
snprintf(fmt, sizeof(fmt), io_Proc_format,
|
snprintf(fmt, sizeof(fmt), io_Proc_format,
|
||||||
pp->ki_pid,
|
pp->ki_pid,
|
||||||
jidlength, jid_buf,
|
ps.jail ? TOP_JID_LEN : 0, jid_buf,
|
||||||
namelength, namelength, (*get_userid)(pp->ki_ruid),
|
namelength, namelength, (*get_userid)(pp->ki_ruid),
|
||||||
rup->ru_nvcsw,
|
rup->ru_nvcsw,
|
||||||
rup->ru_nivcsw,
|
rup->ru_nivcsw,
|
||||||
@ -1142,16 +1104,17 @@ format_next_process(void* xhandle, char *(*get_userid)(int), int flags)
|
|||||||
snprintf(thr_buf, sizeof(thr_buf), "%*d ",
|
snprintf(thr_buf, sizeof(thr_buf), "%*d ",
|
||||||
(int)(sizeof(thr_buf) - 2), pp->ki_numthreads);
|
(int)(sizeof(thr_buf) - 2), pp->ki_numthreads);
|
||||||
|
|
||||||
|
|
||||||
snprintf(fmt, sizeof(fmt), proc_fmt,
|
snprintf(fmt, sizeof(fmt), proc_fmt,
|
||||||
(ps.thread_id) ? pp->ki_tid : pp->ki_pid,
|
(ps.thread_id) ? pp->ki_tid : pp->ki_pid,
|
||||||
jidlength, jid_buf,
|
ps.jail ? TOP_JID_LEN : 0, jid_buf,
|
||||||
namelength, namelength, (*get_userid)(pp->ki_ruid),
|
namelength, namelength, (*get_userid)(pp->ki_ruid),
|
||||||
thr_buf,
|
thr_buf,
|
||||||
pp->ki_pri.pri_level - PZERO,
|
pp->ki_pri.pri_level - PZERO,
|
||||||
format_nice(pp),
|
format_nice(pp),
|
||||||
format_k(PROCSIZE(pp)),
|
format_k(PROCSIZE(pp)),
|
||||||
format_k(pagetok(pp->ki_rssize)),
|
format_k(pagetok(pp->ki_rssize)),
|
||||||
swaplength, swaplength, swap_buf,
|
ps.swap ? TOP_SWAP_LEN : 0, ps.swap ? TOP_SWAP_LEN : 0, swap_buf,
|
||||||
status,
|
status,
|
||||||
cpu,
|
cpu,
|
||||||
format_time(cputime),
|
format_time(cputime),
|
||||||
|
@ -78,7 +78,7 @@ struct process_select
|
|||||||
|
|
||||||
/* routines defined by the machine dependent module */
|
/* routines defined by the machine dependent module */
|
||||||
|
|
||||||
const char *format_header(const char *uname_field);
|
char *format_header(const char *uname_field);
|
||||||
char *format_next_process(void* handle, char *(*get_userid)(int),
|
char *format_next_process(void* handle, char *(*get_userid)(int),
|
||||||
int flags);
|
int flags);
|
||||||
void toggle_pcpustats(void);
|
void toggle_pcpustats(void);
|
||||||
|
@ -268,10 +268,8 @@ format_time(long seconds)
|
|||||||
/*
|
/*
|
||||||
* format_k(amt) - format a kilobyte memory value, returning a string
|
* format_k(amt) - format a kilobyte memory value, returning a string
|
||||||
* suitable for display. Returns a pointer to a static
|
* suitable for display. Returns a pointer to a static
|
||||||
* area that changes each call. "amt" is converted to a
|
* area that changes each call. "amt" is converted to a fixed
|
||||||
* string with a trailing "K". If "amt" is 10000 or greater,
|
* size humanize_number call
|
||||||
* then it is formatted as megabytes (rounded) with a
|
|
||||||
* trailing "M".
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -299,7 +297,7 @@ format_k(int64_t amt)
|
|||||||
|
|
||||||
ret = retarray[index];
|
ret = retarray[index];
|
||||||
index = (index + 1) % NUM_STRINGS;
|
index = (index + 1) % NUM_STRINGS;
|
||||||
humanize_number(ret, 6, amt * 1024, "", HN_AUTOSCALE, HN_NOSPACE);
|
humanize_number(ret, 5, amt * 1024, "", HN_AUTOSCALE, HN_NOSPACE);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user