From owner-svn-src-all@freebsd.org Sat Jun 2 15:52:20 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B83ADF79A75; Sat, 2 Jun 2018 15:52:20 +0000 (UTC) (envelope-from novel@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 69A5A68BA4; Sat, 2 Jun 2018 15:52:20 +0000 (UTC) (envelope-from novel@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4B4FB11DF0; Sat, 2 Jun 2018 15:52:20 +0000 (UTC) (envelope-from novel@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w52FqK7q031317; Sat, 2 Jun 2018 15:52:20 GMT (envelope-from novel@FreeBSD.org) Received: (from novel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w52FqIaU031309; Sat, 2 Jun 2018 15:52:18 GMT (envelope-from novel@FreeBSD.org) Message-Id: <201806021552.w52FqIaU031309@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: novel set sender to novel@FreeBSD.org using -f From: Roman Bogorodskiy Date: Sat, 2 Jun 2018 15:52:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334531 - head/usr.bin/top X-SVN-Group: head X-SVN-Commit-Author: novel X-SVN-Commit-Paths: head/usr.bin/top X-SVN-Commit-Revision: 334531 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Jun 2018 15:52:21 -0000 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 +#include +#include + #include #include #include +#include +#include +#include +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 + 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);