summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/top/commands.c1
-rw-r--r--usr.bin/top/machine.c13
-rw-r--r--usr.bin/top/machine.h1
-rw-r--r--usr.bin/top/top.113
-rw-r--r--usr.bin/top/top.c60
-rw-r--r--usr.bin/top/top.h3
-rw-r--r--usr.bin/top/utils.c37
-rw-r--r--usr.bin/top/utils.h3
8 files changed, 121 insertions, 10 deletions
diff --git a/usr.bin/top/commands.c b/usr.bin/top/commands.c
index 0edb79268f9e..407f7255454a 100644
--- a/usr.bin/top/commands.c
+++ b/usr.bin/top/commands.c
@@ -92,6 +92,7 @@ o - specify sort order (pri, size, res, cpu, time, threads, jid, pid)\n",
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\
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 91086ae9f399..736e4201ac9e 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -764,6 +764,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
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 process_select *sel,
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 process_select *sel,
}
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 process_select *sel,
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 process_select *sel,
/* 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);
}
}
diff --git a/usr.bin/top/machine.h b/usr.bin/top/machine.h
index 20d6e0faec16..26c467b6efef 100644
--- a/usr.bin/top/machine.h
+++ b/usr.bin/top/machine.h
@@ -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) */
};
diff --git a/usr.bin/top/top.1 b/usr.bin/top/top.1
index ec14e08a5618..5a7c5da8803b 100644
--- a/usr.bin/top/top.1
+++ b/usr.bin/top/top.1
@@ -15,6 +15,11 @@ top \- display and update information about the top cpu processes
.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 in lower case:
\*(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 .
@@ -320,6 +329,10 @@ 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
.BR k ill
diff --git a/usr.bin/top/top.c b/usr.bin/top/top.c
index d44dd9898810..b4f9bec5d7ae 100644
--- a/usr.bin/top/top.c
+++ b/usr.bin/top/top.c
@@ -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,6 +375,19 @@ 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;
@@ -1117,6 +1135,36 @@ restart:
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!");
putchar('\r');
diff --git a/usr.bin/top/top.h b/usr.bin/top/top.h
index c62580176396..03ae008356bc 100644
--- a/usr.bin/top/top.h
+++ b/usr.bin/top/top.h
@@ -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 };
/*
diff --git a/usr.bin/top/utils.c b/usr.bin/top/utils.c
index b0e9103f7dbe..f9cf340444e4 100644
--- a/usr.bin/top/utils.c
+++ b/usr.bin/top/utils.c
@@ -15,9 +15,18 @@
#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)
@@ -417,3 +426,31 @@ format_k2(unsigned long long amt)
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;
+}
diff --git a/usr.bin/top/utils.h b/usr.bin/top/utils.h
index 9e5daa7bba4b..2125f82e901e 100644
--- a/usr.bin/top/utils.h
+++ b/usr.bin/top/utils.h
@@ -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);