static DBusHandlerResult dsme_dbus_filter(DBusConnection *con, DBusMessage *msg, void *aptr) { if( dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected") ) { dsme_log(LOG_CRIT, "Disconnected from system bus; terminating"); dsme_exit(EXIT_FAILURE); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
static void start_delayed_shutdown_timer(unsigned seconds) { if (!delayed_shutdown_timer) { stop_delayed_runlevel_timers(); if (!(delayed_shutdown_timer = dsme_create_timer(seconds, delayed_shutdown_fn, NULL))) { dsme_log(LOG_CRIT, PFIX"Could not create a shutdown timer; exit!"); dsme_exit(EXIT_FAILURE); return; } dsme_log(LOG_NOTICE, PFIX"Shutdown or reboot in %i seconds", seconds); } }
static bool start_delayed_user_timer(unsigned seconds) { bool success = false; if (!delayed_shutdown_timer && !delayed_actdead_timer && !delayed_user_timer) { if (!(delayed_user_timer = dsme_create_timer(seconds, delayed_user_fn, NULL))) { dsme_log(LOG_CRIT, PFIX"Could not create a user timer; exit!"); dsme_exit(EXIT_FAILURE); return false; } success = true; dsme_log(LOG_NOTICE, PFIX"User in %i seconds", seconds); } return success; }
/* * 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); }