X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Felogind-dbus.c;h=a9b39c238835162535daefbf20e83c81ecd01154;hp=cf7f3dcb64443fc37684a2f02582e6f05cb663a2;hb=f49259fd34d5c401a177f69287c9eac883ae5c3a;hpb=3e6d9bb47a4f0f7b717de2691b1b962f65851869 diff --git a/src/login/elogind-dbus.c b/src/login/elogind-dbus.c index cf7f3dcb6..a9b39c238 100644 --- a/src/login/elogind-dbus.c +++ b/src/login/elogind-dbus.c @@ -22,8 +22,10 @@ #include "bus-error.h" #include "bus-util.h" #include "elogind-dbus.h" +#include "fd-util.h" #include "process-util.h" #include "sd-messages.h" +#include "sleep.h" #include "sleep-config.h" #include "string-util.h" #include "strv.h" @@ -31,25 +33,6 @@ #include "user-util.h" -int have_multiple_sessions( - Manager *m, - uid_t uid) { - - Session *session; - Iterator i; - - assert(m); - - /* Check for other users' sessions. Greeter sessions do not - * count, and non-login sessions do not count either. */ - HASHMAP_FOREACH(session, m->sessions, i) - if (session->class == SESSION_USER && - session->user->uid != uid) - return true; - - return false; -} - static int bus_manager_log_shutdown( Manager *m, InhibitWhat w, @@ -90,32 +73,55 @@ static int bus_manager_log_shutdown( p = strjoina(p, " (", m->wall_message, ")."); return log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, p, q, NULL); } -static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { +/* elogind specific helper to make HALT and REBOOT possible. */ +static int run_helper(const char *helper) { + int pid = fork(); + if (pid < 0) { + return log_error_errno(errno, "Failed to fork: %m"); + } - static const char * const signal_name[_INHIBIT_WHAT_MAX] = { - [INHIBIT_SHUTDOWN] = "PrepareForShutdown", - [INHIBIT_SLEEP] = "PrepareForSleep" - }; + if (pid == 0) { + /* Child */ - int active = _active; + close_all_fds(NULL, 0); + + execlp(helper, helper, NULL); + log_error_errno(errno, "Failed to execute %s: %m", helper); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_warn(helper, pid, true); +} + +/* elogind specific executor */ +static int shutdown_or_sleep(Manager *m, HandleAction action) { assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(signal_name[w]); - - return sd_bus_emit_signal(m->bus, - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - signal_name[w], - "b", - active); + + switch (action) { + case HANDLE_POWEROFF: + return run_helper(HALT); + case HANDLE_REBOOT: + return run_helper(REBOOT); + case HANDLE_HALT: + return run_helper(HALT); + case HANDLE_KEXEC: + return run_helper(KEXEC); + case HANDLE_SUSPEND: + return do_sleep("suspend", m->suspend_mode, m->suspend_state); + case HANDLE_HIBERNATE: + return do_sleep("hibernate", m->hibernate_mode, m->hibernate_state); + case HANDLE_HYBRID_SLEEP: + return do_sleep("hybrid-sleep", m->hybrid_sleep_mode, m->hybrid_sleep_state); + default: + return -EINVAL; + } } static int execute_shutdown_or_sleep( @@ -217,21 +223,6 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) { return 1; } -static int manager_inhibit_timeout_handler( - sd_event_source *s, - uint64_t usec, - void *userdata) { - - Manager *manager = userdata; - int r; - - assert(manager); - assert(manager->inhibit_timeout_source == s); - - r = manager_dispatch_delayed(manager, true); - return (r < 0) ? r : 0; -} - static int delay_shutdown_or_sleep( Manager *m, InhibitWhat w, @@ -303,68 +294,6 @@ int bus_manager_shutdown_or_sleep_now_or_later( return r; } -int verify_shutdown_creds( - Manager *m, - sd_bus_message *message, - InhibitWhat w, - bool interactive, - const char *action, - const char *action_multiple_sessions, - const char *action_ignore_inhibit, - sd_bus_error *error) { - - _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; - bool multiple_sessions, blocked; - uid_t uid; - int r; - - assert(m); - assert(message); - assert(w >= 0); - assert(w <= _INHIBIT_WHAT_MAX); - - r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); - if (r < 0) - return r; - - r = sd_bus_creds_get_euid(creds, &uid); - if (r < 0) - return r; - - r = have_multiple_sessions(m, uid); - if (r < 0) - return r; - - multiple_sessions = r > 0; - blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); - - if (multiple_sessions && action_multiple_sessions) { - r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error); - if (r < 0) - return r; - if (r == 0) - return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - } - - if (blocked && action_ignore_inhibit) { - r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error); - if (r < 0) - return r; - if (r == 0) - return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - } - - if (!multiple_sessions && !blocked && action) { - r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error); - if (r < 0) - return r; - if (r == 0) - return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - } - - return 0; -} - static int method_do_shutdown_or_sleep( Manager *m, sd_bus_message *message, @@ -404,11 +333,13 @@ static int method_do_shutdown_or_sleep( return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported"); } - r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions, - action_ignore_inhibit, error); - log_debug_elogind("verify_shutdown_creds() returned %d", r); - if (r != 0) - return r; + if (IN_SET(sleep_action, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) { + r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions, + action_ignore_inhibit, error); + log_debug_elogind("verify_shutdown_creds() returned %d", r); + if (r != 0) + return r; + } r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error); if (r < 0)