Пример #1
0
void do_shutdown (int sig)
{
	touch(SYNC_SHUTDOWN);

	if (sdown)
		run_interactive(sdown, "Calling shutdown hook: %s", sdown);

	_d("Sending SIGTERM to all processes.");
	kill(-1, SIGTERM);

	sleep(1);
	/* Call all shutdown hooks, this is the last call before rebooting... */
	plugin_run_hooks(HOOK_SHUTDOWN);

	_d("Sending SIGKILL to remaining processes.");
	kill(-1, SIGKILL);

	sync();
	sync();
	_d("Unmounting file systems, remounting / read-only.");
	run("/bin/umount -fa 2>/dev/null");
	run("/bin/mount -n -o remount,ro / 2>/dev/null");
	run("/sbin/swapoff -ea");

	_d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting");
	if (sig == SIGINT || sig == SIGUSR1)
		reboot(RB_AUTOBOOT);

	reboot(RB_POWER_OFF);
}
Пример #2
0
void do_shutdown(int sig)
{
	touch(SYNC_SHUTDOWN);

	if (sdown)
		run_interactive(sdown, "Calling shutdown hook: %s", sdown);

	/* Call all shutdown hooks before rebooting... */
	plugin_run_hooks(HOOK_SHUTDOWN);

	/* Here is where we signal watchdogd to do a forced reset for us */
	_d("Sending SIGTERM to all processes.");
	kill(-1, SIGTERM);

	/* Wait for WDT to timeout, should be no more than ~1 sec. */
	do_sleep(2);

	_d("Sending SIGKILL to remaining processes.");
	kill(-1, SIGKILL);

	sync();
	sync();
	_d("Unmounting file systems, remounting / read-only.");
	run("/bin/umount -fa 2>/dev/null");
	run("/bin/mount -n -o remount,ro / 2>/dev/null");
	run("/sbin/swapoff -ea");

	_d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting");
	if (sig == SIGINT || sig == SIGUSR1)
		reboot(RB_AUTOBOOT);

	reboot(RB_POWER_OFF);
}
Пример #3
0
/*
 * Handle bootstrap transition to configured runlevel, start TTYs
 *
 * This is the final stage of bootstrap.  It changes to the default
 * (configured) runlevel, calls all external start scripts and final
 * bootstrap hooks before bringing up TTYs.
 *
 * We must ensure that all declared `task [S]` and `run [S]` jobs in
 * finit.conf, or *.conf in finit.d/, run to completion before we
 * finalize the bootstrap process by calling this function.
 */
static void finalize(void)
{
	/*
	 * Run startup scripts in the runparts directory, if any.
	 */
	if (runparts && fisdir(runparts) && !rescue)
		run_parts(runparts, NULL);

	/*
	 * Start all tasks/services in the configured runlevel
	 */
	_d("Change to default runlevel, start all services ...");
	service_runlevel(cfglevel);

	/* Clean up bootstrap-only tasks/services that never started */
	_d("Clean up all bootstrap-only tasks/services ...");
	svc_prune_bootstrap();

	/* All services/tasks/inetd/etc. in configure runlevel have started */
	_d("Running svc up hooks ...");
	plugin_run_hooks(HOOK_SVC_UP);
	service_step_all(SVC_TYPE_ANY);

	/* Convenient SysV compat for when you just don't care ... */
	if (!access(FINIT_RC_LOCAL, X_OK) && !rescue)
		run_interactive(FINIT_RC_LOCAL, "Calling %s", FINIT_RC_LOCAL);

	/* Hooks that should run at the very end */
	_d("Calling all system up hooks ...");
	plugin_run_hooks(HOOK_SYSTEM_UP);
	service_step_all(SVC_TYPE_ANY);

	/* Enable silent mode before starting TTYs */
	_d("Going silent ...");
	log_silent();

	/* Delayed start of TTYs at bootstrap */
	_d("Launching all getty services ...");
	tty_runlevel();
}
Пример #4
0
/**
 * service_stop_dynamic - Stop disabled/removed dynamic services
 */
void service_stop_dynamic(void)
{
	svc_t *svc;

	_d("Stopping disabled/removed services ...");
	for (svc = svc_dynamic_iterator(1); svc; svc = svc_dynamic_iterator(0)) {
		if (svc_is_changed(svc))
			service_stop(svc);
	}

	_d("All disabled/removed services have been stoppped, calling reconf hooks ...");
	plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */
}
Пример #5
0
/*
 * Show user configured banner before service bootstrap progress
 */
