/** * service_enabled - Should the service run? * @svc: Pointer to &svc_t object * @event: Dynamic event, opaque flag passed to callback * @arg: Event argument, used only by external service plugins. * * This method calls an associated service callback, if registered by a * plugin, and returns the &svc_cmd_t status. If no plugin is registered * the service is statically enabled in /etc/finit.conf and the result * will always be %SVC_START. * * Returns: * Either one of %SVC_START, %SVC_STOP, %SVC_RELOAD. */ svc_cmd_t service_enabled(svc_t *svc, int event, void *arg) { if (!svc) { errno = EINVAL; return SVC_STOP; } if (!svc_in_runlevel(svc, runlevel)) return SVC_STOP; /* * Event conditions for services are ignored during bootstrap. */ if (runlevel && !event_service_cond(svc->events)) return SVC_STOP; /* Is there a service plugin registered? */ if (svc->cb) { int status; pid_t pid; /* Let callback run in separate process so it doesn't crash PID 1 */ pid = fork(); if (-1 == pid) { _pe("Failed in %s callback", svc->cmd); return SVC_STOP; } if (!pid) { status = svc->cb(svc, event, arg); exit(status); } if (waitpid(pid, &status, 0) == -1) { _pe("Failed reading status from %s callback", svc->cmd); return SVC_STOP; } /* Callback normally exits here. */ if (WIFEXITED(status)) return WEXITSTATUS(status); /* Check for SEGFAULT or other error ... */ if (WIFSIGNALED(status) && WCOREDUMP(status)) _e("Callback to %s crashed!\n", svc->cmd); else _e("Callback to %s did not exit normally!\n", svc->cmd); return SVC_STOP; } /* No service plugin, default to start, since listed in finit.conf */ return SVC_START; }
/** * service_enabled - Should the service run? * @svc: Pointer to &svc_t object * @event: Dynamic event, opaque flag passed to callback * @arg: Event argument, used only by external service plugins. * * This method calls an associated service callback, if registered by a * plugin, and returns the &svc_cmd_t status. If no plugin is registered * the service is statically enabled in /etc/finit.conf and the result * will always be %SVC_START. * * Returns: * Either one of %SVC_START, %SVC_STOP, %SVC_RELOAD. */ svc_cmd_t service_enabled(svc_t *svc, int event, void *arg) { svc_cmd_t cmd = SVC_START; /* Default to start, since listed in finit.conf */ if (!svc) { errno = EINVAL; return SVC_STOP; } if (!svc_in_runlevel(svc, runlevel)) return SVC_STOP; /* * Event conditions for services are ignored during bootstrap. */ _d("Checking %s runlevel %d and events %s", svc->cmd, runlevel, svc->events); if (runlevel && !event_service_cond(svc->events)) return SVC_STOP; if (svc->state == SVC_RELOAD_STATE) cmd = SVC_RELOAD; if (svc->state == SVC_PAUSED_STATE) cmd = SVC_STOP; /* Is there a service plugin registered? */ if (svc->cb) { int status; pid_t pid; /* Let callback run in separate process so it doesn't crash PID 1 */ pid = fork(); if (-1 == pid) { _pe("Failed in %s callback", svc->cmd); return SVC_STOP; } if (!pid) _exit(svc->cb(svc, event, arg)); if (waitpid(pid, &status, 0) == -1) { _pe("Failed reading status from %s callback", svc->cmd); return SVC_STOP; } /* Callback normally exits here. */ if (WIFEXITED(status)) { svc_cmd_t tmp = WEXITSTATUS(status); return tmp == SVC_START ? cmd : tmp; } /* Check for SEGFAULT or other error ... */ if (WIFSIGNALED(status) && WCOREDUMP(status)) _e("Callback to %s crashed!\n", svc->cmd); else _e("Callback to %s did not exit normally!\n", svc->cmd); return SVC_STOP; } _d("%s => %s", svc->cmd, (cmd == SVC_START ? "SVC_START" : (cmd == SVC_RELOAD ? "SVC_RELOAD" : "SVC_STOP"))); return cmd; }