diff --git a/ChangeLog.md b/ChangeLog.md index 9201934e..dfac459e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -12,6 +12,11 @@ to service conditions. There are other significant changes as well, so make sure to read the whole changelog when upgrading. ### Changes +* The stand-alone `reboot` tool has been replaced with a symlink to + `initctl`, like its siblings: halt, shutdown, poweroff, and suspend. + Calling `reboot` & C:o now defaults to the corresponding `initctl cmd` + with a fallback to sending signals as per traditional SysV init. The + `-f` (force) flag remains, where `reboot(2)` is called directly * Introducing Finit progress 𝓜𝓸𝓭𝓮𝓻𝓷 * Removed built-in inetd super server. If you need this functionality, use an external inetd, like xinetd, instead. A pull request for a diff --git a/src/Makefile.am b/src/Makefile.am index fd84585d..491efa6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ else AM_LDFLAGS = -export-dynamic endif -sbin_PROGRAMS = finit initctl reboot +sbin_PROGRAMS = finit initctl pkglibexec_SCRIPTS = cgreaper.sh if WATCHDOGD pkglibexec_PROGRAMS = watchdogd @@ -49,19 +49,15 @@ else finit_LDADD += -ldl endif -initctl_SOURCES = initctl.c client.c client.h \ - serv.c serv.h svc.h \ +initctl_SOURCES = initctl.c client.c client.h \ + reboot.c serv.c serv.h svc.h \ cond.c cond.h util.c util.h initctl_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99 initctl_CFLAGS += $(lite_CFLAGS) initctl_LDADD = $(lite_LIBS) -reboot_SOURCES = reboot.c util.c util.h -reboot_CFLAGS = $(lite_CFLAGS) -reboot_LDADD = $(lite_LIBS) - INIT_LNKS = init -REBOOT_LNKS = shutdown halt poweroff suspend +REBOOT_LNKS = reboot shutdown halt poweroff suspend if WATCHDOGD watchdogd_SOURCES = watchdog.c watchdog.h @@ -72,46 +68,38 @@ endif # Hook in install to add finit and reboot symlink(s) install-exec-hook: @$(INSTALL_DATA) $(srcdir)/rescue.conf $(DESTDIR)$(pkglibdir) - @for file in $(INIT_LNKS); do \ - lnk=$(DESTDIR)$(sbindir)/$$file; \ - if [ -e $$lnk ]; then \ - echo "Skipping $$lnk exists."; \ - else \ - $(LN_S) finit $$lnk; \ - fi; \ + @for file in $(INIT_LNKS); do \ + lnk=$(DESTDIR)$(sbindir)/$$file; \ + if [ -e $$lnk ]; then \ + echo "Skipping $$lnk exists."; \ + else \ + $(LN_S) finit $$lnk; \ + fi; \ + done + @for file in $(REBOOT_LNKS); do \ + lnk=$(DESTDIR)$(sbindir)/$$file; \ + if [ -e $$lnk ]; then \ + echo "Skipping $$lnk exists."; \ + else \ + $(LN_S) initctl $$lnk; \ + fi; \ done - @if [ -L $(DESTDIR)$(sbindir)/reboot ]; then \ - echo "Non-finit reboot, skipping install."; \ - else \ - for file in $(REBOOT_LNKS); do \ - lnk=$(DESTDIR)$(sbindir)/$$file; \ - if [ -e $$lnk ]; then \ - echo "Skipping $$lnk exists."; \ - else \ - $(LN_S) reboot $$lnk; \ - fi; \ - done; \ - fi uninstall-hook: @$(RM) $(DESTDIR)$(pkglibdir)/rescue.conf - @for file in $(INIT_LNKS); do \ - lnk=`readlink $(DESTDIR)$(sbindir)/$$file`; \ - if [ "$$lnk" != "finit" ]; then \ - echo "Skipping non-finit $$file."; \ - continue; \ - fi; \ - $(RM) $(DESTDIR)$(sbindir)/$$file; \ + @for file in $(INIT_LNKS); do \ + lnk=$(DESTDIR)$(sbindir)/$$file; \ + dst=`readlink $$lnk`; \ + if [ "$$dst" != "finit" ]; then \ + continue; \ + fi; \ + $(RM) $(DESTDIR)$(sbindir)/$$file; \ + done + @for file in $(REBOOT_LNKS); do \ + lnk=$(DESTDIR)$(sbindir)/$$file; \ + dst=`readlink $$lnk`; \ + if [ "$$dst" != "initctl" ]; then \ + continue; \ + fi; \ + $(RM) $$lnk; \ done - @if [ -L $(DESTDIR)$(sbindir)/reboot ]; then \ - echo "Non-finit reboot, skipping uninstall."; \ - else \ - for file in $(REBOOT_LNKS); do \ - lnk=$(DESTDIR)$(sbindir)/$$file; \ - dst=`readlink $$lnk`; \ - if [ "$$dst" != "reboot" ]; then \ - continue; \ - fi; \ - $(RM) $$lnk; \ - done; \ - fi diff --git a/src/initctl.c b/src/initctl.c index 2d81606a..fd12d5dd 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -54,6 +54,9 @@ int verbose = 0; int runlevel = 0; int iw, pw; +extern int reboot_main(int argc, char *argv[]); + + /* figure ut width of IDENT and PID columns */ static void col_widths(void) { @@ -349,17 +352,30 @@ static int do_cond(char *cmd) return do_cond_show(NULL); } -static int do_signal(int signo, const char *msg) +static int do_cmd(int cmd) { - if (kill(1, signo)) - err(1, "Failed signalling init to %s", msg); + struct init_request rq = { + .magic = INIT_MAGIC, + .cmd = cmd, + }; + + if (client_send(&rq, sizeof(rq))) { + if (rq.cmd == INIT_CMD_NACK) + puts(rq.data); + + return 1; + } + + /* Wait here for systemd to shutdown/reboot */ + sleep(5); return 0; } -static int do_halt (char *arg) { return do_signal(SIGUSR1, "halt"); } -static int do_poweroff(char *arg) { return do_signal(SIGUSR2, "power off"); } -static int do_reboot (char *arg) { return do_signal(SIGTERM, "reboot"); } +int do_reboot (char *arg) { return do_cmd(INIT_CMD_REBOOT); } +int do_halt (char *arg) { return do_cmd(INIT_CMD_HALT); } +int do_poweroff(char *arg) { return do_cmd(INIT_CMD_POWEROFF); } +int do_suspend (char *arg) { return do_cmd(INIT_CMD_SUSPEND); } int utmp_show(char *file) { @@ -605,6 +621,22 @@ static int show_cgroup(char *arg) return 0; } +static int transform(char *nm) +{ + char *names[] = { + "reboot", "shutdown", "poweroff", "halt", "suspend", + NULL + }; + size_t i; + + for (i = 0; names[i]; i++) { + if (!strcmp(nm, names[i])) + return 1; + } + + return 0; +} + static int usage(int rc) { fprintf(stderr, @@ -644,7 +676,8 @@ static int usage(int rc) " runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot\n" " reboot Reboot system\n" " halt Halt system\n" - " poweroff Halt and power off system\n", prognm); + " poweroff Halt and power off system\n" + " suspend Suspend system\n", prognm); if (has_utmp()) fprintf(stderr, @@ -693,6 +726,7 @@ int main(int argc, char *argv[]) { "reboot", do_reboot }, { "halt", do_halt }, { "poweroff", do_poweroff }, + { "suspend", do_suspend }, { "utmp", do_utmp }, { NULL, NULL } @@ -706,7 +740,9 @@ int main(int argc, char *argv[]) { NULL, 0, NULL, 0 } }; - progname(argv[0]); + if (transform(progname(argv[0]))) + return reboot_main(argc, argv); + while ((c = getopt_long(argc, argv, "bh?ntv", long_options, NULL)) != EOF) { switch(c) { case 'b': diff --git a/src/reboot.c b/src/reboot.c index 340471d4..ce397b96 100644 --- a/src/reboot.c +++ b/src/reboot.c @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -40,6 +41,13 @@ typedef enum { static cmd_t cmd = CMD_UNKNOWN; static char *msg = NULL; +/* initctl API */ +extern int do_reboot (char *arg); +extern int do_halt (char *arg); +extern int do_poweroff(char *arg); +extern int do_suspend (char *arg); + + static void transform(char *nm) { if (!nm) @@ -80,6 +88,16 @@ static void transform(char *nm) } } +/* + * fallback in case of initctl API failure + */ +static void do_kill(int signo, char *msg) +{ + if (kill(1, signo)) + err(1, "Failed signalling init to %s", msg); + do_sleep(5); +} + static void sig(int signo) { (void)signo; /* NOP */ @@ -100,7 +118,7 @@ static int usage(int rc) return rc; } -int main(int argc, char *argv[]) +int reboot_main(int argc, char *argv[]) { int c, force = 0; struct option long_options[] = { @@ -113,7 +131,7 @@ int main(int argc, char *argv[]) }; /* Initial command taken from program name */ - transform(progname(argv[0])); + transform(prognm); while ((c = getopt_long(argc, argv, "h?fHPpr", long_options, NULL)) != EOF) { switch(c) { @@ -165,6 +183,8 @@ int main(int argc, char *argv[]) case CMD_SUSPEND: c = reboot(RB_SW_SUSPEND); + if (c && errno == EINVAL) + errx(1, "Kernel does not support suspend."); break; case CMD_UNKNOWN: @@ -173,22 +193,25 @@ int main(int argc, char *argv[]) } if (c) - warn("Failed forced %s", msg); - else - return 0; + err(1, "Failed forced %s", msg); + + return 0; } switch (cmd) { case CMD_REBOOT: - c = kill(1, SIGTERM); + if (do_reboot(NULL)) + do_kill(SIGTERM, msg); break; case CMD_HALT: - c = kill(1, SIGUSR1); + if (do_halt(NULL)) + do_kill(SIGUSR1, msg); break; case CMD_POWEROFF: - c = kill(1, SIGUSR2); + if (do_poweroff(NULL)) + do_kill(SIGUSR2, msg); break; case CMD_SUSPEND: @@ -196,16 +219,15 @@ int main(int argc, char *argv[]) * Only initctl supports suspend, we avoid adding * another signal to finit for compat reasons. */ + do_suspend(NULL); + break; + case CMD_UNKNOWN: errx(1, "Invalid command"); break; } - if (c) - err(1, "Failed signalling init to %s", msg); - do_sleep(5); - return 0; }