add init process
openrc-init.c and openrc-shutdown.c are based on code which was written by James Hammons <jlhamm@acm.org>, so I would like to publically thank him for his work.
This commit is contained in:
		
							
								
								
									
										7
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								NEWS.md
									
									
									
									
									
								
							| @@ -3,6 +3,13 @@ | ||||
| This file will contain a list of notable changes for each release. Note | ||||
| the information in this file is in reverse order. | ||||
|  | ||||
| ## OpenRC-0.25 | ||||
|  | ||||
| This version contains an OpenRC-specific implementation of init for | ||||
| Linux which can be used in place of sysvinit or any other init process. | ||||
| For information on its usage, see the man pages for openrc-init (8) and | ||||
| openrc-shutdown (8). | ||||
|  | ||||
| ## OpenRC-0.24.1 | ||||
|  | ||||
| This version starts cleaning up the dependencies so that rc_parallel | ||||
|   | ||||
| @@ -178,6 +178,11 @@ | ||||
| # "xenU"           - XenU Domain (Linux and NetBSD) | ||||
| #rc_sys="" | ||||
|  | ||||
| # if  you use openrc-init, which is currently only available on Linux, | ||||
| # this is the default runlevel to activate after "sysinit" and "boot" | ||||
| # when booting. | ||||
| #rc_default_runlevel="default" | ||||
|  | ||||
| # on Linux and Hurd, this is the number of ttys allocated for logins | ||||
| # It is used in the consolefont, keymaps, numlock and termencoding | ||||
| # service scripts. | ||||
|   | ||||
| @@ -9,7 +9,7 @@ MAN8=		rc-service.8 rc-status.8 rc-update.8 openrc.8 openrc-run.8 \ | ||||
| 		service.8 start-stop-daemon.8 supervise-daemon.8 | ||||
|  | ||||
| ifeq (${OS},Linux) | ||||
| MAN8 += rc-sstat.8 | ||||
| MAN8 += rc-sstat.8 openrc-init.8 openrc-shutdown.8 | ||||
| endif | ||||
|  | ||||
| # Handy macro to create symlinks | ||||
|   | ||||
							
								
								
									
										46
									
								
								man/openrc-init.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								man/openrc-init.8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| .\" Copyright (c) 2017 The OpenRC Authors. | ||||
| .\" See the Authors file at the top-level directory of this distribution and | ||||
| .\" https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
| .\" | ||||
| .\" This file is part of OpenRC. It is subject to the license terms in | ||||
| .\" the LICENSE file found in the top-level directory of this | ||||
| .\" distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
| .\" This file may not be copied, modified, propagated, or distributed | ||||
| .\"    except according to the terms contained in the LICENSE file. | ||||
| .\" | ||||
| .Dd April 6, 2017 | ||||
| .Dt openrc-init 8 SMM | ||||
| .Os OpenRC | ||||
| .Sh NAME | ||||
| .Nm openrc-init | ||||
| .Nd the parent of all processes | ||||
| .Sh SYNOPSIS | ||||
| .Nm | ||||
| .Sh DESCRIPTION | ||||
| .Nm | ||||
| is an init process which can be an alternative to sysvinit or any other | ||||
| init process. | ||||
| .Pp | ||||
| To use | ||||
| .Nm | ||||
| configure your boot loader to invoke it or symlink it to /sbin/init. | ||||
| Also, you will need to use | ||||
| .Xr openrc-shutdown 8 , | ||||
| to halt, reboot or poweroff the system. | ||||
| .Pp | ||||
| The default runlevel is read from the init command line, the | ||||
| rc_default_runlevel setting in rc.conf, the kernel command line, or it is | ||||
| assumed to be "default" if it is not set in any of these places. | ||||
| .Pp | ||||
| .Nm | ||||
| doesn't manage getty's directly, so you will need to manage them another | ||||
| way. For example, you can use the agetty service script as described in | ||||
| agetty-guide.md in this distribution. | ||||
| .Sh BUGS | ||||
| OpenRC 0.25 contains the first release of this init process. | ||||
| I do not know of any specific issues. However, if you use it, please be | ||||
| aware that there may be bugs and report any issues you find. | ||||
| .Sh SEE ALSO | ||||
| .Xr openrc-shutdown 8 , | ||||
| .Sh AUTHORS | ||||
| .An William Hubbs <w.d.hubbs@gmail.com> | ||||
							
								
								
									
										42
									
								
								man/openrc-shutdown.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								man/openrc-shutdown.8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| .\" Copyright (c) 2017 The OpenRC Authors. | ||||