static void banner(void)
{
	char *buf = INIT_HEADING;
	char separator[SCREEN_WIDTH];

	if (plugin_exists(HOOK_BANNER)) {
		plugin_run_hooks(HOOK_BANNER);
		return;
	}

	if (log_is_silent())
		return;

	memset(separator, '=', sizeof(separator));
	fprintf(stderr, "\n\e[2K\e[1m%s %.*s\e[0m\n", buf, SCREEN_WIDTH - (int)strlen(buf) - 2, separator);
}
Пример #6
0
void svc_start_all(void)
{
	svc_t *svc;
	svc_cmd_t cmd;

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		cmd = svc_enabled(svc, 0, NULL);
		if (SVC_START == cmd  || (SVC_RELOAD == cmd && svc->pid == 0))
			svc_start(svc);
		else if (SVC_RELOAD == cmd)
			svc_reload(svc);
	}

	_d("Running svc up hooks ...");
	plugin_run_hooks(HOOK_SVC_UP);
}
Пример #7
0
/*
 * Unless there are services we must collect first (wait for
 * them to stop), we can call HOOK_SVC_RECONF here.
 */
static int service_stop_done(svc_t *svc)
{
	if (svc && !svc_is_changed(svc))
		return 0;

	if (svc && dyn_stop_cnt)
		dyn_stop_cnt--;

	_d("dyn_stop_cnt %d", dyn_stop_cnt);
	if (!dyn_stop_cnt) {
		_d("All disabled/removed services have been stoppped, calling reconf hooks ...");
		plugin_run_hooks(HOOK_SVC_RECONF); /* Reconfigure HW/VLANs/etc here */

		/* Finish off by starting/reload modified/new services */
		service_start_dynamic();
	}

	return 1;
}
Пример #8
0
int main(int argc, char* argv[])
{
	char *path;
	char cmd[256];
	int udev = 0;
	uev_t timer;	       /* Bootstrap timer, on timeout call finalize() */
	uev_ctx_t loop;

	/*
	 * finit/init/telinit client tool uses /dev/initctl pipe
	 * for compatibility but initctl client tool uses socket
	 */
	if (getpid() != 1)
		return client(argc, argv);

	/*
	 * Initalize event context.
	 */
	uev_init(&loop);
	ctx = &loop;

	/*
	 * Set PATH and SHELL early to something sane
	 */
	setenv("PATH", _PATH_STDPATH, 1);
	setenv("SHELL", _PATH_BSHELL, 1);

	/*
	 * Mount base file system, kernel is assumed to run devtmpfs for /dev
	 */
	chdir("/");
	umask(0);
	mount("none", "/proc", "proc", 0, NULL);
	mount("none", "/sys", "sysfs", 0, NULL);
	if (fisdir("/proc/bus/usb"))
		mount("none", "/proc/bus/usb", "usbfs", 0, NULL);

	/*
	 * Parse kernel command line (debug, rescue, splash, etc.)
	 * Also calls log_init() to set correct log level
	 */
	conf_parse_cmdline();

	/* Set up canvas */
	if (!rescue && !log_is_debug())
		screen_init();

	/*
	 * In case of emergency.
	 */
	emergency_shell();

	/*
	 * Initial setup of signals, ignore all until we're up.
	 */
	sig_init();

	/*
	 * Load plugins early, finit.conf may contain references to
	 * features implemented by plugins.
	 */
	plugin_init(&loop);

	/*
	 * Hello world.
	 */
	banner();

	/*
	 * Check file filesystems in /etc/fstab
	 */
	for (int pass = 1; pass < 10 && !rescue; pass++) {
		if (fsck(pass))
			break;
	}

	/*
	 * Initialize .conf system and load static /etc/finit.conf
	 * Also initializes global_rlimit[] for udevd, below.
	 */
	conf_init();

	/*
	 * Some non-embedded systems without an initramfs may not have /dev mounted yet
	 * If they do, check if system has udevadm and perform cleanup from initramfs
	 */
	if (!fismnt("/dev"))
		mount("udev", "/dev", "devtmpfs", MS_RELATIME, "size=10%,nr_inodes=61156,mode=755");
	else if (whichp("udevadm"))
		run_interactive("udevadm info --cleanup-db", "Cleaning up udev db");

	/* Some systems use /dev/pts */
	makedir("/dev/pts", 0755);
	mount("devpts", "/dev/pts", "devpts", 0, "gid=5,mode=620");

	/*
	 * Some systems rely on us to both create /dev/shm and, to mount
	 * a tmpfs there.  Any system with dbus needs shared memory, so
	 * mount it, unless its already mounted, but not if listed in
	 * the /etc/fstab file already.
	 */
	makedir("/dev/shm", 0755);
	if (!fismnt("/dev/shm") && !ismnt("/etc/fstab", "/dev/shm"))
		mount("shm", "/dev/shm", "tmpfs", 0, NULL);

	/*
	 * New tmpfs based /run for volatile runtime data
	 * For details, see http://lwn.net/Articles/436012/
	 */
	if (fisdir("/run") && !fismnt("/run"))
		mount("tmpfs", "/run", "tmpfs", MS_NODEV, "mode=0755,size=10%");
	umask(022);

	/* Bootstrap conditions, needed for hooks */
	cond_init();

	/*
	 * Populate /dev and prepare for runtime events from kernel.
	 * Prefer udev if mdev is also available on the system.
	 */
	path = which("udevd");
	if (!path)
		path = which("/lib/systemd/systemd-udevd");
	if (path) {
		/* Desktop and server distros usually have a variant of udev */
		udev = 1;

		/* Register udevd as a monitored service */
		snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd %s -- Device event managing daemon", path);
		if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
			_pe("Failed registering %s", path);
			udev = 0;
		} else {
			snprintf(cmd, sizeof(cmd), ":1 [S] <svc%s> "
				 "udevadm trigger -c add -t devices "
				 "-- Requesting device events", path);
			service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);

			snprintf(cmd, sizeof(cmd), ":2 [S] <svc%s> "
				 "udevadm trigger -c add -t subsystems "
				 "-- Requesting subsystem events", path);
			service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
		}
		free(path);
	} else {
		path = which("mdev");
		if (path) {
			/* Embedded Linux systems usually have BusyBox mdev */
			if (log_is_debug())
				touch("/dev/mdev.log");

			snprintf(cmd, sizeof(cmd), "%s -s", path);
			free(path);

			run_interactive(cmd, "Populating device tree");
		}
	}

	/*
	 * Start built-in watchdog as soon as possible, if enabled
	 */
	wdogpid = watchdog(argv[0]);

	/*
	 * Mount filesystems
	 */
	if (!rescue) {
#ifdef REMOUNT_ROOTFS
		run("mount -n -o remount,rw /");
#endif
#ifdef SYSROOT
		mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
#endif
	}

	if (!rescue) {
		_d("Root FS up, calling hooks ...");
		plugin_run_hooks(HOOK_ROOTFS_UP);

		umask(0);
		if (run_interactive("mount -na", "Mounting filesystems"))
			plugin_run_hooks(HOOK_MOUNT_ERROR);

		_d("Calling extra mount hook, after mount -a ...");
		plugin_run_hooks(HOOK_MOUNT_POST);

		run("swapon -ea");
		umask(0022);
	}

	/* Base FS up, enable standard SysV init signals */
	sig_setup(&loop);

	if (!rescue) {
		_d("Base FS up, calling hooks ...");
		plugin_run_hooks(HOOK_BASEFS_UP);
	}

	/*
	 * Set up inotify watcher for /etc/finit.d and read all .conf
	 * files to figure out how to bootstrap the system.
	 */
	conf_monitor(&loop);

	/*
	 * Initalize state machine and start all bootstrap tasks
	 * NOTE: no network available!
	 */
	sm_init(&sm);
	sm_step(&sm);

	/* Debian has this little script to copy generated rules while the system was read-only */
	if (udev && fexist("/lib/udev/udev-finish"))
		run_interactive("/lib/udev/udev-finish", "Finalizing udev");

	/* Start new initctl API responder */
	api_init(&loop);
	umask(022);

	/*
	 * Wait for all SVC_TYPE_RUNTASK to have completed their work in
	 * [S], or timeout, before calling finalize()
	 */
	_d("Starting bootstrap finalize timer ...");
	uev_timer_init(&loop, &timer, service_bootstrap_cb, finalize, 1000, 1000);

	/*
	 * Enter main loop to monior /dev/initctl and services
	 */
	_d("Entering main loop ...");
	return uev_run(&loop, 0);
}
Пример #9
0
int main(int argc, char* argv[])
{
	if (getpid() != 1)
		return client(argc, argv);

	/*
	 * Hello world.
	 */
	banner();

	/*
	 * Initial setup of signals, ignore all until we're up.
	 */
	sig_init();

	/*
	 * Mount base file system, kernel is assumed to run devtmpfs for /dev
	 */
	chdir("/");
	umask(0);
	mount("none", "/proc", "proc", 0, NULL);
	mount("none", "/proc/bus/usb", "usbfs", 0, NULL);
	mount("none", "/sys", "sysfs", 0, NULL);
	mkdir("/dev/pts", 0755);
	mkdir("/dev/shm", 0755);
	mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620");
	mount("none", "/dev/shm", "tmpfs", 0, NULL);
	umask(022);

	/*
	 * Parse kernel parameters
	 */
	parse_kernel_cmdline();

	/*
	 * Populate /dev and prepare for runtime events from kernel.
	 */
	run_interactive(SETUP_DEVFS, "Populating device tree");

	/*
	 * Parse configuration file
	 */
	parse_finit_conf(FINIT_CONF);

	/*
	 * Load plugins.  Must run after finit.conf has registered
	 * all services, or service plugins won't have anything to
	 * hook on to.
	 */
	print_desc("Loading plugins", NULL);
	print_result(plugin_load_all(PLUGIN_PATH));

	/*
	 * Mount filesystems
	 */
#ifdef REMOUNT_ROOTFS_RW
	run("/bin/mount -n -o remount,rw /");
#endif
#ifdef SYSROOT
	run(SYSROOT, "/", NULL, MS_MOVE, NULL);
#endif

	_d("Root FS up, calling hooks ...");
	plugin_run_hooks(HOOK_ROOTFS_UP);

	umask(0);
	run("/bin/mount -na");
	run("/sbin/swapon -ea");
	umask(0022);

	/* Cleanup stale files, if any still linger on. */
	run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories");

	/* Base FS up, enable standard SysV init signals */
	sig_setup();

	_d("Base FS up, calling hooks ...");
	plugin_run_hooks(HOOK_BASEFS_UP);

	/*
	 * Start all bootstrap tasks, no network available!
	 */
	svc_bootstrap();

	/*
	 * Network stuff
	 */

	/* Setup kernel specific settings, e.g. allow broadcast ping, etc. */
	run("/sbin/sysctl -e -p /etc/sysctl.conf >/dev/null");

	/* Set initial hostname. */
	set_hostname(hostname);

	ifconfig("lo", "127.0.0.1", "255.0.0.0", 1);
	if (network)
		run_interactive(network, "Starting networking: %s", network);
	umask(022);

	/* Hooks that rely on loopback, or basic networking being up. */
	plugin_run_hooks(HOOK_NETWORK_UP);

	/*
	 * Start all tasks/services in the configured runlevel
	 */
	svc_runlevel(cfglevel);

	_d("Running svc up hooks ...");
	plugin_run_hooks(HOOK_SVC_UP);

	/*
	 * Run startup scripts in /etc/finit.d/, if any.
	 */
	if (rcsd && fisdir(rcsd)) {
		_d("Running startup scripts in %s ...", rcsd);
		run_parts(rcsd, NULL);
	}

	/* Hooks that should run at the very end */
	plugin_run_hooks(HOOK_SYSTEM_UP);

	/*
	 * Enter main loop to monior /dev/initctl and services
	 */
	return run_loop();
}
Пример #10
0
/**
 * service_runlevel - Change to a new runlevel
 * @newlevel: New runlevel to activate
 *
 * Stops all services not in @newlevel and starts, or lets continue to run,
 * those in @newlevel.  Also updates @prevlevel and active @runlevel.
 */
