From 4cf60b74916ef69ee98ce6fc47447f8d473b456d Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Fri, 29 Jul 2016 18:05:07 +0200 Subject: [PATCH] initctl: Add SysV compat support for setenv - Fix compat INIT_CMD_ defines so Finit clients can talk to SysV init - Add setenv support, only for INIT_HALT={POWERDOWN,HALT} to runlevel 6 Signed-off-by: Joachim Nilsson --- finit.h | 35 ++++++++++++++++++++++---------- plugins/initctl.c | 51 ++++++++++++++++++++++++++++++++++++++++++----- sig.h | 5 +++++ 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/finit.h b/finit.h index 867a7a5e..f81bcff0 100644 --- a/finit.h +++ b/finit.h @@ -39,20 +39,33 @@ #define LINE_SIZE 1024 #define BUF_SIZE 4096 -/* We reuse the INIT_CMD_ for the new initctl tool, but telinit only - * supports changing runlevel and reloading the configuration. */ +/* + * We extend the INIT_CMD_ range for the new initctl tool, Finit only + * support changing runlevel, reloading the configuration and setenv + * with the old-style /dev/initctl FIFO. + */ #define INIT_SOCKET _PATH_VARRUN "finit.sock" #define INIT_MAGIC 0x03091969 + +#define INIT_CMD_START 0 #define INIT_CMD_RUNLVL 1 -#define INIT_CMD_DEBUG 2 /* Toggle Finit debug */ -#define INIT_CMD_RELOAD 3 /* Reload *.conf in /etc/finit.d/ */ -#define INIT_CMD_START_SVC 4 -#define INIT_CMD_STOP_SVC 5 -#define INIT_CMD_RELOAD_SVC 6 /* SIGHUP service */ -#define INIT_CMD_RESTART_SVC 7 /* STOP + START service */ -#define INIT_CMD_QUERY_INETD 8 -#define INIT_CMD_EMIT 9 -#define INIT_CMD_GET_RUNLEVEL 10 +#define INIT_CMD_POWERFAIL 2 +#define INIT_CMD_POWERFAILNOW 3 +#define INIT_CMD_POWEROK 4 +#define INIT_CMD_BSD 5 +#define INIT_CMD_SETENV 6 +#define INIT_CMD_UNSETENV 7 + +/* Finit extensions over std SysV */ +#define INIT_CMD_DEBUG 8 /* Toggle Finit debug */ +#define INIT_CMD_RELOAD 9 /* Reload *.conf in /etc/finit.d/ */ +#define INIT_CMD_START_SVC 10 +#define INIT_CMD_STOP_SVC 11 +#define INIT_CMD_RELOAD_SVC 12 /* SIGHUP service */ +#define INIT_CMD_RESTART_SVC 13 /* STOP + START service */ +#define INIT_CMD_QUERY_INETD 14 +#define INIT_CMD_EMIT 15 +#define INIT_CMD_GET_RUNLEVEL 16 #define INIT_CMD_NACK 254 #define INIT_CMD_ACK 255 diff --git a/plugins/initctl.c b/plugins/initctl.c index b275b3c5..f61fe615 100644 --- a/plugins/initctl.c +++ b/plugins/initctl.c @@ -39,6 +39,14 @@ #include "../sig.h" #include "../service.h" +/* + * Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT", + * "=POWERDOWN", or "" to cancel shutdown, before requesting change to + * runlevel 6 over the /dev/initctl FIFO. + */ +shutop_t halt = SHUT_DEFAULT; + + static void parse(void *arg, int fd, int events); static plugin_t plugin = { @@ -58,7 +66,36 @@ static void fifo_open(void) } } -/* Standard reboot/shutdown utilities talk to init using /dev/initctl. +/* + * We only handle INIT_HALT for differentiating between halt/poweroff + */ +static void set_env(char *data) +{ + const char *var = "INIT_HALT"; + + if (strncmp(data, var, strlen(var))) + return; + data += strlen(var); + + /* + * No value means unset env, in this case cancel shutdown. + */ + if (data[0] == 0) { + halt = SHUT_DEFAULT; + /* XXX: Cancel timer here, when we get support for timed shutdown */ + return; + } + + if (string_match(data, "=POWERDOWN")) + halt = SHUT_OFF; + if (string_match(data, "=HALT")) + halt = SHUT_HALT; + + /* Now we wait for runlevel change, or cancelled shutdown */ +} + +/* + * Standard reboot/shutdown utilities talk to init using /dev/initctl. * We should check if the fifo was recreated and reopen it. */ static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) @@ -92,8 +129,8 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) case INIT_CMD_RUNLVL: switch (rq.runlevel) { case '0': - _d("Halting system (SIGUSR2)"); - do_shutdown(SIGUSR2); + _d("Halting system (SIGUSR1 or SIGUSR2)"); + do_shutdown(halt); break; case 's': @@ -109,8 +146,8 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) break; case '6': - _d("Rebooting system (SIGUSR1)"); - do_shutdown(SIGUSR1); + _d("Rebooting system (SIGTERM)"); + do_shutdown(SHUT_REBOOT); break; default: @@ -123,6 +160,10 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) service_reload_dynamic(); break; + case INIT_CMD_SETENV: + set_env(rq.data); + break; + default: _d("Unsupported cmd: %d", rq.cmd); break; diff --git a/sig.h b/sig.h index 5d0160da..c16c21c1 100644 --- a/sig.h +++ b/sig.h @@ -55,6 +55,11 @@ sigaction(sig, &sa, NULL); \ } while (0) +/* + * For old-style /dev/initctl shutdown we default to halt + */ +#define SHUT_DEFAULT SHUT_HALT + typedef enum { SHUT_OFF, SHUT_HALT,