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 H , -halt
 | 
				
			||||||
.Op Fl k , -kexec
 | 
					.Op Fl k , -kexec
 | 
				
			||||||
.Op Fl p , -poweroff
 | 
					.Op Fl p , -poweroff
 | 
				
			||||||
 | 
					.Op Fl R , -reexec
 | 
				
			||||||
.Op Fl r , -reboot
 | 
					.Op Fl r , -reboot
 | 
				
			||||||
.Sh DESCRIPTION
 | 
					.Sh DESCRIPTION
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
is the utility that communicates with openrc-init(8) to bring down the
 | 
					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"
 | 
					.Bl -tag -width "poweroff"
 | 
				
			||||||
.It Fl H , -halt
 | 
					.It Fl H , -halt
 | 
				
			||||||
Stop all services, kill all remaining processes and halt the system.
 | 
					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).
 | 
					kernel loaded via kexec(8).
 | 
				
			||||||
.It Fl p , -poweroff
 | 
					.It Fl p , -poweroff
 | 
				
			||||||
Stop all services, kill all processes and power off the system.
 | 
					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
 | 
					.It Fl r , -reboot
 | 
				
			||||||
Stop all services, kill all processes and reboot the system.
 | 
					Stop all services, kill all processes and reboot the system.
 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@@ -79,6 +80,12 @@ static void init(const char *default_runlevel)
 | 
				
			|||||||
	waitpid(pid, NULL, 0);
 | 
						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)
 | 
					static void handle_shutdown(const char *runlevel, int cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pid_t pid;
 | 
						pid_t pid;
 | 
				
			||||||
@@ -123,10 +130,11 @@ static void signal_handler(int sig)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *default_runlevel = NULL;
 | 
						char *default_runlevel;
 | 
				
			||||||
	char buf[2048];
 | 
						char buf[2048];
 | 
				
			||||||
	int count;
 | 
						int count;
 | 
				
			||||||
	FILE *fifo;
 | 
						FILE *fifo;
 | 
				
			||||||
 | 
						bool reexec = false;
 | 
				
			||||||
	struct sigaction sa;
 | 
						struct sigaction sa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (getpid() != 1)
 | 
						if (getpid() != 1)
 | 
				
			||||||
@@ -134,16 +142,22 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (argc > 1)
 | 
						if (argc > 1)
 | 
				
			||||||
		default_runlevel = argv[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);
 | 
						printf("OpenRC init version %s starting\n", VERSION);
 | 
				
			||||||
	init(default_runlevel);
 | 
						if (! reexec)
 | 
				
			||||||
 | 
							init(default_runlevel);
 | 
				
			||||||
	memset(&sa, 0, sizeof(sa));
 | 
						memset(&sa, 0, sizeof(sa));
 | 
				
			||||||
	sa.sa_handler = signal_handler;
 | 
						sa.sa_handler = signal_handler;
 | 
				
			||||||
	sigaction(SIGCHLD, &sa, NULL);
 | 
						sigaction(SIGCHLD, &sa, NULL);
 | 
				
			||||||
	sigaction(SIGINT, &sa, NULL);
 | 
						sigaction(SIGINT, &sa, NULL);
 | 
				
			||||||
	reboot(RB_DISABLE_CAD);
 | 
						reboot(RB_DISABLE_CAD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mkfifo(RC_INIT_FIFO, 0600) == -1)
 | 
						if (mkfifo(RC_INIT_FIFO, 0600) == -1 && errno != EEXIST)
 | 
				
			||||||
		perror("mkfifo");
 | 
							perror("mkfifo");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
@@ -166,6 +180,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
			handle_shutdown("shutdown", RB_POWER_OFF);
 | 
								handle_shutdown("shutdown", RB_POWER_OFF);
 | 
				
			||||||
		else if (strcmp(buf, "reboot") == 0)
 | 
							else if (strcmp(buf, "reboot") == 0)
 | 
				
			||||||
			handle_shutdown("reboot", RB_AUTOBOOT);
 | 
								handle_shutdown("reboot", RB_AUTOBOOT);
 | 
				
			||||||
 | 
							else if (strcmp(buf, "reexec") == 0)
 | 
				
			||||||
 | 
								handle_reexec(argv[0]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,11 +35,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const char *applet = NULL;
 | 
					const char *applet = NULL;
 | 
				
			||||||
const char *extraopts = NULL;
 | 
					const char *extraopts = NULL;
 | 
				
			||||||
const char *getoptstring = "kpr" getoptstring_COMMON;
 | 
					const char *getoptstring = "HkpRr" getoptstring_COMMON;
 | 
				
			||||||
const struct option longopts[] = {
 | 
					const struct option longopts[] = {
 | 
				
			||||||
	{ "halt",        no_argument, NULL, 'H'},
 | 
						{ "halt",        no_argument, NULL, 'H'},
 | 
				
			||||||
	{ "kexec",        no_argument, NULL, 'k'},
 | 
						{ "kexec",        no_argument, NULL, 'k'},
 | 
				
			||||||
	{ "poweroff",        no_argument, NULL, 'p'},
 | 
						{ "poweroff",        no_argument, NULL, 'p'},
 | 
				
			||||||
 | 
						{ "reexec",        no_argument, NULL, 'R'},
 | 
				
			||||||
	{ "reboot",        no_argument, NULL, 'r'},
 | 
						{ "reboot",        no_argument, NULL, 'r'},
 | 
				
			||||||
	longopts_COMMON
 | 
						longopts_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -47,11 +48,13 @@ const char * const longopts_help[] = {
 | 
				
			|||||||
	"halt the system",
 | 
						"halt the system",
 | 
				
			||||||
	"reboot the system using kexec",
 | 
						"reboot the system using kexec",
 | 
				
			||||||
	"power off the system",
 | 
						"power off the system",
 | 
				
			||||||
 | 
						"re-execute init (use after upgrading)",
 | 
				
			||||||
	"reboot the system",
 | 
						"reboot the system",
 | 
				
			||||||
	longopts_help_COMMON
 | 
						longopts_help_COMMON
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const char *usagestring = NULL;
 | 
					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)
 | 
					static void send_cmd(const char *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -79,6 +82,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	bool do_kexec = false;
 | 
						bool do_kexec = false;
 | 
				
			||||||
	bool do_poweroff = false;
 | 
						bool do_poweroff = false;
 | 
				
			||||||
	bool do_reboot = false;
 | 
						bool do_reboot = false;
 | 
				
			||||||
 | 
						bool do_reexec = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	applet = basename_c(argv[0]);
 | 
						applet = basename_c(argv[0]);
 | 
				
			||||||
if (geteuid() != 0)
 | 
					if (geteuid() != 0)
 | 
				
			||||||
@@ -99,6 +103,10 @@ if (geteuid() != 0)
 | 
				
			|||||||
			do_poweroff = true;
 | 
								do_poweroff = true;
 | 
				
			||||||
			cmd_count++;
 | 
								cmd_count++;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 'R':
 | 
				
			||||||
 | 
								do_reexec = true;
 | 
				
			||||||
 | 
								cmd_count++;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'r':
 | 
							case 'r':
 | 
				
			||||||
			do_reboot = true;
 | 
								do_reboot = true;
 | 
				
			||||||
			cmd_count++;
 | 
								cmd_count++;
 | 
				
			||||||
@@ -118,5 +126,7 @@ if (geteuid() != 0)
 | 
				
			|||||||
		send_cmd("poweroff");
 | 
							send_cmd("poweroff");
 | 
				
			||||||
	else if (do_reboot)
 | 
						else if (do_reboot)
 | 
				
			||||||
		send_cmd("reboot");
 | 
							send_cmd("reboot");
 | 
				
			||||||
 | 
						else if (do_reexec)
 | 
				
			||||||
 | 
							send_cmd("reexec");
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user