void service_runlevel(int newlevel)
{
	svc_t *svc;

	if (runlevel == newlevel)
		return;

	if (newlevel < 0 || newlevel > 9)
		return;

	prevlevel = runlevel;
	runlevel  = newlevel;

	_d("Setting new runlevel --> %d <-- previous %d", runlevel, prevlevel);
	runlevel_set(prevlevel, newlevel);

	/* Make sure to (re)load all *.conf in /etc/finit.d/ */
	conf_reload_dynamic();

	_d("Stopping services services not allowed in new runlevel ...");
	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		if (!svc_in_runlevel(svc, runlevel)) {
#ifndef INETD_DISABLED
			if (svc_is_inetd(svc))
				inetd_stop(&svc->inetd);
			else
#endif
				service_stop(svc);
		}

		/* ... or disabled/removed services from /etc/finit.d/ */
		if (svc_is_dynamic(svc) && svc_is_changed(svc))
			service_stop(svc);
	}

	/* Prev runlevel services stopped, call hooks before starting new runlevel ... */
	_d("All services have been stoppped, calling runlevel change hooks ...");
	plugin_run_hooks(HOOK_RUNLEVEL_CHANGE);  /* Reconfigure HW/VLANs/etc here */

	_d("Starting services services new to this runlevel ...");
	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
