diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 184001dfec..58ebf8795c 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -3,7 +3,7 @@ list(APPEND SPECIAL_TARGETS test install) list(APPEND REQUIRED_TARGETS arp base64 basename cat chmod chown chroot clear cp cut date dd df dirname dmesg du echo env expr false fgrep file find grep groups head host hostname id ifconfig kill killall ln ls mkdir mount mv nproc - pidof ping pmap ps readlink realpath reboot rm rmdir seq shutdown sleep sort stat stty su tail test + pgrep pidof ping pmap ps readlink realpath reboot rm rmdir seq shutdown sleep sort stat stty su tail test touch tr true umount uname uniq uptime w wc which whoami xargs yes ) list(APPEND RECOMMENDED_TARGETS @@ -80,6 +80,7 @@ target_link_libraries(open LibDesktop) target_link_libraries(pape LibGUI) target_link_libraries(passwd LibCrypt) target_link_libraries(paste LibGUI) +target_link_libraries(pgrep LibRegex) target_link_libraries(pls LibCrypt) target_link_libraries(pro LibProtocol) target_link_libraries(run-tests LibRegex) diff --git a/Userland/Utilities/pgrep.cpp b/Userland/Utilities/pgrep.cpp new file mode 100644 index 0000000000..abfdfa3884 --- /dev/null +++ b/Userland/Utilities/pgrep.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021, Aziz Berkay Yesilyurt + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + if (pledge("stdio rpath", nullptr) < 0) { + perror("pledge"); + return 1; + } + + bool case_insensitive = false; + bool invert_match = false; + char const* pattern = nullptr; + + Core::ArgsParser args_parser; + args_parser.add_option(case_insensitive, "Make matches case-insensitive", nullptr, 'i'); + args_parser.add_option(invert_match, "Select non-matching lines", "invert-match", 'v'); + args_parser.add_positional_argument(pattern, "Process name to search for", "process-name"); + args_parser.parse(argc, argv); + + PosixOptions options {}; + if (case_insensitive) + options |= PosixFlags::Insensitive; + + Regex re(pattern, options); + if (re.parser_result.error != Error::NoError) { + return 1; + } + + auto processes = Core::ProcessStatisticsReader::get_all(); + if (!processes.has_value()) + return 1; + + Vector matches; + for (auto& it : processes.value()) { + auto result = re.match(it.name, PosixFlags::Global); + if (result.success ^ invert_match) { + matches.append(it.pid); + } + } + + quick_sort(matches); + + for (auto& match : matches) { + outln("{}", match); + } + + return 0; +}