pkill.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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 = TRY(Core::ProcessStatisticsReader::get_all());
  33. PosixOptions options {};
  34. if (case_insensitive) {
  35. options |= PosixFlags::Insensitive;
  36. }
  37. Regex<PosixExtended> re(pattern, options);
  38. if (re.parser_result.error != regex::Error::NoError) {
  39. return 1;
  40. }
  41. Vector<Core::ProcessStatistics> matched_processes;
  42. for (auto& process : all_processes.processes) {
  43. auto result = re.match(process.name, PosixFlags::Global);
  44. if (result.success) {
  45. matched_processes.append(process);
  46. }
  47. }
  48. if (matched_processes.is_empty()) {
  49. return 1;
  50. }
  51. for (auto& process : matched_processes) {
  52. if (echo) {
  53. outln("{} killed (pid {})", process.name, process.pid);
  54. }
  55. kill(process.pid, signal);
  56. }
  57. return 0;
  58. }