Преглед на файлове

ps: Add `-u` option, to list processes associated with specified users

Sam Atkins преди 2 години
родител
ревизия
be71ccb690
променени са 2 файла, в които са добавени 19 реда и са изтрити 1 реда
  1. 2 1
      Base/usr/share/man/man1/ps.md
  2. 17 0
      Userland/Utilities/ps.cpp

+ 2 - 1
Base/usr/share/man/man1/ps.md

@@ -5,7 +5,7 @@ ps - list currently running processes
 ## Synopsis
 
 ```**sh
-$ ps [--version] [-a] [-A] [-e] [-f] [-p pid-list] [-q pid-list]
+$ ps [--version] [-a] [-A] [-e] [-f] [-p pid-list] [-q pid-list] [-u user-list]
 ```
 
 ## Description
@@ -20,6 +20,7 @@ For each process, print its PID (process ID), to which TTY it belongs, and invok
 * `-f`: Also print for each process: UID (as resolved username), PPID (parent PID), and STATE (Runnable, Sleeping, Selecting, Reading, etc.)
 * `-p pid-list`: Only consider the given PIDs, if they exist. `pid-list` is a list of PIDs, separated by commas or spaces.
 * `-q pid-list`: Only consider the given PIDs, if they exist. Output the processes in the order provided by `pid-list`. `pid-list` is a list of PIDs, separated by commas or spaces.
+* `-u user-list`: Only consider processes for the given users, if they exist. `user-list` is a list of UIDs or login names, separated by commas or spaces.
 
 ## Examples
 

+ 17 - 0
Userland/Utilities/ps.cpp

@@ -7,6 +7,7 @@
 
 #include <AK/QuickSort.h>
 #include <AK/String.h>
+#include <LibCore/Account.h>
 #include <LibCore/ArgsParser.h>
 #include <LibCore/ProcessStatisticsReader.h>
 #include <LibCore/System.h>
@@ -61,6 +62,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
     TRY(Core::System::pledge("stdio rpath"));
     TRY(Core::System::unveil("/sys/kernel/processes", "r"));
     TRY(Core::System::unveil("/etc/passwd", "r"));
+    TRY(Core::System::unveil("/etc/group", "r"));
     TRY(Core::System::unveil(nullptr, nullptr));
 
     enum class Alignment {
@@ -81,6 +83,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
     bool provided_pid_list = false;
     bool provided_quick_pid_list = false;
     Vector<pid_t> pid_list;
+    Vector<uid_t> uid_list;
 
     Core::ArgsParser args_parser;
     args_parser.add_option(every_terminal_process_flag, "Show every process associated with terminals", nullptr, 'a');
@@ -101,6 +104,18 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
             warnln("Could not parse '{}' as a PID.", pid_string);
         return pid;
     }));
+    args_parser.add_option(make_list_option(uid_list, "Show processes with a matching user ID or login name. (Comma- or space-separated list.)", nullptr, 'u', "user-list", [&](StringView user_string) -> Optional<uid_t> {
+        if (auto uid = user_string.to_uint<uid_t>(); uid.has_value()) {
+            return uid.value();
+        }
+
+        auto maybe_account = Core::Account::from_name(user_string, Core::Account::Read::PasswdOnly);
+        if (maybe_account.is_error()) {
+            warnln("Could not find user '{}': {}", user_string, maybe_account.error());
+            return {};
+        }
+        return maybe_account.value().uid();
+    }));
     args_parser.parse(arguments);
 
     if (provided_pid_list && provided_quick_pid_list) {
@@ -148,6 +163,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
     // Filter
     if (!pid_list.is_empty()) {
         processes.remove_all_matching([&](auto& process) { return !pid_list.contains_slow(process.pid); });
+    } else if (!uid_list.is_empty()) {
+        processes.remove_all_matching([&](auto& process) { return !uid_list.contains_slow(process.uid); });
     } else if (every_terminal_process_flag) {
         processes.remove_all_matching([&](auto& process) { return process.tty.is_empty(); });
     } else if (!every_process_flag) {