[systemd-commits] man/logind.conf.xml src/login

Lennart Poettering lennart at kemper.freedesktop.org
Wed Sep 19 04:23:41 PDT 2012


 man/logind.conf.xml                        |   84 ++++++++-------
 src/login/logind-button.c                  |  159 ++++++++---------------------
 src/login/logind-button.h                  |   12 +-
 src/login/logind-dbus.c                    |   23 ++--
 src/login/logind-gperf.gperf               |   25 ++--
 src/login/logind-inhibit.c                 |   63 ++++++++---
 src/login/logind-inhibit.h                 |    7 -
 src/login/logind.c                         |   21 ++-
 src/login/logind.conf                      |    9 +
 src/login/logind.h                         |    4 
 src/login/org.freedesktop.login1.policy.in |   48 ++++++--
 11 files changed, 239 insertions(+), 216 deletions(-)

New commits:
commit beaafb2ea6be591882aef21fe19b88e3b2461087
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 13:10:10 2012 +0200

    logind: rework power key/suspend key/lid switch handling
    
    http://lists.freedesktop.org/archives/systemd-devel/2012-September/006604.html
    https://bugzilla.gnome.org/show_bug.cgi?id=680689
    
    This changes the meaning of the
    HandlePowerKey=/HandleSleepKey=/HandleLidSwitch= setting of logind.conf

diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 304f570..ccfc4ab 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -204,49 +204,57 @@
                                 <listitem><para>Controls whether
                                 logind shall handle the system power
                                 and sleep keys and the lid switch to
-                                trigger system power-off or
-                                suspend. Can be one of
-                                <literal>off</literal>,
-                                <literal>no-session</literal>,
-                                <literal>tty-session</literal>,
-                                <literal>any-session</literal> and
-                                <literal>always</literal>. If
-                                <literal>off</literal> logind will
-                                never handle these keys. If
-                                <literal>no-session</literal> logind
-                                will handle these keys when no user is
-                                logged in and no inhibitor lock is
-                                taken, and trigger a warning beep
-                                otherwise. If set to
-                                <literal>tty-session</literal> logind
-                                will handle these keys if no inhibitor
-                                lock is taken, and either no user is
-                                logged in or the foreground session is
-                                a text login and the only one
-                                existing. If
-                                <literal>any-session</literal> is set
-                                logind will handle these keys if no
-                                inhibitor lock is taken, and either no
-                                user is logged in or the foreground
-                                session is the only one existing
-                                (regardless whether graphical or
-                                text). If set to
-                                <literal>always</literal> logind will
-                                handle these keys in any case, even if
-                                one or more users are logged in or an
-                                inhibitor lock is taken. Only input
-                                devices with the
+                                trigger actions such as system
+                                power-off or suspend. Can be one of
+                                <literal>ignore</literal>,
+                                <literal>poweroff</literal>,
+                                <literal>reboot</literal>,
+                                <literal>halt</literal>,
+                                <literal>kexec</literal> and
+                                <literal>hibernate</literal>. If
+                                <literal>ignore</literal> logind will
+                                never handle these keys. Otherwise the
+                                specified action will be taken in the
+                                respective event. Only input devices
+                                with the
                                 <literal>power-switch</literal> udev
-                                tag will be watched for key
+                                tag will be watched for key/lid switch
                                 events. <varname>HandlePowerKey=</varname>
                                 defaults to
-                                <literal>no-session</literal>.
-                                <varname>HandleSleepKey=</varname>
-                                defaults to
-                                <literal>tty-session</literal>,
+                                <literal>poweroff</literal>.
+                                <varname>HandleSleepKey=</varname> and
                                 <varname>HandleLidSwitch=</varname>
+                                default to
+                                <literal>suspend</literal>.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>PowerKeyIgnoreInhibited=</varname></term>
+                                <term><varname>SleepKeyIgnoreInhibited=</varname></term>
+                                <term><varname>LidSwitchIgnoreInhibited=</varname></term>
+
+                                <listitem><para>Controls whether
+                                actions triggered by the power and
+                                sleep keys and the lid switch are
+                                subject to inhibitor locks. These
+                                settings take boolean arguments. If
+                                <literal>off</literal> the inhibitor
+                                locks taken by applications in order
+                                to block the requested operation are
+                                respected, if <literal>on</literal>
+                                the requested operation is executed in
+                                any
+                                case. <varname>PowerKeyIgnoreInhibited=</varname>
+                                and
+                                <varname>SleepKeyIgnoreInhibited=</varname>
+                                defaults to <literal>off</literal>,
+                                <varname>LidSwitchIgnoreInhibited=</varname>
                                 defaults to
