init: add re-exec capability
This will allow the re-execution of the init process after upgrading OpenRC.
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user