#ifndef INETD_DISABLED
		/* Inetd services have slightly different semantics */
		if (svc_is_inetd(svc)) {
			if (svc_in_runlevel(svc, runlevel))
				inetd_start(&svc->inetd);

			continue;
		}
#endif

		/* All other services consult their callback here */
		svc_dance(svc);
	}

	/* Cleanup stale services */
	svc_clean_dynamic(service_unregister);

	if (0 == runlevel) {
		do_shutdown(SIGUSR2);
		return;
	}
	if (6 == runlevel) {
		do_shutdown(SIGUSR1);
		return;
	}

	if (runlevel == 1)
		touch("/etc/nologin");	/* Disable login in single-user mode */
	else
		erase("/etc/nologin");

	if (0 != prevlevel)
		tty_runlevel(runlevel);
}
Пример #11
0
int main(int UNUSED(args), char *argv[])
{
	/*
	 * Initial setup of signals, ignore all until we're up.
	 */
	sig_init();

	/*
	 * Mount base file system, kernel is assumed to run devtmpfs for /dev
	 */
	chdir("/");
	umask(0);
	mount("none", "/proc", "proc", 0, NULL);
	mount("none", "/proc/bus/usb", "usbfs", 0, NULL);
	mount("none", "/sys", "sysfs", 0, NULL);
	mkdir("/dev/pts", 0755);
	mkdir("/dev/shm", 0755);
	mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620");
	mount("none", "/dev/shm", "tmpfs", 0, NULL);
	umask(022);

	/*
	 * Parse kernel parameters
	 */
	parse_kernel_cmdline();

	cls();
	echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")");

	/*
	 * Populate /dev and prepare for runtime events from kernel.
	 */
