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