From 0389ef128a0e60d4ef747b845710d0430b27bf2e Mon Sep 17 00:00:00 2001
From: irevoire <irevoire@hotmail.fr>
Date: Tue, 21 Jan 2020 17:09:28 +0100
Subject: [PATCH 1/2] implement the signal command

---
 main/gridinit.c     | 100 ++++++++++++++++++++++++++++++++++++++++++++
 main/gridinit_cmd.c |  13 ++++++
 2 files changed, 113 insertions(+)

diff --git a/main/gridinit.c b/main/gridinit.c
index 58478e9..9b3deee 100644
--- a/main/gridinit.c
+++ b/main/gridinit.c
@@ -321,6 +321,105 @@ command_stop(GString *out, int argc, char **argv)
 	return service_run_groupv(argc, argv, out, stop_process);
 }
 
+static void
+command_signal(GString *out, int argc, char **argv)
+{
+	char *str_signal;
+	int signal;
+
+	static struct signal_mapping_s {
+		char *name;
+		int value;
+	} SIGNAL [] = {
+#ifdef __unix__ // the base signals
+		{ "SIGABRT",	SIGABRT},
+		{ "SIGALRM",	SIGALRM },
+		{ "SIGBUS",	SIGBUS },
+		{ "SIGCHLD",	SIGCHLD },
+		{ "SIGCONT",	SIGCONT },
+		{ "SIGEMT",	SIGEMT },
+		{ "SIGFPE",	SIGFPE },
+		{ "SIGHUP",	SIGHUP },
+		{ "SIGILL",	SIGILL },
+		{ "SIGINFO",	SIGINFO },
+		{ "SIGINT",	SIGINT },
+		{ "SIGIO",	SIGIO },
+		{ "SIGKILL",	SIGKILL },
+		{ "SIGPIPE",	SIGPIPE },
+		{ "SIGPROF",	SIGPROF },
+		{ "SIGQUIT",	SIGQUIT },
+		{ "SIGSEGV",	SIGSEGV },
+		{ "SIGSTOP",	SIGSTOP },
+		{ "SIGSYS",	SIGSYS },
+		{ "SIGTERM",	SIGTERM },
+		{ "SIGTRAP",	SIGTRAP },
+		{ "SIGTSTP",	SIGTSTP },
+		{ "SIGTTIN",	SIGTTIN },
+		{ "SIGTTOU",	SIGTTOU },
+		{ "SIGURG",	SIGURG },
+		{ "SIGUSR1",	SIGUSR1 },
+		{ "SIGUSR2",	SIGUSR2 },
+		{ "SIGVTALRM",	SIGVTALRM },
+		{ "SIGWINCH",	SIGWINCH },
+		{ "SIGXCPU",	SIGXCPU },
+		{ "SIGXFSZ",	SIGXFSZ },
+#else
+#error Your plateform is not supported
+#endif
+
+#ifdef __FreeBSD__ // freebsd specific signals
+		{ "SIGTHR",	SIGTHR },
+		{ "SIGLIBRT",	SIGLIBRT },
+#endif
+#ifdef __linux__ // linux specific signals
+		{ "SIGCLD",	SIGCLD },
+		{ "SIGIOT",	SIGIOT },
+		{ "SIGLOST",	SIGLOST },
+		{ "SIGPOLL",	SIGPOLL },
+		{ "SIGPWR",	SIGPWR },
+		{ "SIGSTKFLT",	SIGSTKFLT },
+		{ "SIGUNUSED",	SIGUNUSED },
+		{ NULL, 0 },
+#endif
+	};
+
+	errno = 0; // this should not be needed
+
+	if( argc <= 0) {
+		g_string_append_printf(out, "No signal were specified\n");
+		return; // nothing to do
+	}
+
+	str_signal = argv[0];
+	argv++;
+	argc--;
+	g_string_append_printf(out, "START signal\n");
+
+	// first we try to convert the string to an integer
+	signal = strtol(str_signal, NULL, 10); // TODO should we autodetect the base?
+	if (errno != 0) { // conversion failed
+		errno = 0;
+		// we look into the of known signals
+		for (struct signal_mapping_s* s = SIGNAL;; s++) {
+			if (s->name == NULL) { // we did not find any signals
+				g_string_append_printf(out, "Unable to decode the signal %s\n", str_signal);
+				return;
+			}
+			if (0 == strcasecmp(str_signal, s->name)) {
+				signal = s->value;
+				break;
+			}
+		}
+	}
+
+	void signal_process(void *u UNUSED, struct child_info_s *ci) {
+		kill(ci->pid, signal);
+	}
+
+	g_assert_nonnull(out);
+	return service_run_groupv(argc, argv, out, signal_process);
+}
+
 static void
 command_restart(GString *out, int argc, char **argv)
 {
@@ -427,6 +526,7 @@ __resolve_command(const gchar *n)
 		{"repair",  command_repair },
 		{"start",   command_start },
 		{"stop",    command_stop },
+		{"signal",  command_signal },
 		{"restart", command_restart },
 		{"reload",  command_reload },
 		{NULL,      NULL}
diff --git a/main/gridinit_cmd.c b/main/gridinit_cmd.c
index a0e2c97..a25d3e6 100644
--- a/main/gridinit_cmd.c
+++ b/main/gridinit_cmd.c
@@ -141,6 +141,7 @@ static const gchar description[] =
 	"  kill    : Stops the given processes or groups, they won't be automatically\n"
 	"            restarted even after a configuration reload\n"
 	"  stop    : Calls 'kill' until the children exit\n"
+	"  signal  : Send a choosen signal to the given processes or groups\n"
 	"  restart : Restarts the given processes or groups\n"
 	"  reload  : Reloads the configuration, stopping obsolete processes, starting\n"
 	"            the newly discovered. Broken or stopped processes are not restarted\n"
@@ -630,6 +631,17 @@ command_kill(int argc, char **args)
 		|| dump_args.count_success == 0;
 }
 
+static int
+command_signal(int argc, char **args)
+{
+	struct dump_as_is_arg_s dump_args = {};
+
+	int rc = send_commandv(dump_as_is, &dump_args, "signal", argc, args);
+	return rc
+		|| dump_args.count_errors != 0
+		|| dump_args.count_success == 0;
+}
+
 static gboolean
 _all_down(char **args, gboolean *down)
 {
@@ -713,6 +725,7 @@ struct command_s {
 	{ "status3", command_status2 },
 	{ "start",   command_start },
 	{ "stop",    command_stop },
+	{ "signal",  command_signal },
 	{ "kill",    command_kill },
 	{ "restart", command_restart },
 	{ "reload",  command_reload },

From a5ccd6339b3a89d7f252479a3bbd8bc0b3a571ea Mon Sep 17 00:00:00 2001
From: irevoire <irevoire@hotmail.fr>
Date: Tue, 21 Jan 2020 17:47:35 +0100
Subject: [PATCH 2/2] remove the useless print

---
 main/gridinit.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/main/gridinit.c b/main/gridinit.c
index 9b3deee..0d2f473 100644
--- a/main/gridinit.c
+++ b/main/gridinit.c
@@ -393,7 +393,6 @@ command_signal(GString *out, int argc, char **argv)
 	str_signal = argv[0];
 	argv++;
 	argc--;
-	g_string_append_printf(out, "START signal\n");
 
 	// first we try to convert the string to an integer
 	signal = strtol(str_signal, NULL, 10); // TODO should we autodetect the base?