On Wed, Feb 10, 2016 at 11:04:18PM +0000, Edd Barrett wrote: > 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++) { ^^^^ NULL pointer dereference is possible here.
Also, unclear why you need both arg and args variables. --patrick > + 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 >