Serenity Operating System
at master 68 lines 2.0 kB view raw
1/* 2 * Copyright (c) 2022, Maxwell Trussell <maxtrussell@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Format.h> 8#include <AK/Vector.h> 9#include <LibCore/ArgsParser.h> 10#include <LibCore/ProcessStatisticsReader.h> 11#include <LibCore/System.h> 12#include <LibMain/Main.h> 13#include <LibRegex/Regex.h> 14#include <LibRegex/RegexOptions.h> 15#include <signal.h> 16#include <sys/types.h> 17 18ErrorOr<int> serenity_main(Main::Arguments args) 19{ 20 TRY(Core::System::pledge("stdio proc rpath")); 21 TRY(Core::System::unveil("/sys/kernel/processes", "r")); 22 TRY(Core::System::unveil("/etc/passwd", "r")); 23 TRY(Core::System::unveil(nullptr, nullptr)); 24 25 bool case_insensitive = false; 26 bool echo = false; 27 StringView pattern; 28 int signal = SIGTERM; 29 30 Core::ArgsParser args_parser; 31 args_parser.add_option(case_insensitive, "Make matches case-insensitive", nullptr, 'i'); 32 args_parser.add_option(echo, "Display what is killed", "echo", 'e'); 33 args_parser.add_option(signal, "Signal number to send", "signal", 's', "number"); 34 args_parser.add_positional_argument(pattern, "Process name to search for", "process-name"); 35 args_parser.parse(args); 36 37 auto all_processes = TRY(Core::ProcessStatisticsReader::get_all()); 38 39 PosixOptions options {}; 40 if (case_insensitive) { 41 options |= PosixFlags::Insensitive; 42 } 43 44 Regex<PosixExtended> re(pattern, options); 45 if (re.parser_result.error != regex::Error::NoError) { 46 return 1; 47 } 48 49 Vector<Core::ProcessStatistics> matched_processes; 50 for (auto& process : all_processes.processes) { 51 auto result = re.match(process.name, PosixFlags::Global); 52 if (result.success) { 53 matched_processes.append(process); 54 } 55 } 56 57 if (matched_processes.is_empty()) { 58 return 1; 59 } 60 61 for (auto& process : matched_processes) { 62 if (echo) { 63 outln("{} killed (pid {})", process.name, process.pid); 64 } 65 kill(process.pid, signal); 66 } 67 return 0; 68}