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;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to