summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/killall.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/Userland/killall.cpp b/Userland/killall.cpp
new file mode 100644
index 0000000000..cd28a6a56b
--- /dev/null
+++ b/Userland/killall.cpp
@@ -0,0 +1,76 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <LibCore/CFile.h>
+#include <AK/AKString.h>
+
+static void print_usage_and_exit()
+{
+ printf("usage: killall [-signal] process_name\n");
+ exit(1);
+}
+
+static int kill_all(const String& process_name, const unsigned signum)
+{
+ CFile file("/proc/all");
+ if (!file.open(CIODevice::ReadOnly)) {
+ fprintf(stderr, "killall failed to open /proc/all\n");
+ return 3;
+ }
+
+ for (;;) {
+ auto line = file.read_line(1024);
+
+ if (line.is_empty())
+ break;
+
+ auto chomped = String((const char*)line.pointer(), line.size() - 1, Chomp);
+ auto parts = chomped.split_view(',');
+
+ if (parts.size() < 18)
+ break;
+
+ bool ok = false;
+ pid_t pid = parts[0].to_uint(ok);
+ String name = parts[11];
+
+ if (!ok) {
+ fprintf(stderr, "killall failed : couldn't convert %s to a valid pid\n", parts[0].characters());
+ return 4;
+ }
+
+ if (name == process_name) {
+ int ret = kill(pid, signum);
+ if (ret < 0)
+ perror("kill");
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ bool ok;
+ unsigned signum = SIGTERM;
+ int name_argi = 1;
+
+ if (argc != 2 && argc != 3)
+ print_usage_and_exit();
+
+ if (argc == 3) {
+ name_argi = 2;
+
+ if (argv[1][0] != '-')
+ print_usage_and_exit();
+
+ signum = String(&argv[1][1]).to_uint(ok);
+ if (!ok) {
+ printf("'%s' is not a valid signal number\n", &argv[1][1]);
+ return 2;
+ }
+ }
+
+ return kill_all(argv[name_argi], signum);
+}