Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 Jun 2018 15:52:18 +0000 (UTC)
From:      Roman Bogorodskiy <novel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r334531 - head/usr.bin/top
Message-ID:  <201806021552.w52FqIaU031309@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: novel (ports committer)
Date: Sat Jun  2 15:52:18 2018
New Revision: 334531
URL: https://svnweb.freebsd.org/changeset/base/334531

Log:
  top: add -p option and p command to only show a single process
  
  Allow to show only a single process specified by PID. This could
  be done either by running top like 'top -p PID' or using the 'p' command
  inside top.
  
  Reviewed by:	eadler
  Approved by:	eadler
  Obtained from:	OpenBSD
  Differential Revision:	https://reviews.freebsd.org/D15501

Modified:
  head/usr.bin/top/commands.c
  head/usr.bin/top/machine.c
  head/usr.bin/top/machine.h
  head/usr.bin/top/top.1
  head/usr.bin/top/top.c
  head/usr.bin/top/top.h
  head/usr.bin/top/utils.c
  head/usr.bin/top/utils.h

Modified: head/usr.bin/top/commands.c
==============================================================================
--- head/usr.bin/top/commands.c	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/commands.c	Sat Jun  2 15:52:18 2018	(r334531)
@@ -92,6 +92,7 @@ o       - specify sort order (pri, size, res, cpu, tim
 o       - specify sort order (vcsw, ivcsw, read, write, fault, total, jid, pid)\n",
 	    stdout);
 	fputs("\
+p       - display one process (+ selects all processes)\n\
 P       - toggle the displaying of per-CPU statistics\n\
 r       - renice a process\n\
 s       - change number of seconds to delay between updates\n\

Modified: head/usr.bin/top/machine.c
==============================================================================
--- head/usr.bin/top/machine.c	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/machine.c	Sat Jun  2 15:52:18 2018	(r334531)
@@ -764,6 +764,7 @@ get_process_info(struct system_info *si, struct proces
 	int show_self;
 	int show_system;
 	int show_uid;
+	int show_pid;
 	int show_kidle;
 
 	/*
@@ -783,7 +784,7 @@ get_process_info(struct system_info *si, struct proces
 		previous_pref = malloc(nproc * sizeof(*previous_pref));
 		if (previous_procs == NULL || previous_pref == NULL) {
 			(void) fprintf(stderr, "top: Out of memory.\n");
-			quit(23);
+			quit(TOP_EX_SYS_ERROR);
 		}
 		previous_proc_count_max = nproc;
 	}
@@ -822,7 +823,7 @@ get_process_info(struct system_info *si, struct proces
 	}
 	if (pref == NULL || pbase == NULL || pcpu == NULL) {
 		(void) fprintf(stderr, "top: Out of memory.\n");
-		quit(23);
+		quit(TOP_EX_SYS_ERROR);
 	}
 	/* get a pointer to the states summary array */
 	si->procstates = process_states;
@@ -833,6 +834,7 @@ get_process_info(struct system_info *si, struct proces
 	show_self = sel->self == -1;
 	show_system = sel->system;
 	show_uid = sel->uid[0] != -1;
+	show_pid = sel->pid != -1;
 	show_kidle = sel->kidle;
 
 	/* count up process states and get pointers to interesting procs */
@@ -894,6 +896,9 @@ get_process_info(struct system_info *si, struct proces
 			/* skip proc. that don't belong to the selected UID */
 			continue;
 
+		if (show_pid && pp->ki_pid != sel->pid)
+			continue;
+
 		*prefp++ = pp;
 		active_procs++;
 	}
@@ -1177,12 +1182,12 @@ getsysctl(const char *name, void *ptr, size_t len)
 	if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
 		fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
 		    strerror(errno));
-		quit(23);
+		quit(TOP_EX_SYS_ERROR);
 	}
 	if (nlen != len) {
 		fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n",
 		    name, (unsigned long)len, (unsigned long)nlen);
-		quit(23);
+		quit(TOP_EX_SYS_ERROR);
 	}
 }
 