| .\" See the Authors file at the top-level directory of this distribution and | ||||
| .\" https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
| .\" | ||||
| .\" This file is part of OpenRC. It is subject to the license terms in | ||||
| .\" the LICENSE file found in the top-level directory of this | ||||
| .\" distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
| .\" This file may not be copied, modified, propagated, or distributed | ||||
| .\"    except according to the terms contained in the LICENSE file. | ||||
| .\" | ||||
| .Dd April 6, 2017 | ||||
| .Dt openrc-shutdown 8 SMM | ||||
| .Os OpenRC | ||||
| .Sh NAME | ||||
| .Nm openrc-shutdown | ||||
| .Nd bring the system down | ||||
| .Sh SYNOPSIS | ||||
| .Nm | ||||
| .Op Fl H , -halt | ||||
| .Op Fl k , -kexec | ||||
| .Op Fl p , -poweroff | ||||
| .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: | ||||
| .Bl -tag -width "poweroff" | ||||
| .It Fl H , -halt | ||||
| Stop all services, kill all remaining processes and halt the system. | ||||
| .It Fl k , -kexec | ||||
| 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 , -reboot | ||||
| Stop all services, kill all processes and reboot the system. | ||||
| .El | ||||
| .Sh SEE ALSO | ||||
| .Xr openrc-init 8 , | ||||
| .Xr kexec 8 , | ||||
| .Sh AUTHORS | ||||
| .An William Hubbs <w.d.hubbs@gmail.com> | ||||
| @@ -39,6 +39,7 @@ extern "C" { | ||||
| #define RC_CONFDIR              RC_SYSCONFDIR "/conf.d" | ||||
| #define RC_PLUGINDIR            RC_LIBDIR "/plugins" | ||||
|  | ||||
| #define RC_INIT_FIFO RC_SVCDIR"/init.ctl" | ||||
| #define RC_PROFILE_ENV     RC_SYSCONFDIR "/profile.env" | ||||
| #define RC_SYS_WHITELIST   RC_LIBEXECDIR "/conf.d/env_whitelist" | ||||
| #define RC_USR_WHITELIST   RC_SYSCONFDIR "/conf.d/env_whitelist" | ||||
|   | ||||
							
								
								
									
										2
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -59,4 +59,6 @@ mark_service_failed | ||||
| rc-abort | ||||
| rc | ||||
| openrc | ||||
| openrc-init | ||||
| openrc-run | ||||
| openrc-shutdown | ||||
|   | ||||
| @@ -1,3 +1,7 @@ | ||||
| include ../../Makefile.inc | ||||
| MK=		../../mk | ||||
| include ${MK}/os.mk | ||||
|  | ||||
| SRCS=	checkpath.c do_e.c do_mark_service.c do_service.c \ | ||||
| 		do_value.c fstabinfo.c is_newer_than.c is_older_than.c \ | ||||
| 		mountinfo.c openrc-run.c rc-abort.c rc.c \ | ||||
| @@ -9,6 +13,10 @@ ifeq (${MKSELINUX},yes) | ||||
| SRCS+=		rc-selinux.c | ||||
| endif | ||||
|  | ||||
| ifeq (${OS},Linux) | ||||
| SRCS+=		openrc-init.c openrc-shutdown.c | ||||
| endif | ||||
|  | ||||
| CLEANFILES=	version.h rc-selinux.o | ||||
|  | ||||
| BINDIR=		${PREFIX}/bin | ||||
| @@ -34,6 +42,11 @@ RC_SBINPROGS=	mark_service_starting mark_service_started \ | ||||
| 		mark_service_inactive mark_service_wasinactive \ | ||||
| 		mark_service_hotplugged mark_service_failed \ | ||||
| 		rc-abort swclock | ||||
|  | ||||
| ifeq (${OS},Linux) | ||||
| SBINPROGS+= openrc-init openrc-shutdown | ||||
| endif | ||||
|  | ||||
| ALL_PROGS=	${BINPROGS} ${SBINPROGS} ${RC_BINPROGS} ${RC_SBINPROGS} | ||||
| CLEANFILES+=	${ALL_PROGS} | ||||
|  | ||||
| @@ -41,8 +54,6 @@ LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo | ||||
| LOCAL_LDFLAGS=-L../librc -L../libeinfo | ||||
| LDADD+=		-lutil -lrc -leinfo | ||||
|  | ||||
| include ../../Makefile.inc | ||||
| MK=		../../mk | ||||
| include ${MK}/prog.mk | ||||
| include ${MK}/gitver.mk | ||||
| include ${MK}/cc.mk | ||||
| @@ -96,6 +107,9 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o | ||||
| fstabinfo: fstabinfo.o _usage.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| openrc-init: openrc-init.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| is_newer_than: is_newer_than.o rc-misc.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| @@ -114,6 +128,9 @@ mountinfo: mountinfo.o _usage.o rc-misc.o | ||||
| openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| openrc-shutdown: openrc-shutdown.o _usage.o | ||||
| 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} | ||||
|  | ||||
| openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o | ||||
| ifeq (${MKSELINUX},yes) | ||||
| openrc-run runscript: rc-selinux.o | ||||
|   | ||||
							
								
								
									
										168
									
								
								src/rc/openrc-init.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								src/rc/openrc-init.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| /* | ||||
|  * openrc-init.c | ||||
|  * This is the init process (pid 1) for OpenRC. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2017 The OpenRC Authors. | ||||
|  * See the Authors file at the top-level directory of this distribution and | ||||
|  * https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
|  * | ||||
|  * This file is part of OpenRC. It is subject to the license terms in | ||||
|  * the LICENSE file found in the top-level directory of this | ||||
|  * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
|  * This file may not be copied, modified, propagated, or distributed | ||||
|  *    except according to the terms contained in the LICENSE file. | ||||
|  */ | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/reboot.h> | ||||
| #include <sys/wait.h> | ||||
|  | ||||
| #include "helpers.h" | ||||
| #include "rc.h" | ||||
| #include "version.h" | ||||
|  | ||||
| static const char *rc_default_runlevel = "default"; | ||||
|  | ||||
| static pid_t do_openrc(const char *runlevel) | ||||
| { | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	pid = fork(); | ||||
| 	switch(pid) { | ||||
| 		case -1: | ||||
| 			perror("fork"); | ||||
| 			break; | ||||
| 		case 0: | ||||
| 			setsid(); | ||||
| 			printf("Starting %s runlevel\n", runlevel); | ||||
| 			execl("/sbin/openrc", "/sbin/openrc", runlevel, NULL); | ||||
| 			perror("exec"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| static void init(const char *default_runlevel) | ||||
| { | ||||
| 	const char *runlevel = NULL; | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	pid = do_openrc("sysinit"); | ||||
| 	waitpid(pid, NULL, 0); | ||||
| 	pid = do_openrc("boot"); | ||||
| 	waitpid(pid, NULL, 0); | ||||
| 	if (default_runlevel) | ||||
| 		runlevel = default_runlevel; | ||||
| 	else | ||||
| 		runlevel = rc_conf_value("rc_default_runlevel"); | ||||
| 	if (!runlevel) | ||||
| 		runlevel = rc_default_runlevel; | ||||
| 	if (!rc_runlevel_exists(runlevel)) { | ||||
| 		printf("%s is an invalid runlevel\n", runlevel); | ||||
| 		runlevel = rc_default_runlevel; | ||||
| 	} | ||||
| 	pid = do_openrc(runlevel); | ||||
| 	waitpid(pid, NULL, 0); | ||||
| } | ||||
|  | ||||
| static void handle_shutdown(const char *runlevel, int cmd) | ||||
| { | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	pid = do_openrc(runlevel); | ||||
| 	while (waitpid(pid, NULL, 0) != pid); | ||||
| 	sync(); | ||||
| 	reboot(cmd); | ||||
| } | ||||
|  | ||||
| static void reap_zombies(void) | ||||
| { | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	for (;;) { | ||||
| 		pid = waitpid(-1, NULL, WNOHANG); | ||||
| 		if (pid == 0) | ||||
| 			break; | ||||
| 		else if (pid == -1) { | ||||
| 			if (errno == ECHILD) | ||||
| 				break; | ||||
| 			perror("waitpid"); | ||||
| 			continue; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void signal_handler(int sig) | ||||
| { | ||||
| 	switch(sig) { | ||||
| 		case SIGINT: | ||||
| 			handle_shutdown("reboot", RB_AUTOBOOT); | ||||
| 			break; | ||||
| 		case SIGCHLD: | ||||
| 			reap_zombies(); | ||||
| 			break; | ||||
| 		default: | ||||
| 			printf("Unknown signal received, %d\n", sig); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	char *default_runlevel = NULL; | ||||
| 	char buf[2048]; | ||||
| 	int count; | ||||
| 	FILE *fifo; | ||||
| 	struct sigaction sa; | ||||
|  | ||||
| 	if (getpid() != 1) | ||||
| 		return 1; | ||||
|  | ||||
| 	if (argc > 1) | ||||
| 		default_runlevel = argv[1]; | ||||
|  | ||||
| 	printf("OpenRC init version %s starting\n", VERSION); | ||||
| 	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) | ||||
| 		perror("mkfifo"); | ||||
|  | ||||
| 	for (;;) { | ||||
| 		/* This will block until a command is sent down the pipe... */ | ||||
| 		fifo = fopen(RC_INIT_FIFO, "r"); | ||||
| 		if (!fifo) { | ||||
| 			if (errno != EINTR) | ||||
| 				perror("fopen"); | ||||
| 			continue; | ||||
| 		} | ||||
| 		count = fread(buf, 1, 2048, fifo); | ||||
| 		buf[count] = 0; | ||||
| 		fclose(fifo); | ||||
| 		printf("PID1: Received \"%s\" from FIFO...\n", buf); | ||||
| 		if (strcmp(buf, "halt") == 0) | ||||
| 			handle_shutdown("shutdown", RB_HALT_SYSTEM); | ||||
| 		else if (strcmp(buf, "kexec") == 0) | ||||
| 			handle_shutdown("reboot", RB_KEXEC); | ||||
| 		else if (strcmp(buf, "poweroff") == 0) | ||||
| 			handle_shutdown("shutdown", RB_POWER_OFF); | ||||
| 		else if (strcmp(buf, "reboot") == 0) | ||||
| 			handle_shutdown("reboot", RB_AUTOBOOT); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										119
									
								
								src/rc/openrc-shutdown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/rc/openrc-shutdown.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| /* | ||||
|  * openrc-shutdown.c | ||||
|  * If you are using OpenRC's provided init, this will shut down or | ||||
|  * reboot your system. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2017 The OpenRC Authors. | ||||
|  * See the Authors file at the top-level directory of this distribution and | ||||
|  * https://github.com/OpenRC/openrc/blob/master/AUTHORS | ||||
|  * | ||||
|  * This file is part of OpenRC. It is subject to the license terms in | ||||
|  * the LICENSE file found in the top-level directory of this | ||||
|  * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE | ||||
|  * This file may not be copied, modified, propagated, or distributed | ||||
|  *    except according to the terms contained in the LICENSE file. | ||||
|  */ | ||||
|  | ||||
| #include <getopt.h> | ||||
| #include <signal.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include "einfo.h" | ||||
| #include "rc.h" | ||||
| #include "helpers.h" | ||||
| #include "_usage.h" | ||||
|  | ||||
| const char *applet = NULL; | ||||
| const char *extraopts = NULL; | ||||
| const char *getoptstring = "kpr" getoptstring_COMMON; | ||||
| const struct option longopts[] = { | ||||
| 	{ "halt",        no_argument, NULL, 'H'}, | ||||
| 	{ "kexec",        no_argument, NULL, 'k'}, | ||||
| 	{ "poweroff",        no_argument, NULL, 'p'}, | ||||
| 	{ "reboot",        no_argument, NULL, 'r'}, | ||||
| 	longopts_COMMON | ||||
| }; | ||||
| const char * const longopts_help[] = { | ||||
| 	"halt the system", | ||||
| 	"reboot the system using kexec", | ||||
| 	"power off the system", | ||||
| 	"reboot the system", | ||||
| 	longopts_help_COMMON | ||||
| }; | ||||
| const char *usagestring = NULL; | ||||
| const char *exclusive = "Select one of --halt, --kexec, --poweroff or --reboot"; | ||||
|  | ||||
| static void send_cmd(const char *cmd) | ||||
| { | ||||
| 	FILE *fifo; | ||||
|  	size_t ignored; | ||||
|  | ||||
| 	fifo = fopen(RC_INIT_FIFO, "w"); | ||||
|  | ||||
| 	if (!fifo) { | ||||
| 		perror("fopen"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	ignored = fwrite(cmd, 1, strlen(cmd), fifo); | ||||
| 	if (ignored != strlen(cmd)) | ||||
| 		printf("Error writing to init fifo\n"); | ||||
| 	fclose(fifo); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	int opt; | ||||
| 	int cmd_count = 0; | ||||
| 	bool do_halt = false; | ||||
| 	bool do_kexec = false; | ||||
| 	bool do_poweroff = false; | ||||
| 	bool do_reboot = false; | ||||
|  | ||||
| 	applet = basename_c(argv[0]); | ||||
| if (geteuid() != 0) | ||||
| 	eerrorx("%s: you must be root\n", applet); | ||||
| 	while ((opt = getopt_long(argc, argv, getoptstring, | ||||
| 		    longopts, (int *) 0)) != -1) | ||||
| 	{ | ||||
| 		switch (opt) { | ||||
| 		case 'H': | ||||
| 			do_halt = true; | ||||
| 			cmd_count++; | ||||
| 			break; | ||||
| 		case 'k': | ||||
| 			do_kexec = true; | ||||
| 			cmd_count++; | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 			do_poweroff = true; | ||||
| 			cmd_count++; | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			do_reboot = true; | ||||
| 			cmd_count++; | ||||
| 			break; | ||||
| 		case_RC_COMMON_GETOPT | ||||
| 		} | ||||
| 	} | ||||
| 	if (cmd_count != 1) { | ||||
| 		eerror("%s: %s\n", applet, exclusive); | ||||
| 		usage(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (do_halt) | ||||
| 		send_cmd("halt"); | ||||
| 	else if (do_kexec) | ||||
| 		send_cmd("kexec"); | ||||
| 	else if (do_poweroff) | ||||
| 		send_cmd("poweroff"); | ||||
| 	else if (do_reboot) | ||||
| 		send_cmd("reboot"); | ||||
| 	return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user