static int delayed_user_fn(void* unused) { change_runlevel(DSME_STATE_USER); delayed_user_timer = 0; return 0; /* stop the interval */ }
static int delayed_actdead_fn(void* unused) { change_runlevel(DSME_STATE_ACTDEAD); delayed_actdead_timer = 0; return 0; /* stop the interval */ }
/* * This function will do the shutdown or reboot (based on desired runlevel). * If the telinit is present, runlevel change is requested. * Otherwise function will shutdown/reboot by itself. * TODO: How to make sure runlevel transition work * TODO: Is checking telinit reliable enough? */ static void shutdown(dsme_runlevel_t runlevel) { char command[64]; if ((runlevel != DSME_RUNLEVEL_REBOOT) && (runlevel != DSME_RUNLEVEL_SHUTDOWN) && (runlevel != DSME_RUNLEVEL_MALF)) { dsme_log(LOG_WARNING, "Shutdown request to bad runlevel (%d)", runlevel); return; } dsme_log(LOG_NOTICE, runlevel == DSME_RUNLEVEL_SHUTDOWN ? "Shutdown" : runlevel == DSME_RUNLEVEL_REBOOT ? "Reboot" : "Malf"); /* If we have systemd, use systemctl commands */ if (access("/bin/systemctl", X_OK) == 0) { if (runlevel == DSME_RUNLEVEL_SHUTDOWN) { snprintf(command, sizeof(command), "/bin/systemctl --no-block poweroff"); } else if (runlevel == DSME_RUNLEVEL_REBOOT) { snprintf(command, sizeof(command), "/bin/systemctl --no-block reboot"); } else { dsme_log(LOG_WARNING, "MALF not supported by our systemd implementation"); goto fail_and_exit; } dsme_log(LOG_NOTICE, "Issuing %s", command); if (system(command) != 0) { dsme_log(LOG_WARNING, "command %s failed: %m", command); /* We ignore error. No retry or anything else */ } } /* If runlevel change fails, handle the shutdown/reboot by DSME */ else if (!change_runlevel(runlevel)) { dsme_log(LOG_CRIT, "Doing forced shutdown/reboot"); sync(); (void)remount_mmc_readonly(); if (runlevel == DSME_RUNLEVEL_SHUTDOWN || runlevel == DSME_RUNLEVEL_MALF) { if (access("/sbin/poweroff", X_OK) == 0) { snprintf(command, sizeof(command), "/sbin/poweroff"); } else { snprintf(command, sizeof(command), "/usr/sbin/poweroff"); } dsme_log(LOG_CRIT, "Issuing %s", command); if (system(command) != 0) { dsme_log(LOG_ERR, "%s failed, trying again in 3s", command); sleep(3); if (system(command) != 0) { dsme_log(LOG_ERR, "%s failed again", command); goto fail_and_exit; } } } else { if (access("/sbin/reboot", X_OK) == 0) { snprintf(command, sizeof(command), "/sbin/reboot"); } else { snprintf(command, sizeof(command), "/usr/sbin/reboot"); } dsme_log(LOG_CRIT, "Issuing %s", command); if (system(command) != 0) { dsme_log(LOG_ERR, "%s failed, trying again in 3s", command); sleep(3); if (system(command) != 0) { dsme_log(LOG_ERR, "%s failed again", command); goto fail_and_exit; } } } } return; fail_and_exit: dsme_log(LOG_CRIT, "Closing to clean-up!"); dsme_exit(EXIT_FAILURE); }
static void request_process(Server *s, const struct init_request *req) { assert(s); assert(req); if (req->magic != INIT_MAGIC) { log_error("Got initctl request with invalid magic. Ignoring."); return; } switch (req->cmd) { case INIT_CMD_RUNLVL: if (!isprint(req->runlevel)) log_error("Got invalid runlevel. Ignoring."); else switch (req->runlevel) { /* we are async anyway, so just use kill for reexec/reload */ case 'u': case 'U': if (kill(1, SIGTERM) < 0) log_error_errno(errno, "kill() failed: %m"); /* The bus connection will be * terminated if PID 1 is reexecuted, * hence let's just exit here, and * rely on that we'll be restarted on * the next request */ s->quit = true; break; case 'q': case 'Q': if (kill(1, SIGHUP) < 0) log_error_errno(errno, "kill() failed: %m"); break; default: change_runlevel(s, req->runlevel); } return; case INIT_CMD_POWERFAIL: case INIT_CMD_POWERFAILNOW: case INIT_CMD_POWEROK: log_warning("Received UPS/power initctl request. This is not implemented in systemd. Upgrade your UPS daemon!"); return; case INIT_CMD_CHANGECONS: log_warning("Received console change initctl request. This is not implemented in systemd."); return; case INIT_CMD_SETENV: case INIT_CMD_UNSETENV: log_warning("Received environment initctl request. This is not implemented in systemd."); return; default: log_warning("Received unknown initctl request. Ignoring."); return; } }
DSME_HANDLER(DSM_MSGTYPE_CHANGE_RUNLEVEL, conn, msg) { (void)change_runlevel(msg->runlevel); }