Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Nov 2018 19:41:54 +0100
From:      Christian Barthel <bch@online.de>
To:        freebsd-hackers@freebsd.org
Subject:   top(1): adding grep like selection and system processes
Message-ID:  <878t1j1vrh.fsf@x230.onfire.org>

next in thread | raw e-mail | index | archive | help
--=-=-=
Content-Type: text/plain

Hello, 

I've added two features that I (personally) found useful in top(1): 

A grep-like feature to filter command names in top(1) (inspired by the
OpenBSD top version).  One example may be to filter out all current
virtual machines by using "top -g bhyve" or interactively with "g
bhyve". (there was already a selection field ps.command; so, perhaps
someone is already working on a similar feature?).  It is not possible
to filter with a regular expression.

The second flag is selection of system processes with -K or
interactively toggle between user and system processes.

I want to ask if this is of general interest for FreeBSD users or if its
useful for someone else here?  I've tested it on FreeBSD 13.0-CURRENT.

Christian


--=-=-=
Content-Type: text/x-diff
Content-Disposition: attachment; filename=top-grep-sysproc.patch
Content-Description: top(1) patch to add grep-like feature and system
 process selection. 

diff --git a/usr.bin/top/commands.c b/usr.bin/top/commands.c
index 88f4b0867d4..082f5fcc9af 100644
--- a/usr.bin/top/commands.c
+++ b/usr.bin/top/commands.c
@@ -59,10 +59,12 @@ const struct command all_commands[] =
 	{'H', "toggle the displaying of threads", false, CMD_thrtog},
 	{'h', "show this help text", true, CMD_help},
 	{'?', NULL, true, CMD_help},
+	{'g', "grep command name", false, CMD_grep},
 	{'i', "toggle the displaying of idle processes", false, CMD_idletog},
 	{'I', NULL, false, CMD_idletog},
 	{'j', "toggle the displaying of jail ID", false, CMD_jidtog},
 	{'J', "display processes for only one jail (+ selects all jails)", false, CMD_jail},
+	{'K', "toggle between system and user processes", false, CMD_kern},
 	{'k', "kill processes; send a signal to a list of processes", false, CMD_kill},
 	{'q', "quit" , true, CMD_quit},
 	{'m', "toggle the display between 'cpu' and 'io' modes", false, CMD_viewtog},
diff --git a/usr.bin/top/commands.h b/usr.bin/top/commands.h
index 0071fbe62fc..75fe9756a56 100644
--- a/usr.bin/top/commands.h
+++ b/usr.bin/top/commands.h
@@ -46,6 +46,8 @@ enum cmd_id {
 	CMD_order,
 	CMD_pid	,
 	CMD_toggletid,
+	CMD_grep,
+	CMD_kern,
 };
 
 struct command {
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 374c9da0edf..2fb5b5221b7 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -803,6 +803,13 @@ get_process_info(struct system_info *si, struct process_select *sel,
 			/* skip self */
 			continue;
 
+		if (sel->command && strncmp(pp->ki_comm, sel->command, COMMLEN))
+			/* skip not matching commands */
+			continue;
+
+		if (!sel->user && !(pp->ki_flag & P_SYSTEM) && sel->pid == -1)
+			continue;
+
 		if (!sel->system && (pp->ki_flag & P_SYSTEM) && sel->pid == -1)
 			/* skip system process */
 			continue;
diff --git a/usr.bin/top/machine.h b/usr.bin/top/machine.h
index c3c7777d910..40a36e947b9 100644
--- a/usr.bin/top/machine.h
+++ b/usr.bin/top/machine.h
@@ -63,6 +63,7 @@ struct process_select
     bool idle;		/* show idle processes */
     bool self;		/* show self */
     bool system;		/* show system processes */
+    bool user;                  /* show user processes */
     bool thread;		/* show threads */
     bool thread_id;		/* show thread ids */
 #define TOP_MAX_UIDS 8
@@ -73,7 +74,7 @@ struct process_select
     bool swap;		/* show swap usage */
     bool kidle;		/* show per-CPU idle threads */
     int pid;		/* only this pid (unless pid == -1) */
-    const char *command;	/* only this command (unless == NULL) */
+    char *command;	/* only this command (unless == NULL) */
 };
 
 /* routines defined by the machine dependent module */
diff --git a/usr.bin/top/top.c b/usr.bin/top/top.c
index 2279479409b..3a30bf40d9a 100644
--- a/usr.bin/top/top.c
+++ b/usr.bin/top/top.c
@@ -271,6 +271,7 @@ main(int argc, char *argv[])
     ps.idle    = true;
     ps.self    = true;
     ps.system  = false;
+    ps.user    = true;
     reset_uids();
     ps.thread  = false;
     ps.wcpu    = 1;
@@ -305,14 +306,20 @@ main(int argc, char *argv[])
 	    optind = 1;
 	}
 
-	while ((i = getopt_long(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:p:Ttw", longopts, NULL)) != EOF)
+	while ((i = getopt_long(ac, av, "CSIHKPabg:ijJ:nquvzs:d:U:m:o:p:Ttw", longopts, NULL)) != EOF)
 	{
 	    switch(i)
 	    {
 	      case 'v':			/* show version number */
 			  errx(0, "version FreeBSD");
 			  break;
-
+	      case 'g':
+	                  ps.command = strdup(optarg);
+	                  break;
+	      case 'K':
+			 ps.user = false;
+		         ps.system = true;
+			 break;
 	      case 'u':			/* toggle uid/username display */
 		do_unames = !do_unames;
 		break;
@@ -870,7 +877,15 @@ main(int argc, char *argv[])
 				    topn = newval;
 				}
 				break;
-
+			    case CMD_kern:
+				if (ps.user == false) {
+					ps.user = true;
+					ps.system = false;
+				} else {
+					ps.user = false;
+					ps.system = true;
+				}
+				break;
 			    case CMD_delay:	/* new seconds delay */
 				new_message(MT_standout, "Seconds to delay: ");
 				if ((i = readline(tempbuf1, 8, true)) > -1)
@@ -1027,7 +1042,19 @@ main(int argc, char *argv[])
 				reset_display();
 				putchar('\r');
 				break;
+			    case CMD_grep:
+				new_message(MT_standout,
+				    "command name: ");
+				if (readline(tempbuf2, sizeof(tempbuf2), false) > 0) {
+					if (ps.command != NULL)
+						free(ps.command);
 
+					if (tempbuf2[0] == '+' && tempbuf2[1] == '\0')
+						ps.command = NULL;
+					else
+						ps.command = strdup(tempbuf2);
+				}
+				break;
 			    case CMD_jail:
 				new_message(MT_standout,
 				    "Jail to show (+ for all): ");

--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?878t1j1vrh.fsf>