Edd Barrett
2016-02-10 23:04:18 UTC
Hey,
I'd like top(1)'s filter feature (-g) to search process arguments. This
would make searching for (e.g.) Python scripts by name much easier. The
current behaviour only searches the program name, which for scripts is
the interpreter binary name (e.g. python2.7). Currently the best you
could do to find a Python script by name is to filter for "python", then
press "C" to enable argument display, then scan the args by eyeball.
Here is a diff that allows searching of arguments, but only if
arguments are currently being displayed.
I know the timing is bad, but any comments?
Index: machine.c
===================================================================
RCS file: /home/edd/cvsync/src/usr.bin/top/machine.c,v
retrieving revision 1.85
diff -u -p -r1.85 machine.c
--- machine.c 20 Aug 2015 22:32:42 -0000 1.85
+++ machine.c 6 Feb 2016 15:12:42 -0000
@@ -57,6 +57,8 @@
static int swapmode(int *, int *);
static char *state_abbr(struct kinfo_proc *);
static char *format_comm(struct kinfo_proc *);
+int cmd_matches(struct kinfo_proc *proc, char *cmd);
+static char **get_proc_args(struct kinfo_proc *kp);
/* get_process_info passes back a handle. This is what it looks like: */
@@ -360,6 +362,54 @@ getprocs(int op, int arg, int *cnt)
return (procbase);
}
+static char **
+get_proc_args(struct kinfo_proc *kp)
+{
+ static char **s;
+ size_t siz = 100;
+ int mib[4];
+
+ for (;; siz *= 2) {
+ if ((s = realloc(s, siz)) == NULL)
+ err(1, NULL);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = kp->p_pid;
+ mib[3] = KERN_PROC_ARGV;
+ if (sysctl(mib, 4, s, &siz, NULL, 0) == 0)
+ break;
+ if (errno != ENOMEM)
+ return (NULL);
+ }
+ return (s);
+}
+
+int
+cmd_matches(struct kinfo_proc *proc, char *term)
+{
+ extern int show_args;
+ char **args = NULL, **arg = NULL;
+
+ if (!term) {
+ /* No command filter set */
+ return (1);
+ } else {
+ /* Filter set, process name needs to contain term */
+ if (strstr(proc->p_comm, term)) {
+ return (1);
+ }
+ /* If showing arguments, search those as well */
+ if (show_args) {
+ args = get_proc_args(proc);
+ for (arg = args; *arg != NULL; arg++) {
+ if (strstr(*arg, term))
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
caddr_t
get_process_info(struct system_info *si, struct process_select *sel,
int (*compare) (const void *, const void *))
@@ -421,8 +471,7 @@ get_process_info(struct system_info *si,
(!hide_uid || pp->p_ruid != sel->huid) &&
(!show_uid || pp->p_ruid == sel->uid) &&
(!show_pid || pp->p_pid == sel->pid) &&
- (!show_cmd || strstr(pp->p_comm,
- sel->command))) {
+ (!show_cmd || cmd_matches(pp, sel->command))) {
*prefp++ = pp;
active_procs++;
}
@@ -462,27 +511,17 @@ state_abbr(struct kinfo_proc *pp)
static char *
format_comm(struct kinfo_proc *kp)
{
- static char **s, buf[MAX_COLS];
- size_t siz = 100;
- char **p;
- int mib[4];
+ static char buf[MAX_COLS];
+ char **p, **s;
extern int show_args;
if (!show_args)
return (kp->p_comm);
- for (;; siz *= 2) {
- if ((s = realloc(s, siz)) == NULL)
- err(1, NULL);
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC_ARGS;
- mib[2] = kp->p_pid;
- mib[3] = KERN_PROC_ARGV;
- if (sysctl(mib, 4, s, &siz, NULL, 0) == 0)
- break;
- if (errno != ENOMEM)
- return (kp->p_comm);
- }
+ s = get_proc_args(kp);
+ if (s == NULL)
+ return (kp->p_comm);
+
buf[0] = '\0';
for (p = s; *p != NULL; p++) {
if (p != s)
Index: top.1
===================================================================
RCS file: /home/edd/cvsync/src/usr.bin/top/top.1,v
retrieving revision 1.66
diff -u -p -r1.66 top.1
--- top.1 6 May 2015 07:53:29 -0000 1.66
+++ top.1 6 Feb 2016 15:03:50 -0000
@@ -107,7 +107,8 @@ The default is 1 for dumb terminals.
.It Fl g Ar string
Display only processes that contain
.Ar string
-in their command name.
+in their command name. If displaying of arguments is enabled, the
+arguments are searched too.
.It Fl H
Show process threads in the display.
Normally, only the main process is shown.
@@ -305,7 +306,8 @@ command.
.It g Ar string
Display only processes that contain
.Ar string
-in their command name.
+in their command name. If displaying of arguments is enabled, the
+arguments are searched too.
.Sq g+
shows all processes.
.It H
I'd like top(1)'s filter feature (-g) to search process arguments. This
would make searching for (e.g.) Python scripts by name much easier. The
current behaviour only searches the program name, which for scripts is
the interpreter binary name (e.g. python2.7). Currently the best you
could do to find a Python script by name is to filter for "python", then
press "C" to enable argument display, then scan the args by eyeball.
Here is a diff that allows searching of arguments, but only if
arguments are currently being displayed.
I know the timing is bad, but any comments?
Index: machine.c
===================================================================
RCS file: /home/edd/cvsync/src/usr.bin/top/machine.c,v
retrieving revision 1.85
diff -u -p -r1.85 machine.c
--- machine.c 20 Aug 2015 22:32:42 -0000 1.85
+++ machine.c 6 Feb 2016 15:12:42 -0000
@@ -57,6 +57,8 @@
static int swapmode(int *, int *);
static char *state_abbr(struct kinfo_proc *);
static char *format_comm(struct kinfo_proc *);
+int cmd_matches(struct kinfo_proc *proc, char *cmd);
+static char **get_proc_args(struct kinfo_proc *kp);
/* get_process_info passes back a handle. This is what it looks like: */
@@ -360,6 +362,54 @@ getprocs(int op, int arg, int *cnt)
return (procbase);
}
+static char **
+get_proc_args(struct kinfo_proc *kp)
+{
+ static char **s;
+ size_t siz = 100;
+ int mib[4];
+
+ for (;; siz *= 2) {
+ if ((s = realloc(s, siz)) == NULL)
+ err(1, NULL);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = kp->p_pid;
+ mib[3] = KERN_PROC_ARGV;
+ if (sysctl(mib, 4, s, &siz, NULL, 0) == 0)
+ break;
+ if (errno != ENOMEM)
+ return (NULL);
+ }
+ return (s);
+}
+
+int
+cmd_matches(struct kinfo_proc *proc, char *term)
+{
+ extern int show_args;
+ char **args = NULL, **arg = NULL;
+
+ if (!term) {
+ /* No command filter set */
+ return (1);
+ } else {
+ /* Filter set, process name needs to contain term */
+ if (strstr(proc->p_comm, term)) {
+ return (1);
+ }
+ /* If showing arguments, search those as well */
+ if (show_args) {
+ args = get_proc_args(proc);
+ for (arg = args; *arg != NULL; arg++) {
+ if (strstr(*arg, term))
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
caddr_t
get_process_info(struct system_info *si, struct process_select *sel,
int (*compare) (const void *, const void *))
@@ -421,8 +471,7 @@ get_process_info(struct system_info *si,
(!hide_uid || pp->p_ruid != sel->huid) &&
(!show_uid || pp->p_ruid == sel->uid) &&
(!show_pid || pp->p_pid == sel->pid) &&
- (!show_cmd || strstr(pp->p_comm,
- sel->command))) {
+ (!show_cmd || cmd_matches(pp, sel->command))) {
*prefp++ = pp;
active_procs++;
}
@@ -462,27 +511,17 @@ state_abbr(struct kinfo_proc *pp)
static char *
format_comm(struct kinfo_proc *kp)
{
- static char **s, buf[MAX_COLS];
- size_t siz = 100;
- char **p;
- int mib[4];
+ static char buf[MAX_COLS];
+ char **p, **s;
extern int show_args;
if (!show_args)
return (kp->p_comm);
- for (;; siz *= 2) {
- if ((s = realloc(s, siz)) == NULL)
- err(1, NULL);
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC_ARGS;
- mib[2] = kp->p_pid;
- mib[3] = KERN_PROC_ARGV;
- if (sysctl(mib, 4, s, &siz, NULL, 0) == 0)
- break;
- if (errno != ENOMEM)
- return (kp->p_comm);
- }
+ s = get_proc_args(kp);
+ if (s == NULL)
+ return (kp->p_comm);
+
buf[0] = '\0';
for (p = s; *p != NULL; p++) {
if (p != s)
Index: top.1
===================================================================
RCS file: /home/edd/cvsync/src/usr.bin/top/top.1,v
retrieving revision 1.66
diff -u -p -r1.66 top.1
--- top.1 6 May 2015 07:53:29 -0000 1.66
+++ top.1 6 Feb 2016 15:03:50 -0000
@@ -107,7 +107,8 @@ The default is 1 for dumb terminals.
.It Fl g Ar string
Display only processes that contain
.Ar string
-in their command name.
+in their command name. If displaying of arguments is enabled, the
+arguments are searched too.
.It Fl H
Show process threads in the display.
Normally, only the main process is shown.
@@ -305,7 +306,8 @@ command.
.It g Ar string
Display only processes that contain
.Ar string
-in their command name.
+in their command name. If displaying of arguments is enabled, the
+arguments are searched too.
.Sq g+
shows all processes.
.It H
--
Best Regards
Edd Barrett
http://www.theunixzoo.co.uk
Best Regards
Edd Barrett
http://www.theunixzoo.co.uk