Ejemplo n.º 1
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();
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
static int client(int argc, char *argv[])
{
	int fd;
	int c;
	struct option long_options[] = {
		{"debug", 0, NULL, 'd'},
		{"help", 0, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};
	struct init_request rq = {
		.magic = INIT_MAGIC,
		.cmd = 0
	};

	while ((c = getopt_long (argc, argv, "h?d", long_options, NULL)) != EOF) {
		switch(c) {
		case 'd':
			rq.cmd = INIT_CMD_DEBUG;
			break;

		case 'h':
		case '?':
			return usage(0);
		default:
			return usage(1);
		}
	}

	if (!rq.cmd) {
		if (argc < 2) {
			fprintf(stderr, "Missing runlevel.\n");
			return 1;
		}

		rq.cmd = INIT_CMD_RUNLVL;
		rq.runlevel = (int)argv[1][0];
	}

	if (!fexist(FINIT_FIFO)) {
		fprintf(stderr, "/sbin/init does not support %s!\n", FINIT_FIFO);
		return 1;
	}

	fd = open(FINIT_FIFO, O_WRONLY);
	if (-1 == fd) {
		perror("Failed opening " FINIT_FIFO);
		return 1;
	}
	write(fd, &rq, sizeof(rq));
	close(fd);

	return 0;
}

static int run_loop(void)
{
	int delay = DELAY_TTY ?: 1;

	_d("Entering main loop ...");
	while (1) {
		svc_monitor();
		plugin_monitor();

		/* Delayed start of TTYs to let the system stabilize
		 * after switching runlevels. */
		if (delay) {
			if (--delay == 0)
				tty_runlevel(runlevel);
			continue;
		}
	}

	return 0;
}
Ejemplo n.º 4
0
/**
 * svc_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 svc_runlevel(int newlevel)
{
	svc_t *svc;

	if (runlevel == newlevel)
		return;

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

	prevlevel = runlevel;
	runlevel  = newlevel;
	utmp_save(prevlevel, newlevel);

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

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		svc_cmd_t cmd;

		/* Inetd services have slightly different semantics */
#ifndef INETD_DISABLED
		if (svc->type == SVC_CMD_INETD) {
			if (!ISSET(svc->runlevels, runlevel))
				inetd_stop(&svc->inetd);
			else
				inetd_start(&svc->inetd);

			continue;
		}
#endif

		/* All other services consult their callback here */
		cmd = svc_enabled(svc, 0, NULL);
		if (svc->pid) {
			if (cmd == SVC_STOP)
				svc_stop(svc);
			else if (cmd == SVC_RELOAD)
				svc_reload(svc);
		} else {
			if (cmd == SVC_START)
				svc_start(svc);
		}
	}

	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);
}