Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2022, Zachary Penn <zack@sysdevs.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <AK/DeprecatedString.h>
9#include <LibCore/ProcessStatisticsReader.h>
10#include <LibCore/System.h>
11#include <LibMain/Main.h>
12#include <ctype.h>
13#include <signal.h>
14#include <stdlib.h>
15
16static void print_usage_and_exit()
17{
18 warnln("usage: killall [-signal] process_name");
19 exit(1);
20}
21
22static ErrorOr<int> kill_all(DeprecatedString const& process_name, unsigned const signum)
23{
24 auto all_processes = TRY(Core::ProcessStatisticsReader::get_all());
25
26 for (auto& process : all_processes.processes) {
27 if (process.name == process_name) {
28 TRY(Core::System::kill(process.pid, signum));
29 }
30 }
31
32 return 0;
33}
34
35ErrorOr<int> serenity_main(Main::Arguments arguments)
36{
37 unsigned signum = SIGTERM;
38 int name_argi = 1;
39
40 if (arguments.argc != 2 && arguments.argc != 3)
41 print_usage_and_exit();
42
43 if (arguments.argc == 3) {
44 name_argi = 2;
45
46 if (arguments.argv[1][0] != '-')
47 print_usage_and_exit();
48
49 Optional<unsigned> number;
50
51 if (isalpha(arguments.argv[1][1])) {
52 int value = getsignalbyname(&arguments.argv[1][1]);
53 if (value >= 0 && value < NSIG)
54 number = value;
55 }
56
57 if (!number.has_value())
58 number = DeprecatedString(&arguments.argv[1][1]).to_uint();
59
60 if (!number.has_value()) {
61 warnln("'{}' is not a valid signal name or number", &arguments.argv[1][1]);
62 return 2;
63 }
64 signum = number.value();
65 }
66
67 return kill_all(arguments.strings[name_argi], signum);
68}