-static int nologin_timeout_handler(
- sd_event_source *s,
- uint64_t usec,
- void *userdata) {
-
- Manager *m = userdata;
- int r;
-
- log_info("Creating /run/nologin, blocking further logins...");
-
- r = write_string_file_atomic("/run/nologin", "System is going down.");
- if (r < 0)
- log_error_errno(r, "Failed to create /run/nologin: %m");
- else
- m->unlink_nologin = true;
-
- return 0;
-}
-
-static int update_schedule_file(Manager *m) {
-
- int r;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *t = NULL, *temp_path = NULL;
-
- assert(m);
-
- r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
-
- t = cescape(m->wall_message);
- if (!t)
- return log_oom();
-
- r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
- if (r < 0)
- return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
-
- (void) fchmod(fileno(f), 0644);
-
- fprintf(f,
- "USEC="USEC_FMT"\n"
- "WARN_WALL=%i\n"
- "MODE=%s\n",
- m->scheduled_shutdown_timeout,
- m->enable_wall_messages,
- m->scheduled_shutdown_type);
-
- if (!isempty(m->wall_message))
- fprintf(f, "WALL_MESSAGE=%s\n", t);
-
- (void) fflush_and_check(f);
-
- if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
- log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
- r = -errno;
-
- (void) unlink(temp_path);
- (void) unlink("/run/systemd/shutdown/scheduled");
- }
-
- return r;
-}
-
-static int manager_scheduled_shutdown_handler(
- sd_event_source *s,
- uint64_t usec,
- void *userdata) {
-
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- Manager *m = userdata;
- const char *target;
- int r;
-
- assert(m);
-
- if (isempty(m->scheduled_shutdown_type))
- return 0;
-
- if (streq(m->scheduled_shutdown_type, "halt"))
- target = SPECIAL_HALT_TARGET;
- else if (streq(m->scheduled_shutdown_type, "poweroff"))
- target = SPECIAL_POWEROFF_TARGET;
- else
- target = SPECIAL_REBOOT_TARGET;
-
- r = execute_shutdown_or_sleep(m, 0, target, &error);
- if (r < 0)
- return log_error_errno(r, "Unable to execute transition to %s: %m", target);
-
- return 0;
-}
-
-static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- const char *action_multiple_sessions = NULL;
- const char *action_ignore_inhibit = NULL;
- const char *action = NULL;
- uint64_t elapse;
- char *type;
- int r;
-
- assert(m);
- assert(message);
-
- r = sd_bus_message_read(message, "st", &type, &elapse);
- if (r < 0)
- return r;
-
- if (streq(type, "reboot")) {
- action = "org.freedesktop.login1.reboot";
- action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
- } else if (streq(type, "halt")) {
- action = "org.freedesktop.login1.halt";
- action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
- } else if (streq(type, "poweroff")) {
- action = "org.freedesktop.login1.poweroff";
- action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
- } else
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
-
- r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
- action, action_multiple_sessions, action_ignore_inhibit, error);
- if (r != 0)
- return r;
-
- if (m->scheduled_shutdown_timeout_source) {
- r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_time() failed: %m");
-
- r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
- } else {
- r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
- CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
- if (r < 0)
- return log_error_errno(r, "sd_event_add_time() failed: %m");
- }
-
- r = free_and_strdup(&m->scheduled_shutdown_type, type);
- if (r < 0) {
- m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
- return log_oom();
- }
-
- if (m->nologin_timeout_source) {
- r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_time() failed: %m");
-
- r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
- } else {
- r = sd_event_add_time(m->event, &m->nologin_timeout_source,
- CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
- if (r < 0)
- return log_error_errno(r, "sd_event_add_time() failed: %m");
- }
-
- m->scheduled_shutdown_timeout = elapse;
-
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
- if (r >= 0) {
- const char *tty;
-
- (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
- (void) sd_bus_creds_get_tty(creds, &tty);
-
- r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
- if (r < 0) {
- m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
- return log_oom();
- }
- }
-
- r = manager_setup_wall_message_timer(m);
- if (r < 0)
- return r;
-
- if (!isempty(type)) {
- r = update_schedule_file(m);
- if (r < 0)
- return r;
- } else
- (void) unlink("/run/systemd/shutdown/scheduled");
-
- return sd_bus_reply_method_return(message, NULL);
-}
-
-static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- bool cancelled;
-
- assert(m);
- assert(message);
-
- cancelled = m->scheduled_shutdown_type != NULL;
-
- m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
- m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
- m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
- free(m->scheduled_shutdown_type);
- m->scheduled_shutdown_type = NULL;
- m->scheduled_shutdown_timeout = 0;
-
- if (cancelled) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- const char *tty = NULL;
- uid_t uid = 0;
- int r;
-
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
- if (r >= 0) {
- (void) sd_bus_creds_get_uid(creds, &uid);
- (void) sd_bus_creds_get_tty(creds, &tty);
- }
-
- utmp_wall("The system shutdown has been cancelled",
- lookup_uid(uid), tty, logind_wall_tty_filter, m);
- }
-
- return sd_bus_reply_method_return(message, "b", cancelled);
-}
-
-static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {