diff --git a/man/openrc-shutdown.8 b/man/openrc-shutdown.8 index 98ec64a6..eae16ae8 100644 --- a/man/openrc-shutdown.8 +++ b/man/openrc-shutdown.8 @@ -19,11 +19,13 @@ .Op Fl H , -halt .Op Fl k , -kexec .Op Fl p , -poweroff +.Op Fl R , -reexec .Op Fl r , -reboot .Sh DESCRIPTION .Nm is the utility that communicates with openrc-init(8) to bring down the -system. The following options affect how the system is brought down: +system or instruct openrc-init to re-execute itself. It supports the +following options: .Bl -tag -width "poweroff" .It Fl H , -halt Stop all services, kill all remaining processes and halt the system. @@ -32,6 +34,9 @@ Stop all services, kill all processes and boot directly into a new kernel loaded via kexec(8). .It Fl p , -poweroff Stop all services, kill all processes and power off the system. +.It Fl R , -reexec +instruct openrc-init to re-exec itself. This should be used after an +upgrade of OpenRC if you are using openrc-init as your init process. .It Fl r , -reboot Stop all services, kill all processes and reboot the system. .El diff --git a/src/rc/openrc-init.c b/src/rc/openrc-init.c index fb3347a4..61052806 100644 --- a/src/rc/openrc-init.c +++ b/src/rc/openrc-init.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -79,6 +80,12 @@ static void init(const char *default_runlevel) waitpid(pid, NULL, 0); } +static void handle_reexec(char *my_name) +{ + execl(my_name, my_name, "reexec", NULL); + return; +} + static void handle_shutdown(const char *runlevel, int cmd) { pid_t pid; @@ -123,10 +130,11 @@ static void signal_handler(int sig) int main(int argc, char **argv) { - char *default_runlevel = NULL; + char *default_runlevel; char buf[2048]; int count; FILE *fifo; + bool reexec = false; struct sigaction sa; if (getpid() != 1) @@ -134,16 +142,22 @@ int main(int argc, char **argv) if (argc > 1) default_runlevel = argv[1]; + else + default_runlevel = NULL; + + if (default_runlevel && strcmp(default_runlevel, "reexec") == 0) + reexec = true; printf("OpenRC init version %s starting\n", VERSION); - init(default_runlevel); + if (! reexec) + init(default_runlevel); memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGINT, &sa, NULL); reboot(RB_DISABLE_CAD); - if (mkfifo(RC_INIT_FIFO, 0600) == -1) + if (mkfifo(RC_INIT_FIFO, 0600) == -1 && errno != EEXIST) perror("mkfifo"); for (;;) { @@ -166,6 +180,8 @@ int main(int argc, char **argv) handle_shutdown("shutdown", RB_POWER_OFF); else if (strcmp(buf, "reboot") == 0) handle_shutdown("reboot", RB_AUTOBOOT); + else if (strcmp(buf, "reexec") == 0) + handle_reexec(argv[0]); } return 0; } diff --git a/src/rc/openrc-shutdown.c b/src/rc/openrc-shutdown.c index 978e8a68..8905d354 100644 --- a/src/rc/openrc-shutdown.c +++ b/src/rc/openrc-shutdown.c @@ -35,11 +35,12 @@ const char *applet = NULL; const char *extraopts = NULL; -const char *getoptstring = "kpr" getoptstring_COMMON; +const char *getoptstring = "HkpRr" getoptstring_COMMON; const struct option longopts[] = { { "halt", no_argument, NULL, 'H'}, { "kexec", no_argument, NULL, 'k'}, { "poweroff", no_argument, NULL, 'p'}, + { "reexec", no_argument, NULL, 'R'}, { "reboot", no_argument, NULL, 'r'}, longopts_COMMON }; @@ -47,11 +48,13 @@ const char * const longopts_help[] = { "halt the system", "reboot the system using kexec", "power off the system", + "re-execute init (use after upgrading)", "reboot the system", longopts_help_COMMON }; const char *usagestring = NULL; -const char *exclusive = "Select one of --halt, --kexec, --poweroff or --reboot"; +const char *exclusive = "Select one of " +"--halt, --kexec, --poweroff, --reexec or --reboot"; static void send_cmd(const char *cmd) { @@ -79,6 +82,7 @@ int main(int argc, char **argv) bool do_kexec = false; bool do_poweroff = false; bool do_reboot = false; + bool do_reexec = false; applet = basename_c(argv[0]); if (geteuid() != 0) @@ -99,6 +103,10 @@ if (geteuid() != 0) do_poweroff = true; cmd_count++; break; + case 'R': + do_reexec = true; + cmd_count++; + break; case 'r': do_reboot = true; cmd_count++; @@ -118,5 +126,7 @@ if (geteuid() != 0) send_cmd("poweroff"); else if (do_reboot) send_cmd("reboot"); + else if (do_reexec) + send_cmd("reexec"); return 0; }