Modified: head/usr.bin/top/machine.h
==============================================================================
--- head/usr.bin/top/machine.h	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/machine.h	Sat Jun  2 15:52:18 2018	(r334531)
@@ -69,6 +69,7 @@ struct process_select
     int jail;		/* show jail ID */
     int swap;		/* show swap usage */
     int kidle;		/* show per-CPU idle threads */
+    pid_t pid;		/* only this pid (unless pid == -1) */
     char *command;	/* only this command (unless == NULL) */
 };
 

Modified: head/usr.bin/top/top.1
==============================================================================
--- head/usr.bin/top/top.1	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/top.1	Sat Jun  2 15:52:18 2018	(r334531)
@@ -15,6 +15,11 @@ top \- display and update information about the top cp
 .BI \-m io | cpu
 ] [
 .BI \-o field
+]
+.br
+.ti +4
+[
+.BI \-p pid
 ] [
 .BI \-s time
 ] [
@@ -178,6 +183,10 @@ is the name of the column as seen in the output, but i
 \*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
 \*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
 .TP
+.BI \-p pid
+Show only the process
+.IR pid .
+.TP
 .BI \-J jail
 Show only those processes owned by
 .IR jail .
@@ -319,6 +328,10 @@ Change the order in which the display is sorted.  This
 available on all systems.  The sort key names vary from system to system
 but usually include:  \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
 \*(lqtime\*(rq.  The default is cpu.
+.TP
+.B p
+Display a specific process (prompt for pid).
+If the pid specified is simply \*(lq+\*(rq, then show all processes.
 .TP
 .B e
 Display a list of system errors (if any) generated by the last

Modified: head/usr.bin/top/top.c
==============================================================================
--- head/usr.bin/top/top.c	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/top.c	Sat Jun  2 15:52:18 2018	(r334531)
@@ -226,8 +226,9 @@ main(int argc, char *argv[])
     char *order_name = NULL;
     int order_index = 0;
     fd_set readfds;
+    char old_system = false;
 
-    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
+    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwop";
 /* these defines enumerate the "strchr"s of the commands in command_chars */
 #define CMD_redraw	0
 #define CMD_update	1
@@ -256,7 +257,8 @@ main(int argc, char *argv[])
 #define CMD_pcputog	23
 #define CMD_jail	24
 #define CMD_swaptog	25
-#define CMD_order       26
+#define CMD_order	26
+#define CMD_pid		27
 
     /* set the buffer for stdout */
 #ifdef DEBUG
@@ -291,6 +293,7 @@ main(int argc, char *argv[])
     ps.jail    = false;
     ps.swap    = false;
     ps.kidle   = true;
+    ps.pid     = -1; 
     ps.command = NULL;
 
     /* get preset options from the environment */
@@ -316,7 +319,7 @@ main(int argc, char *argv[])
 	    optind = 1;
 	}
 
-	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
+	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:p:tw")) != EOF)
 	{
 	    switch(i)
 	    {
@@ -338,7 +341,8 @@ main(int argc, char *argv[])
 		break;
 
 	      case 'S':			/* show system processes */
-		ps.system = !ps.system;
+		ps.system = true;
+		old_system = true;
 		break;
 
 	      case 'I':                   /* show idle processes */
@@ -371,7 +375,20 @@ main(int argc, char *argv[])
 		    displays = i;
 		}
 		break;
+	      case 'p': {
+		unsigned long long num;
+		const char *errstr;
 
+		num = strtonum(optarg, 0, INT_MAX, &errstr);
+		if (errstr != NULL || !find_pid(num)) {
+			fprintf(stderr, "%s: unknown pid\n", optarg);
+			exit(1);
+		}
+		ps.pid = (pid_t)num;
+		ps.system = true;
+		break;
+	      }
+
 	      case 's':
 		if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
 		{
@@ -456,8 +473,8 @@ main(int argc, char *argv[])
 
 	      default:
 		fprintf(stderr,
-"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
-"       [-J jail] [-U username] [number]\n",
+"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-p pid]\n"
+"       [-s time] [-J jail] [-U username] [number]\n",
 			myname);
 		exit(1);
 	    }
@@ -1018,6 +1035,7 @@ restart:
 				break;
 			    case CMD_viewsys:
 				ps.system = !ps.system;
+				old_system = ps.system;
 				break;
 			    case CMD_showargs:
 				fmt_flags ^= FMT_SHOWARGS;
@@ -1116,6 +1134,36 @@ restart:
 				header_text = format_header(uname_field);
 				reset_display();
 				putchar('\r');
+				break;
+			    case CMD_pid:
+				new_message(MT_standout,
+					"Process id to show (+ for all): ");
+				if (readline(tempbuf2, sizeof(tempbuf2), false) > 0) {
+					if (tempbuf2[0] == '+' &&
+                   			    tempbuf2[1] == '\0') {
+						ps.pid = (pid_t)-1;
+						ps.system = old_system;
+					} else {
+						unsigned long long num;
+						const char *errstr;
+
+						num = strtonum(tempbuf2, 0, INT_MAX,
+							&errstr);
+						if (errstr != NULL || !find_pid(num)) {
+							new_message(MT_standout,
+								" %s: unknown pid",
+								tempbuf2);
+							no_command = true;
+						} else {
+							if (ps.system == false)
+								old_system = false;
+							ps.pid = (pid_t)num;
+							ps.system = true;
+						}
+					}
+					putchar('\r');
+				} else
+					clear_message();
 				break;
 			    default:
 				new_message(MT_standout, " BAD CASE IN SWITCH!");

Modified: head/usr.bin/top/top.h
==============================================================================
--- head/usr.bin/top/top.h	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/top.h	Sat Jun  2 15:52:18 2018	(r334531)
@@ -34,6 +34,9 @@ extern int Header_lines;	/* 7 */
 
 #define NUM_AVERAGES    3
 
+/* Exit code for system errors */
+#define TOP_EX_SYS_ERROR	23
+
 enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
 
 /*

Modified: head/usr.bin/top/utils.c
==============================================================================
--- head/usr.bin/top/utils.c	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/utils.c	Sat Jun  2 15:52:18 2018	(r334531)
@@ -15,10 +15,19 @@
 #include "top.h"
 #include "utils.h"
 
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <kvm.h>
 
+void quit(int);
+
 int
 atoiwi(const char *str)
 {
@@ -416,4 +425,32 @@ format_k2(unsigned long long amt)
     *p = '\0';
 
     return(ret);
+}
+
+int
+find_pid(pid_t pid)
+{
+	kvm_t *kd = NULL;
+	struct kinfo_proc *pbase = NULL;
+	int nproc;
+	int ret = 0;
+
+	kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
+	if (kd == NULL) {
+		fprintf(stderr, "top: kvm_open() failed.\n");
+		quit(TOP_EX_SYS_ERROR);
+	}
+
+	pbase = kvm_getprocs(kd, KERN_PROC_PID, pid, &nproc);
+	if (pbase == NULL) {
+		goto done;
+	}
+
+	if ((nproc == 1) && (pbase->ki_pid == pid)) {
+		ret = 1;
+	}
+
+done:
+	kvm_close(kd);	
+	return ret;
 }

Modified: head/usr.bin/top/utils.h
==============================================================================
--- head/usr.bin/top/utils.h	Sat Jun  2 14:07:27 2018	(r334530)
+++ head/usr.bin/top/utils.h	Sat Jun  2 15:52:18 2018	(r334531)
@@ -10,6 +10,8 @@
  *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
  */
 
+#include <unistd.h>
+
 int atoiwi(const char *);
 char *itoa(unsigned int);
 char *itoa7(unsigned int);
@@ -20,4 +22,5 @@ char *format_time(long);
 char *format_k(int);
 char *format_k2(unsigned long long);
 int string_index(const char *string, char *array[]);
+int find_pid(pid_t pid);
 



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