-                                <literal>off</literal>.</para></listitem>
+                                <literal>yes</literal>. This means
+                                that the lid switch does not respect
+                                suspend blockers by default, but the
+                                power and sleep keys do.
+                                </para></listitem>
                         </varlistentry>
 
                 </variablelist>
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index d023294..7cb3f38 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -150,127 +150,60 @@ fail:
         return r;
 }
 
-static Session *button_get_session(Button *b) {
-        Seat *seat;
-        assert(b);
-
-        if (!b->seat)
-                return NULL;
+static int button_handle(Button *b, InhibitWhat inhibit_key, HandleButton handle, bool ignore_inhibited) {
+
+        static const char * const message_table[_HANDLE_BUTTON_MAX] = {
+                [HANDLE_POWEROFF] = "Powering Off...",
+                [HANDLE_REBOOT] = "Rebooting...",
+                [HANDLE_HALT] = "Halting...",
+                [HANDLE_KEXEC] = "Rebooting via kexec...",
+                [HANDLE_SUSPEND] = "Suspending...",
+                [HANDLE_HIBERNATE] = "Hibernating..."
+        };
+
+        static const char * const target_table[_HANDLE_BUTTON_MAX] = {
+                [HANDLE_POWEROFF] = "poweroff.target",
+                [HANDLE_REBOOT] = "reboot.target",
+                [HANDLE_HALT] = "halt.target",
+                [HANDLE_KEXEC] = "kexec.target",
+                [HANDLE_SUSPEND] = "suspend.target",
+                [HANDLE_HIBERNATE] = "hibernate.target"
+        };
 
-        seat = hashmap_get(b->manager->seats, b->seat);
-        if (!seat)
-                return NULL;
-
-        return seat->active;
-}
-
-static int button_power_off(Button *b, HandleButton handle) {
         DBusError error;
         int r;
+        InhibitWhat inhibit_operation;
 
         assert(b);
 
-        if (handle == HANDLE_OFF)
+        /* If the key handling is turned off, don't do anything */
+        if (handle == HANDLE_IGNORE) {
+                log_debug("Refusing key handling, as it is turned off.");
                 return 0;
-
-        if (handle == HANDLE_NO_SESSION) {
-                if (hashmap_size(b->manager->sessions) > 0) {
-                        log_error("Refusing power-off, user is logged in.");
-                        warn_melody();
-                        return -EPERM;
-                }
-
-        } else if (handle == HANDLE_TTY_SESSION ||
-                   handle == HANDLE_ANY_SESSION) {
-                unsigned n;
-                Session *s;
-
-                n = hashmap_size(b->manager->sessions);
-                s = button_get_session(b);
-
-                /* Silently ignore events of graphical sessions */
-                if (handle == HANDLE_TTY_SESSION &&
-                    s && s->type == SESSION_X11)
-                        return 0;
-
-                if (n > 1 || (n == 1 && !s)) {
-                        log_error("Refusing power-off, other user is logged in.");
-                        warn_melody();
-                        return -EPERM;
-                }
-
-        }
-
-        if (handle != HANDLE_ALWAYS) {
-                if (manager_is_inhibited(b->manager, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL)) {
-                        log_error("Refusing power-off, shutdown is inhibited.");
-                        warn_melody();
-                        return -EPERM;
-                }
         }
 
-        log_info("Powering off...");
-
-        dbus_error_init(&error);
-        r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN, &error);
-        if (r < 0) {
-                log_error("Failed to power off: %s", bus_error_message(&error));
-                dbus_error_free(&error);
-        }
-
-        return r;
-}
-
-static int button_suspend(Button *b, HandleButton handle) {
-        DBusError error;
-        int r;
-
-        assert(b);
-
-        if (handle == HANDLE_OFF)
+        /* If the key handling is inhibited, don't do anything */
+        if (manager_is_inhibited(b->manager, inhibit_key, INHIBIT_BLOCK, NULL, true)) {
+                log_debug("Refusing key handling, %s is inhibited.", inhibit_what_to_string(inhibit_key));
                 return 0;
-
-        if (handle == HANDLE_NO_SESSION) {
-                if (hashmap_size(b->manager->sessions) > 0) {
-                        log_error("Refusing suspend, user is logged in.");
-                        warn_melody();
-                        return -EPERM;
-                }
-
-        } else if (handle == HANDLE_TTY_SESSION ||
-                   handle == HANDLE_ANY_SESSION) {
-                unsigned n;
-                Session *s;
-
-                n = hashmap_size(b->manager->sessions);
-                s = button_get_session(b);
-
-                /* Silently ignore events of graphical sessions */
-                if (handle == HANDLE_TTY_SESSION &&
-                    s && s->type == SESSION_X11)
-                        return 0;
-
-                if (n > 1 || (n == 1 && !s)) {
-                        log_error("Refusing suspend, other user is logged in.");
-                        warn_melody();
-                        return -EPERM;
-                }
         }
 
-        if (handle != HANDLE_ALWAYS) {
-                if (manager_is_inhibited(b->manager, INHIBIT_SLEEP, INHIBIT_BLOCK, NULL)) {
-                        log_error("Refusing suspend, sleeping is inhibited.");
-                        warn_melody();
-                        return -EPERM;
-                }
+        inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
+
+        /* If the actual operation is inhibited, warn and fail */
+        if (!ignore_inhibited &&
+            manager_is_inhibited(b->manager, inhibit_operation, INHIBIT_BLOCK, NULL, false)) {
+                log_error("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_operation));
+                warn_melody();
+                return -EPERM;
         }
 
-        log_info("Suspending...");
+        log_info("%s", message_table[handle]);
 
         dbus_error_init(&error);
-        r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_SUSPEND_TARGET, INHIBIT_SLEEP, &error);
+        r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, target_table[handle], inhibit_operation, &error);
         if (r < 0) {
-                log_error("Failed to suspend: %s", bus_error_message(&error));
+                log_error("Failed to execute operation: %s", bus_error_message(&error));
                 dbus_error_free(&error);
         }
 
@@ -296,12 +229,12 @@ int button_process(Button *b) {
                 case KEY_POWER:
                 case KEY_POWER2:
                         log_info("Power key pressed.");
-                        return button_power_off(b, b->manager->handle_power_key);
+                        return button_handle(b, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited);
 
                 case KEY_SLEEP:
                 case KEY_SUSPEND:
                         log_info("Sleep key pressed.");
-                        return button_suspend(b, b->manager->handle_sleep_key);
+                        return button_handle(b, INHIBIT_HANDLE_SLEEP_KEY, b->manager->handle_sleep_key, b->manager->sleep_key_ignore_inhibited);
 
                 }
         } else if (ev.type == EV_SW && ev.value > 0) {
@@ -310,7 +243,7 @@ int button_process(Button *b) {
 
                 case SW_LID:
                         log_info("Lid closed.");
-                        return button_suspend(b, b->manager->handle_lid_switch);
+                        return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited);
                 }
         }
 
@@ -318,11 +251,13 @@ int button_process(Button *b) {
 }
 
 static const char* const handle_button_table[_HANDLE_BUTTON_MAX] = {
-        [HANDLE_OFF] = "off",
-        [HANDLE_NO_SESSION] = "no-session",
-        [HANDLE_TTY_SESSION] = "tty-session",
-        [HANDLE_ANY_SESSION] = "any-session",
-        [HANDLE_ALWAYS] = "always"
+        [HANDLE_IGNORE] = "ignore",
+        [HANDLE_POWEROFF] = "poweroff",
+        [HANDLE_REBOOT] = "reboot",
+        [HANDLE_HALT] = "halt",
+        [HANDLE_KEXEC] = "kexec",
+        [HANDLE_SUSPEND] = "suspend",
+        [HANDLE_HIBERNATE] = "hibernate"
 };
 DEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting");
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
index 7518d05..dd6582e 100644
--- a/src/login/logind-button.h
+++ b/src/login/logind-button.h
@@ -25,11 +25,13 @@
 typedef struct Button Button;
 
 typedef enum HandleButton {
-        HANDLE_OFF,
-        HANDLE_NO_SESSION,   /* Only handle key when nobody is logged in; honour inhibitors */
-        HANDLE_TTY_SESSION,  /* Only handle key when nobody is logged in, or the fg session is the only one and non-graphical; honour inhibitors */
-        HANDLE_ANY_SESSION,  /* Only handle key when nobody is logged in, or the fg session is the only one; honour inhibtors */
-        HANDLE_ALWAYS,       /* Always handle, ignore sessions; ignore inhibitors */
+        HANDLE_IGNORE,
+        HANDLE_POWEROFF,
+        HANDLE_REBOOT,
+        HANDLE_HALT,
+        HANDLE_KEXEC,
+        HANDLE_SUSPEND,
+        HANDLE_HIBERNATE,
         _HANDLE_BUTTON_MAX,
         _HANDLE_BUTTON_INVALID = -1
 } HandleButton;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 4f180b0..4ae5ba7 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -722,10 +722,19 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa
                 goto fail;
         }
 
