pkill.cpp 2.1 KB

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