#if defined(USE_UDEV)
	run_interactive("udevd --daemon", "Populating device tree");
#elif defined (MDEV)
	run_interactive(MDEV " -s", "Populating device tree");
#endif

	/*
	 * Parse configuration file
	 */
	parse_finit_conf(FINIT_CONF);

	/*
	 * Load plugins.  Must run after finit.conf has registered
	 * all services, or service plugins won't have anything to
	 * hook on to.
	 */
	print_desc("", "Loading plugins");
	print_result(plugin_load_all(PLUGIN_PATH));

	/*
	 * Mount filesystems
	 */
	_d("Mount filesystems in /etc/fstab ...");

#ifdef REMOUNT_ROOTFS_RW
	run("/bin/mount -n -o remount,rw /");
#endif
#ifdef SYSROOT
	run(SYSROOT, "/", NULL, MS_MOVE, NULL);
#endif
	_d("Root FS up, calling hooks ...");
	plugin_run_hooks(HOOK_ROOTFS_UP);

	umask(0);
	run("/bin/mount -na");
	run("/sbin/swapon -ea");
	umask(0022);

	/* Cleanup stale files, if any still linger on. */
	run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories");

	/*
	 * Base FS up, enable standard SysV init signals
	 */
	sig_setup();

	_d("Base FS up, calling hooks ...");
	plugin_run_hooks(HOOK_BASEFS_UP);

	/*
	 * Network stuff
	 */

	/* Setup kernel specific settings, e.g. allow broadcast ping, etc. */
	run("/sbin/sysctl -e -p /etc/sysctl.conf >/dev/null");

	/* Set initial hostname. */
	set_hostname(hostname);

	ifconfig("lo", "127.0.0.1", "255.0.0.0", 1);
	if (network)
		run_interactive(network, "Starting networking: %s", network);
	umask(022);

	/*
	 * Hooks that rely on loopback, or basic networking being up.
	 */
	plugin_run_hooks(HOOK_NETWORK_UP);

	/*
	 * Start service monitor framework
	 */
	_d("Starting all static services from %s", FINIT_CONF);
	svc_start_all();

	/*
	 * Run startup scripts in /etc/finit.d/, if any.
	 */
	if (rcsd && fisdir(rcsd)) {
		_d("Running startup scripts in %s ...", rcsd);
		run_parts(rcsd, NULL);
	}

	/*
	 * Hooks that should run at the very end
	 */
	plugin_run_hooks(HOOK_SYSTEM_UP);

	/* Start GETTY on console */
	_d("Starting getty on console ...");
	run_getty(GETTY, argv);

	/*
	 * Enter main loop to monior /dev/initctl and services
	 */
	_d("Entering main loop ...");
	return run_loop();
}