From 0a280740716bde571c0f0db64d78a7f2141b56f4 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@tele2.at>
Date: Sun, 25 Mar 2018 12:50:40 +0200
Subject: Add System V init like killall5 helper program

Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
---
 .gitignore        |   1 +
 Makefile.am       |   3 ++
 cmd/Makemodule.am |   6 ++++
 cmd/killall5.c    | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 112 insertions(+)
 create mode 100644 cmd/killall5.c

diff --git a/.gitignore b/.gitignore
index 3124259..2f392f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ init
 service
 reboot
 shutdown
+killall5
 
 services/agetty
 services/hostname
diff --git a/Makefile.am b/Makefile.am
index b1152ed..d0e888e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,6 +7,9 @@ sbin_PROGRAMS =
 noinst_LIBRARIES =
 EXTRA_DIST = README LICENSE
 
+helperdir = @SCRIPTDIR@
+helper_PROGRAMS =
+
 include lib/Makemodule.am
 include cmd/Makemodule.am
 include initd/Makemodule.am
diff --git a/cmd/Makemodule.am b/cmd/Makemodule.am
index d26b93b..40c0933 100644
--- a/cmd/Makemodule.am
+++ b/cmd/Makemodule.am
@@ -10,4 +10,10 @@ reboot_CFLAGS = $(AM_CFLAGS)
 reboot_LDFLAGS = $(AM_LDFLAGS)
 reboot_LDADD = libinit.a
 
+killall5_SOURCES = cmd/killall5.c
+killall5_CPPFLAGS = $(AM_CPPFLAGS)
+killall5_CFLAGS = $(AM_CFLAGS)
+killall5_LDFLAGS = $(AM_LDFLAGS)
+
 sbin_PROGRAMS += reboot shutdown
+helper_PROGRAMS += killall5
diff --git a/cmd/killall5.c b/cmd/killall5.c
new file mode 100644
index 0000000..9453d33
--- /dev/null
+++ b/cmd/killall5.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * Copyright (C) 2018 - David Oberhollenzer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include <sys/types.h>
+#include <dirent.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "util.h"
+
+static NORETURN void usage_and_exit(void)
+{
+	fputs("Usage: killall5 SIGNAL\n", stderr);
+	exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+	int signo, ret = EXIT_SUCCESS;
+	pid_t pid, mypid, mysid;
+	struct dirent *ent;
+	const char *ptr;
+	DIR *dir;
+
+	if (argc != 2)
+		usage_and_exit();
+
+	ptr = argv[1];
+	if (*ptr == '-')
+		++ptr;
+
+	if (!isdigit(*ptr))
+		usage_and_exit();
+
+	for (signo = 0; isdigit(*ptr); ++ptr)
+		signo = signo * 10 + ((*ptr) - '0');
+
+	if (*ptr != '\0' || signo < 1 || signo > 31)
+		usage_and_exit();
+
+	kill(-1, SIGSTOP);
+
+	dir = opendir("/proc");
+	if (dir == NULL) {
+		perror("opendir /proc");
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+
+	mypid = getpid();
+	mysid = getsid(0);
+
+	for (;;) {
+		errno = 0;
+		ent = readdir(dir);
+
+		if (ent == NULL) {
+			if (errno) {
+				perror("readdir");
+				ret = EXIT_FAILURE;
+			}
+			break;
+		}
+
+		if (!isdigit(ent->d_name[0]))
+			continue;
+
+		for (pid = 0, ptr = ent->d_name; isdigit(*ptr); ++ptr)
+			pid = pid * 10 + ((*ptr) - '0');
+
+		if (*ptr != '\0' || pid == mypid || getsid(pid) == mysid)
+			continue;
+
+		if (kill(pid, signo)) {
+			ret = EXIT_FAILURE;
+			fprintf(stderr, "kill %d: %s\n",
+					(int)pid, strerror(errno));
+		}
+	}
+out:
+	kill(-1, SIGCONT);
+	return ret;
+}
-- 
cgit v1.2.3