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