From faac60c8fcc31dcc5cbd4bd575a00cea18c42d7d Mon Sep 17 00:00:00 2001 From: Stanislav Sedov Date: Sat, 14 Apr 2007 10:16:52 +0000 Subject: [PATCH] - Add new 'a' switch and runtime option that allows 'top' to display process titles extracted from argv vector instead of the real executable names. This is useful when you want to watch applications that set their status information via setproctitle(3). Approved by: alfred MFC after: 2 weeks --- contrib/top/top.X | 8 ++++- contrib/top/top.c | 21 ++++++++++--- contrib/top/top.h | 5 +++ usr.bin/top/machine.c | 73 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/contrib/top/top.X b/contrib/top/top.X index ff1a1d9aca8..304ee91e2b6 100644 --- a/contrib/top/top.X +++ b/contrib/top/top.X @@ -10,7 +10,7 @@ top \- display and update information about the top cpu processes .SH SYNOPSIS .B top [ -.B \-bCHIinqStuv +.B \-abCHIinqStuv ] [ .BI \-d count ] [ @@ -78,6 +78,12 @@ the \*(lqWCPU\*(rq column respectively. Show system processes in the display. Normally, system processes such as the pager and the swapper are not shown. This option makes them visible. .TP +.B \-a +Display command names derived from the argv[] vector, rather than real +executable name. It's useful when you want to watch applications, that +puts their status information there. If the real name differs from argv[0], +it will be displayed in parenthesis. +.TP .B \-b Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is ignored. Interrupt characters (such as ^C and ^\e) still have an effect. diff --git a/contrib/top/top.c b/contrib/top/top.c index 81933e4454c..970d143649d 100644 --- a/contrib/top/top.c +++ b/contrib/top/top.c @@ -65,6 +65,8 @@ extern char *optarg; /* imported from screen.c */ extern int overstrike; +static int fmt_flags = 0; + /* signal handling routines */ sigret_t leave(); sigret_t onalrm(); @@ -193,9 +195,9 @@ char *argv[]; fd_set readfds; #ifdef ORDER - static char command_chars[] = "\f qh?en#sdkriIutHmSCo"; + static char command_chars[] = "\f qh?en#sdkriIutHmSCao"; #else - static char command_chars[] = "\f qh?en#sdkriIutHmSC"; + static char command_chars[] = "\f qh?en#sdkriIutHmSCa"; #endif /* these defines enumerate the "strchr"s of the commands in command_chars */ #define CMD_redraw 0 @@ -219,8 +221,9 @@ char *argv[]; #define CMD_viewtog 17 #define CMD_viewsys 18 #define CMD_wcputog 19 +#define CMD_showargs 20 #ifdef ORDER -#define CMD_order 20 +#define CMD_order 21 #endif /* set the buffer for stdout */ @@ -277,7 +280,7 @@ char *argv[]; optind = 1; } - while ((i = getopt(ac, av, "CSIHbinquvs:d:U:m:o:t")) != EOF) + while ((i = getopt(ac, av, "CSIHabinquvs:d:U:m:o:t")) != EOF) { switch(i) { @@ -316,6 +319,10 @@ char *argv[]; interactive = No; break; + case 'a': + fmt_flags ^= FMT_SHOWARGS; + break; + case 'd': /* number of displays to show */ if ((i = atoiwi(optarg)) == Invalid || i == 0) { @@ -651,7 +658,8 @@ restart: /* now show the top "n" processes. */ for (i = 0; i < active_procs; i++) { - (*d_process)(i, format_next_process(processes, get_userid)); + (*d_process)(i, format_next_process(processes, get_userid, + fmt_flags)); } } else @@ -1020,6 +1028,9 @@ restart: case CMD_viewsys: ps.system = !ps.system; break; + case CMD_showargs: + fmt_flags ^= FMT_SHOWARGS; + break; #ifdef ORDER case CMD_order: new_message(MT_standout, diff --git a/contrib/top/top.h b/contrib/top/top.h index 59cdeed2d7d..2b32d1007fd 100644 --- a/contrib/top/top.h +++ b/contrib/top/top.h @@ -39,4 +39,9 @@ char *version_string(); enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX }; +/* + * Format modifiers + */ +#define FMT_SHOWARGS 0x00000001 + extern enum displaymodes displaymode; diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index d3f9ef08375..7d973b8fabe 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "top.h" #include "machine.h" @@ -649,7 +650,7 @@ get_process_info(struct system_info *si, struct process_select *sel, static char fmt[128]; /* static area where result is built */ char * -format_next_process(caddr_t handle, char *(*get_userid)(int)) +format_next_process(caddr_t handle, char *(*get_userid)(int), int flags) { struct kinfo_proc *pp; const struct kinfo_proc *oldp; @@ -661,6 +662,8 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) struct rusage ru, *rup; long p_tot, s_tot; char *proc_fmt, thr_buf[6]; + char *cmdbuf = NULL; + char **args; /* find and remember the next proc structure */ hp = (struct handle *)handle; @@ -723,6 +726,65 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) break; } + cmdbuf = (char *)malloc(cmdlengthdelta + 1); + if (cmdbuf == NULL) { + warn("malloc(%d)", cmdlengthdelta + 1); + return NULL; + } + + if (!(flags & FMT_SHOWARGS)) { + snprintf(cmdbuf, cmdlengthdelta, "%s", pp->ki_comm); + } + else if (pp->ki_args == NULL || + (args = kvm_getargv(kd, pp, cmdlengthdelta)) == NULL || !(*args)) + snprintf(cmdbuf, cmdlengthdelta, "[%s]", pp->ki_comm); + else { + char *src, *dst, *argbuf; + char *cmd; + size_t argbuflen; + size_t len; + + argbuflen = cmdlengthdelta * 4; + argbuf = (char *)malloc(argbuflen + 1); + if (argbuf == NULL) { + warn("malloc(%d)", argbuflen + 1); + free(cmdbuf); + return NULL; + } + + dst = argbuf; + + /* Extract cmd name from argv */ + cmd = strrchr(*args, '/'); + if (cmd == NULL) + cmd = *args; + else + cmd++; + + for (; (src = *args++) != NULL; ) { + if (*src == '\0') + continue; + len = (argbuflen - (dst - argbuf) - 1) / 4; + strvisx(dst, src, strlen(src) < len ? strlen(src) : len, + VIS_NL | VIS_CSTYLE); + while (*dst != '\0') + dst++; + if ((argbuflen - (dst - argbuf) - 1) / 4 > 0) + *dst++ = ' '; /* add delimiting space */ + } + if (dst != argbuf && dst[-1] == ' ') + dst--; + *dst = '\0'; + + if (strcmp(cmd, pp->ki_comm) != 0 ) + snprintf(cmdbuf, cmdlengthdelta, "%s (%s)",argbuf, \ + pp->ki_comm); + else + strlcpy(cmdbuf, argbuf, cmdlengthdelta); + + free(argbuf); + } + if (displaymode == DISP_IO) { oldp = get_old_proc(pp); if (oldp != NULL) { @@ -752,7 +814,10 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) s_tot == 0 ? 0.0 : (p_tot * 100.0 / s_tot), screen_width > cmdlengthdelta ? screen_width - cmdlengthdelta : 0, - printable(pp->ki_comm)); + printable(cmdbuf)); + + free(cmdbuf); + return (fmt); } @@ -777,7 +842,9 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) format_time(cputime), ps.wcpu ? 100.0 * weighted_cpu(pct, pp) : 100.0 * pct, screen_width > cmdlengthdelta ? screen_width - cmdlengthdelta : 0, - printable(pp->ki_comm)); + printable(cmdbuf)); + + free(cmdbuf); /* return the result */ return (fmt);