+        /* Delay is only supported for shutdown/sleep */
+        if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) {
+                r = -EINVAL;
+                goto fail;
+        }
+
         r = verify_polkit(connection, message,
-                          w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
-                          w == INHIBIT_SLEEP    ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
-                                                  (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-idle"     : "org.freedesktop.login1.inhibit-delay-idle"),
+                          w == INHIBIT_SHUTDOWN         ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
+                          w == INHIBIT_SLEEP            ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
+                          w == INHIBIT_IDLE             ? "org.freedesktop.login1.inhibit-block-idle" :
+                          w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
+                          w == INHIBIT_HANDLE_SLEEP_KEY ? "org.freedesktop.login1.inhibit-handle-sleep-key" :
+                                                          "org.freedesktop.login1.inhibit-handle-lid-switch",
                           false, NULL, error);
         if (r < 0)
                 goto fail;
@@ -1079,7 +1088,7 @@ static int bus_manager_can_shutdown_or_sleep(
                 return r;
 
         multiple_sessions = r > 0;
-        blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+        blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
 
         if (multiple_sessions) {
                 r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
@@ -1193,7 +1202,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(
 
         delayed =
                 m->inhibit_delay_max > 0 &&
-                manager_is_inhibited(m, w, INHIBIT_DELAY, NULL);
+                manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false);
 
         if (delayed)
                 /* Shutdown is delayed, keep in mind what we
@@ -1261,7 +1270,7 @@ static int bus_manager_do_shutdown_or_sleep(
                 return r;
 
         multiple_sessions = r > 0;
-        blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+        blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
 
         if (multiple_sessions) {
                 r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
@@ -2294,7 +2303,7 @@ int manager_dispatch_delayed(Manager *manager) {
         /* Continue delay? */
         delayed =
                 manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
-                manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL);
+                manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false);
         if (delayed)
                 return 0;
 
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index f12718c..412dbb5 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -14,14 +14,17 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Login.NAutoVTs,          config_parse_unsigned, 0, offsetof(Manager, n_autovts)
-Login.ReserveVT,         config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
-Login.KillUserProcesses, config_parse_bool,     0, offsetof(Manager, kill_user_processes)
-Login.KillOnlyUsers,     config_parse_strv,     0, offsetof(Manager, kill_only_users)
-Login.KillExcludeUsers,  config_parse_strv,     0, offsetof(Manager, kill_exclude_users)
-Login.Controllers,       config_parse_strv,     0, offsetof(Manager, controllers)
-Login.ResetControllers,  config_parse_strv,     0, offsetof(Manager, reset_controllers)
-Login.InhibitDelayMaxSec,config_parse_usec,     0, offsetof(Manager, inhibit_delay_max)
-Login.HandlePowerKey,    config_parse_handle_button, 0, offsetof(Manager, handle_power_key)
-Login.HandleSleepKey,    config_parse_handle_button, 0, offsetof(Manager, handle_sleep_key)
-Login.HandleLidSwitch,   config_parse_handle_button, 0, offsetof(Manager, handle_lid_switch)
+Login.NAutoVTs,                 config_parse_unsigned,      0, offsetof(Manager, n_autovts)
+Login.ReserveVT,                config_parse_unsigned,      0, offsetof(Manager, reserve_vt)
+Login.KillUserProcesses,        config_parse_bool,          0, offsetof(Manager, kill_user_processes)
+Login.KillOnlyUsers,            config_parse_strv,          0, offsetof(Manager, kill_only_users)
+Login.KillExcludeUsers,         config_parse_strv,          0, offsetof(Manager, kill_exclude_users)
+Login.Controllers,              config_parse_strv,          0, offsetof(Manager, controllers)
+Login.ResetControllers,         config_parse_strv,          0, offsetof(Manager, reset_controllers)
+Login.InhibitDelayMaxSec,       config_parse_usec,          0, offsetof(Manager, inhibit_delay_max)
+Login.HandlePowerKey,           config_parse_handle_button, 0, offsetof(Manager, handle_power_key)
+Login.HandleSleepKey,           config_parse_handle_button, 0, offsetof(Manager, handle_sleep_key)
+Login.HandleLidSwitch,          config_parse_handle_button, 0, offsetof(Manager, handle_lid_switch)
+Login.PowerKeyIgnoreInhibited,  config_parse_bool,          0, offsetof(Manager, power_key_ignore_inhibited)
+Login.SleepKeyIgnoreInhibited,  config_parse_bool,          0, offsetof(Manager, sleep_key_ignore_inhibited)
+Login.LidSwitchIgnoreInhibited, config_parse_bool,          0, offsetof(Manager, lid_switch_ignore_inhibited)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 60b6237..6acc5c8 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -348,7 +348,24 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
         return what;
 }
 
-bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since) {
+static int pid_is_active(Manager *m, pid_t pid) {
+        Session *s;
+        int r;
+
+        r = manager_get_session_by_pid(m, pid, &s);
+        if (r <= 0)
+                return r;
+
+        return session_is_active(s);
+}
+
+bool manager_is_inhibited(
+                Manager *m,
+                InhibitWhat w,
+                InhibitMode mm,
+                dual_timestamp *since,
+                bool only_active) {
+
         Inhibitor *i;
         Iterator j;
         struct dual_timestamp ts = { 0, 0 };
@@ -364,6 +381,9 @@ bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timest
                 if (i->mode != mm)
                         continue;
 
+                if (only_active && pid_is_active(m, i->pid) <= 0)
+                        continue;
+
                 if (!inhibited ||
                     i->since.monotonic < ts.monotonic)
                         ts = i->since;
@@ -378,22 +398,32 @@ bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timest
 }
 
 const char *inhibit_what_to_string(InhibitWhat w) {
-
-        static const char* const table[_INHIBIT_WHAT_MAX] = {
-                [0] = "",
-                [INHIBIT_SHUTDOWN] = "shutdown",
-                [INHIBIT_SLEEP] = "sleep",
-                [INHIBIT_IDLE] = "idle",
-                [INHIBIT_SHUTDOWN|INHIBIT_SLEEP] = "shutdown:sleep",
-                [INHIBIT_SHUTDOWN|INHIBIT_IDLE] = "shutdown:idle",
-                [INHIBIT_SHUTDOWN|INHIBIT_SLEEP|INHIBIT_IDLE] = "shutdown:sleep:idle",
-                [INHIBIT_SLEEP|INHIBIT_IDLE] = "sleep:idle"
-        };
+        static __thread char buffer[73];
+        char *p;
 
         if (w < 0 || w >= _INHIBIT_WHAT_MAX)
                 return NULL;
 
-        return table[w];
+        p = buffer;
+        if (w & INHIBIT_SHUTDOWN)
+                p = stpcpy(p, "shutdown:");
+        if (w & INHIBIT_SLEEP)
+                p = stpcpy(p, "sleep:");
+        if (w & INHIBIT_IDLE)
+                p = stpcpy(p, "idle:");
+        if (w & INHIBIT_HANDLE_POWER_KEY)
+                p = stpcpy(p, "handle-power-key:");
+        if (w & INHIBIT_HANDLE_SLEEP_KEY)
+                p = stpcpy(p, "handle-sleep-key:");
+        if (w & INHIBIT_HANDLE_LID_SWITCH)
+                p = stpcpy(p, "handle-lid-switch:");
+
+        if (p > buffer)
+                *(p-1) = 0;
+        else
+                *p = 0;
+
+        return buffer;
 }
 
 InhibitWhat inhibit_what_from_string(const char *s) {
@@ -408,12 +438,17 @@ InhibitWhat inhibit_what_from_string(const char *s) {
                         what |= INHIBIT_SLEEP;
                 else if (l == 4 && strncmp(w, "idle", l) == 0)
                         what |= INHIBIT_IDLE;
+                else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
+                        what |= INHIBIT_HANDLE_POWER_KEY;
+                else if (l == 16 && strncmp(w, "handle-sleep-key", l) == 0)
+                        what |= INHIBIT_HANDLE_SLEEP_KEY;
+                else if (l == 16 && strncmp(w, "handle-lid-switch", l) == 0)
+                        what |= INHIBIT_HANDLE_LID_SWITCH;
                 else
                         return _INHIBIT_WHAT_INVALID;
         }
 
         return what;
-
 }
 
 static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index e72536f..d89a1b3 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -31,7 +31,10 @@ typedef enum InhibitWhat {
         INHIBIT_SHUTDOWN = 1,
         INHIBIT_SLEEP = 2,
         INHIBIT_IDLE = 4,
-        _INHIBIT_WHAT_MAX = 8,
+        INHIBIT_HANDLE_POWER_KEY = 8,
+        INHIBIT_HANDLE_SLEEP_KEY = 16,
+        INHIBIT_HANDLE_LID_SWITCH = 32,
+        _INHIBIT_WHAT_MAX = 64,
         _INHIBIT_WHAT_INVALID = -1
 } InhibitWhat;
 
@@ -80,7 +83,7 @@ int inhibitor_create_fifo(Inhibitor *i);
 void inhibitor_remove_fifo(Inhibitor *i);
 
 InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm);
-bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since);
+bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool only_active);
 
 const char *inhibit_what_to_string(InhibitWhat k);
 InhibitWhat inhibit_what_from_string(const char *s);
diff --git a/src/login/logind.c b/src/login/logind.c
index 3f71f5b..e22f68d 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -55,9 +55,10 @@ Manager *manager_new(void) {
         m->n_autovts = 6;
         m->reserve_vt = 6;
         m->inhibit_delay_max = 5 * USEC_PER_SEC;
-        m->handle_power_key = HANDLE_NO_SESSION;
-        m->handle_sleep_key = HANDLE_TTY_SESSION;
-        m->handle_lid_switch = HANDLE_OFF;
+        m->handle_power_key = HANDLE_POWEROFF;
+        m->handle_sleep_key = HANDLE_SUSPEND;
+        m->handle_lid_switch = HANDLE_SUSPEND;
+        m->lid_switch_ignore_inhibited = true;
 
         m->devices = hashmap_new(string_hash_func, string_compare_func);
         m->seats = hashmap_new(string_hash_func, string_compare_func);
@@ -494,9 +495,9 @@ int manager_enumerate_buttons(Manager *m) {
 
         /* Loads buttons from udev */
 
-        if (m->handle_power_key == HANDLE_OFF &&
-            m->handle_sleep_key == HANDLE_OFF &&
-            m->handle_lid_switch == HANDLE_OFF)
+        if (m->handle_power_key == HANDLE_IGNORE &&
+            m->handle_sleep_key == HANDLE_IGNORE &&
+            m->handle_lid_switch == HANDLE_IGNORE)
                 return 0;
 
         e = udev_enumerate_new(m->udev);
@@ -1304,9 +1305,9 @@ static int manager_connect_udev(Manager *m) {
                 return -errno;
 
         /* Don't watch keys if nobody cares */
-        if (m->handle_power_key != HANDLE_OFF ||
-            m->handle_sleep_key != HANDLE_OFF ||
-            m->handle_lid_switch != HANDLE_OFF) {
+        if (m->handle_power_key != HANDLE_IGNORE ||
+            m->handle_sleep_key != HANDLE_IGNORE ||
+            m->handle_lid_switch != HANDLE_IGNORE) {
 
                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
                 if (!m->udev_button_monitor)
@@ -1406,7 +1407,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
 
         assert(m);
 
-        idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
+        idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false);
 
         HASHMAP_FOREACH(s, m->sessions, i) {
                 dual_timestamp k;
diff --git a/src/login/logind.conf b/src/login/logind.conf
index db5dde4..0ac02c0 100644
--- a/src/login/logind.conf
+++ b/src/login/logind.conf
@@ -16,6 +16,9 @@
 #Controllers=
 #ResetControllers=cpu
 #InhibitDelayMaxSec=5
-#HandlePowerKey=no-session
-#HandleSleepKey=tty-session
-#HandleLidSwitch=off
+#HandlePowerKey=poweroff
+#HandleSleepKey=suspend
+#HandleLidSwitch=suspend
+#PowerKeyIgnoreInhibited=no
+#SleepKeyIgnoreInhibited=no
+#LidSwitchIgnoreInhibited=yes
diff --git a/src/login/logind.h b/src/login/logind.h
index 8aa28a3..0b52bf7 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -102,6 +102,10 @@ struct Manager {
         HandleButton handle_power_key;
         HandleButton handle_sleep_key;
         HandleButton handle_lid_switch;
+
+        bool power_key_ignore_inhibited;
+        bool sleep_key_ignore_inhibited;
+        bool lid_switch_ignore_inhibited;
 };
 
 enum {
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 970adbe..8d991e4 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -20,7 +20,17 @@
                 <_description>Allow applications to inhibit system shutdown</_description>
                 <_message>Authentication is required to allow an application to inhibit system shutdown.</_message>
                 <defaults>
-                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-delay-shutdown">
+                <_description>Allow applications to delay system shutdown</_description>
+                <_message>Authentication is required to allow an application to delay system shutdown.</_message>
+                <defaults>
+                        <allow_any>yes</allow_any>
                         <allow_inactive>yes</allow_inactive>
                         <allow_active>yes</allow_active>
                 </defaults>
@@ -30,7 +40,17 @@
                 <_description>Allow applications to inhibit system sleep</_description>
                 <_message>Authentication is required to allow an application to inhibit system sleep.</_message>
                 <defaults>
-                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_any>no</allow_any>
+                        <allow_inactive>yes</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+        </action>
+
+        <action id="org.freedesktop.login1.inhibit-delay-sleep">
+                <_description>Allow applications to delay system sleep</_description>
+                <_message>Authentication is required to allow an application to delay system sleep.</_message>
+                <defaults>
+                        <allow_any>yes</allow_any>
                         <allow_inactive>yes</allow_inactive>
                         <allow_active>yes</allow_active>
                 </defaults>
@@ -46,31 +66,31 @@
                 </defaults>
         </action>
 
-        <action id="org.freedesktop.login1.inhibit-delay-shutdown">
-                <_description>Allow applications to delay system shutdown</_description>
-                <_message>Authentication is required to allow an application to delay system shutdown.</_message>
+        <action id="org.freedesktop.login1.inhibit-handle-power-key">
+                <_description>Allow applications to inhibit system handling of the power key</_description>
+                <_message>Authentication is required to allow an application to inhibit system handling of the power key.</_message>
                 <defaults>
-                        <allow_any>yes</allow_any>
+                        <allow_any>no</allow_any>
                         <allow_inactive>yes</allow_inactive>
                         <allow_active>yes</allow_active>
                 </defaults>
         </action>
 
-        <action id="org.freedesktop.login1.inhibit-delay-sleep">
-                <_description>Allow applications to delay system sleep</_description>
-                <_message>Authentication is required to allow an application to delay system sleep.</_message>
+        <action id="org.freedesktop.login1.inhibit-handle-sleep-key">
+                <_description>Allow applications to inhibit system handling of the sleep key</_description>
+                <_message>Authentication is required to allow an application to inhibit system handling of the sleep key.</_message>
                 <defaults>
-                        <allow_any>yes</allow_any>
+                        <allow_any>no</allow_any>
                         <allow_inactive>yes</allow_inactive>
                         <allow_active>yes</allow_active>
                 </defaults>
         </action>
 
-        <action id="org.freedesktop.login1.inhibit-delay-idle">
-                <_description>Allow applications to delay automatic system suspend</_description>
-                <_message>Authentication is required to allow an application to delay automatic system suspend.</_message>
+        <action id="org.freedesktop.login1.inhibit-handle-lid-switch">
+                <_description>Allow applications to inhibit system handling of the lid switch</_description>
+                <_message>Authentication is required to allow an application to inhibit system handling of the lid switch.</_message>
                 <defaults>
-                        <allow_any>yes</allow_any>
+                        <allow_any>no</allow_any>
                         <allow_inactive>yes</allow_inactive>
                         <allow_active>yes</allow_active>
                 </defaults>



More information about the systemd-commits mailing list