/** * 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 */ }
/* * Assert condition only if the service is running, but not if it's * recently been changed or while it's starting up. * * We must wait for the service to create/touch its pidfile. */ static void pidfile_reconf(void *_null) { static char name[MAX_ARG_LEN]; svc_t *svc; (void)(_null); for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) { if (svc->state == SVC_RUNNING_STATE && !svc_is_changed(svc) && !svc_is_starting(svc)) { snprintf(name, MAX_ARG_LEN, "svc%s", svc->cmd); cond_set_path(cond_path(name), COND_ON); } } }
/* * 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; }
/** * service_stop_dynamic - Stop disabled/removed dynamic services * * We call it "stop", but in reality it could be "skip" as well, if the * service supports SIGHUP. This function is just one step on the road * to reload all modified 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) && svc->pid) { svc_state_t new_state = SVC_RELOAD_STATE; if (svc_is_removed(svc)) new_state = SVC_HALTED_STATE; if (!svc_has_sighup(svc)) dyn_stop_cnt++; _d("Marking service %s as state %d", svc->cmd, new_state); service_stop(svc, new_state); } } /* Check if we need to collect any services before calling user HOOK */ service_stop_done(NULL); }
/** * 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); }