diff --git a/Base/usr/share/man/man1/ps.md b/Base/usr/share/man/man1/ps.md index 4454964522..ef3b857f54 100644 --- a/Base/usr/share/man/man1/ps.md +++ b/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 diff --git a/Userland/Utilities/ps.cpp b/Userland/Utilities/ps.cpp index 4356c9b163..c76b06fea8 100644 --- a/Userland/Utilities/ps.cpp +++ b/Userland/Utilities/ps.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,7 @@ ErrorOr 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 serenity_main(Main::Arguments arguments) bool provided_pid_list = false; bool provided_quick_pid_list = false; Vector pid_list; + Vector 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 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 { + if (auto uid = user_string.to_uint(); 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 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) {