From owner-svn-src-head@freebsd.org Mon Aug 7 08:45:10 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2065EDC4524; Mon, 7 Aug 2017 08:45:10 +0000 (UTC) (envelope-from gahr@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 mx1.freebsd.org (Postfix) with ESMTPS id EF11716E3; Mon, 7 Aug 2017 08:45:09 +0000 (UTC) (envelope-from gahr@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v778j9V7092671; Mon, 7 Aug 2017 08:45:09 GMT (envelope-from gahr@FreeBSD.org) Received: (from gahr@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v778j8gS092667; Mon, 7 Aug 2017 08:45:08 GMT (envelope-from gahr@FreeBSD.org) Message-Id: <201708070845.v778j8gS092667@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gahr set sender to gahr@FreeBSD.org using -f From: Pietro Cerutti Date: Mon, 7 Aug 2017 08:45:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r322139 - in head: contrib/top usr.bin/top X-SVN-Group: head X-SVN-Commit-Author: gahr X-SVN-Commit-Paths: in head: contrib/top usr.bin/top X-SVN-Commit-Revision: 322139 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Aug 2017 08:45:10 -0000 Author: gahr (ports committer) Date: Mon Aug 7 08:45:08 2017 New Revision: 322139 URL: https://svnweb.freebsd.org/changeset/base/322139 Log: Enhance top(1) to filter on multiple usernames Reviewed by: cognet, bapt Approved by: cognet MFC after: 1 week Relnotes: yes Differential Revision: https://reviews.freebsd.org/D11840 Modified: head/contrib/top/machine.h head/contrib/top/top.c head/contrib/top/top.xs head/usr.bin/top/machine.c Modified: head/contrib/top/machine.h ============================================================================== --- head/contrib/top/machine.h Mon Aug 7 07:40:00 2017 (r322138) +++ head/contrib/top/machine.h Mon Aug 7 08:45:08 2017 (r322139) @@ -70,7 +70,8 @@ struct process_select int self; /* show self */ int system; /* show system processes */ int thread; /* show threads */ - int uid; /* only this uid (unless uid == -1) */ +#define TOP_MAX_UIDS 8 + int uid[TOP_MAX_UIDS]; /* only these uids (unless uid[0] == -1) */ int wcpu; /* show weighted cpu */ int jid; /* only this jid (unless jid == -1) */ int jail; /* show jail ID */ Modified: head/contrib/top/top.c ============================================================================== --- head/contrib/top/top.c Mon Aug 7 07:40:00 2017 (r322138) +++ head/contrib/top/top.c Mon Aug 7 08:45:08 2017 (r322139) @@ -134,7 +134,110 @@ void (*d_process)(int line, char *thisline) = i_proces void reset_display(void); +static void +reset_uids() +{ + for (size_t i = 0; i < TOP_MAX_UIDS; ++i) + ps.uid[i] = -1; +} +static int +add_uid(int uid) +{ + size_t i = 0; + + /* Add the uid if there's room */ + for (; i < TOP_MAX_UIDS; ++i) + { + if (ps.uid[i] == -1 || ps.uid[i] == uid) + { + ps.uid[i] = uid; + break; + } + } + + return (i == TOP_MAX_UIDS); +} + +static void +rem_uid(int uid) +{ + size_t i = 0; + size_t where = TOP_MAX_UIDS; + + /* Look for the user to remove - no problem if it's not there */ + for (; i < TOP_MAX_UIDS; ++i) + { + if (ps.uid[i] == -1) + break; + if (ps.uid[i] == uid) + where = i; + } + + /* Make sure we don't leave a hole in the middle */ + if (where != TOP_MAX_UIDS) + { + ps.uid[where] = ps.uid[i-1]; + ps.uid[i-1] = -1; + } +} + +static int +handle_user(char *buf, size_t buflen) +{ + int rc = 0; + int uid = -1; + char *buf2 = buf; + + new_message(MT_standout, "Username to show (+ for all): "); + if (readline(buf, buflen, No) <= 0) + { + clear_message(); + return rc; + } + + if (buf[0] == '+' || buf[0] == '-') + { + if (buf[1] == '\0') + { + reset_uids(); + goto end; + } + else + ++buf2; + } + + if ((uid = userid(buf2)) == -1) + { + new_message(MT_standout, " %s: unknown user", buf2); + rc = 1; + goto end; + } + + if (buf2 == buf) + { + reset_uids(); + ps.uid[0] = uid; + goto end; + } + + if (buf[0] == '+') + { + if (add_uid(uid)) + { + new_message(MT_standout, " too many users, reset with '+'"); + rc = 1; + goto end; + } + } + else + rem_uid(uid); + +end: + putchar('\r'); + return rc; +} + int main(argc, argv) @@ -252,7 +355,7 @@ char *argv[]; ps.idle = Yes; ps.self = -1; ps.system = No; - ps.uid = -1; + reset_uids(); ps.thread = No; ps.wcpu = 1; ps.jid = -1; @@ -299,7 +402,7 @@ char *argv[]; break; case 'U': /* display only username's processes */ - if ((ps.uid = userid(optarg)) == -1) + if ((ps.uid[0] = userid(optarg)) == -1) { fprintf(stderr, "%s: unknown user\n", optarg); exit(1); @@ -1004,31 +1107,8 @@ restart: break; case CMD_user: - new_message(MT_standout, - "Username to show (+ for all): "); - if (readline(tempbuf2, sizeof(tempbuf2), No) > 0) - { - if (tempbuf2[0] == '+' && - tempbuf2[1] == '\0') - { - ps.uid = -1; - } - else if ((i = userid(tempbuf2)) == -1) - { - new_message(MT_standout, - " %s: unknown user", tempbuf2); - no_command = Yes; - } - else - { - ps.uid = i; - } - putchar('\r'); - } - else - { - clear_message(); - } + if (handle_user(tempbuf2, sizeof(tempbuf2))) + no_command = Yes; break; case CMD_thrtog: Modified: head/contrib/top/top.xs ============================================================================== --- head/contrib/top/top.xs Mon Aug 7 07:40:00 2017 (r322138) +++ head/contrib/top/top.xs Mon Aug 7 08:45:08 2017 (r322139) @@ -307,9 +307,11 @@ This acts similarly to the command .IR renice (8)). .TP .B u -Display only processes owned by a specific username (prompt for username). -If the username specified is simply \*(lq+\*(rq, then processes belonging -to all users will be displayed. +Display only processes owned by a specific set of usernames (prompt for +username). If the username specified is simply \*(lq+\*(rq or \*(lq-\*(rq, +then processes belonging to all users will be displayed. Usernames can be added +to and removed from the set by prepending them with \*(lq+\*(rq and +\*(lq-\*(rq, respectively. .TP .B o Change the order in which the display is sorted. This command is not Modified: head/usr.bin/top/machine.c ============================================================================== --- head/usr.bin/top/machine.c Mon Aug 7 07:40:00 2017 (r322138) +++ head/usr.bin/top/machine.c Mon Aug 7 08:45:08 2017 (r322139) @@ -273,7 +273,19 @@ static const char *format_nice(const struct kinfo_proc static void getsysctl(const char *name, void *ptr, size_t len); static int swapmode(int *retavail, int *retfree); static void update_layout(void); +static int find_uid(uid_t needle, int *haystack); +static int +find_uid(uid_t needle, int *haystack) +{ + size_t i = 0; + + for (; i < TOP_MAX_UIDS; ++i) + if ((uid_t)haystack[i] == needle) + return 1; + return 0; +} + void toggle_pcpustats(void) { @@ -847,7 +859,7 @@ get_process_info(struct system_info *si, struct proces show_jid = sel->jid != -1; show_self = sel->self == -1; show_system = sel->system; - show_uid = sel->uid != -1; + show_uid = sel->uid[0] != -1; show_command = sel->command != NULL; show_kidle = sel->kidle; @@ -906,7 +918,7 @@ get_process_info(struct system_info *si, struct proces /* skip proc. that don't belong to the selected JID */ continue; - if (show_uid && pp->ki_ruid != (uid_t)sel->uid) + if (show_uid && !find_uid(pp->ki_ruid, sel->uid)) /* skip proc. that don't belong to the selected UID */ continue;