]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: rework logic to decide whether lock + idle + display applies to a session
authorLennart Poettering <lennart@poettering.net>
Wed, 29 Nov 2023 10:18:01 +0000 (11:18 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 11 Jan 2024 16:23:47 +0000 (17:23 +0100)
Let's streamline the logic that decides whether the screen lock, idle
timeout or display election mechanism applies to a session class. Let's
add explicitly SESSION_CLASS_IS_XYZ() macros for each, and then resue
them at all suitable places, and refuse any attempts to use the
functionality on the wrong clases with a friendly error message.

src/login/logind-core.c
src/login/logind-session-dbus.c
src/login/logind-session.c
src/login/logind-session.h
src/login/logind-user.c

index 26133ee6efceece88d6b716ff8b09ebb5aa814bf..582cbcbea84709873e5572fd60a22225cb6c4256 100644 (file)
@@ -413,6 +413,9 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
                 dual_timestamp k;
                 int ih;
 
+                if (!SESSION_CLASS_CAN_IDLE(s->class))
+                        continue;
+
                 ih = session_get_idle_hint(s, &k);
                 if (ih < 0)
                         return ih;
index 6da3dd59d5a0057940029117fe79e3a8b1ff5b38..d4e656ae85d031b7f3c64d6bfab7486b55c2776d 100644 (file)
@@ -216,7 +216,9 @@ int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_erro
         if (r == 0)
                 return 1; /* Will call us back */
 
-        r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
+        r = session_send_lock(s, /* lock= */ strstr(sd_bus_message_get_member(message), "Lock"));
+        if (r == -ENOTTY)
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Session does not support lock screen.");
         if (r < 0)
                 return r;
 
@@ -248,7 +250,7 @@ static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_
 
         r = session_set_idle_hint(s, b);
         if (r == -ENOTTY)
-                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical and non-user sessions.");
         if (r < 0)
                 return r;
 
@@ -278,7 +280,11 @@ static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bu
         if (uid != 0 && uid != s->user->user_record->uid)
                 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
 
-        session_set_locked_hint(s, b);
+        r = session_set_locked_hint(s, b);
+        if (r == -ENOTTY)
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Session does not support lock screen.");
+        if (r < 0)
+                return r;
 
         return sd_bus_reply_method_return(message, NULL);
 }
@@ -765,6 +771,9 @@ int session_send_lock(Session *s, bool lock) {
 
         assert(s);
 
+        if (!SESSION_CLASS_CAN_LOCK(s->class))
+                return -ENOTTY;
+
         p = session_bus_path(s);
         if (!p)
                 return -ENOMEM;
@@ -786,6 +795,9 @@ int session_send_lock_all(Manager *m, bool lock) {
         HASHMAP_FOREACH(session, m->sessions) {
                 int k;
 
+                if (!SESSION_CLASS_CAN_LOCK(session->class))
+                        continue;
+
                 k = session_send_lock(session, lock);
                 if (k < 0)
                         r = k;
index e9d95e1db8f97fe20fbe0dc144e0f64eb9d8faf1..3226f3db78376bd3034ed14ce6ac99b8c5c9e855 100644 (file)
@@ -1155,7 +1155,9 @@ found_atime:
 int session_set_idle_hint(Session *s, bool b) {
         assert(s);
 
-        if (!SESSION_TYPE_IS_GRAPHICAL(s->type))
+        if (!SESSION_CLASS_CAN_IDLE(s->class)) /* Only some session classes know the idle concept at all */
+                return -ENOTTY;
+        if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) /* And only graphical session types can set the field explicitly */
                 return -ENOTTY;
 
         if (s->idle_hint == b)
@@ -1181,15 +1183,20 @@ int session_get_locked_hint(Session *s) {
         return s->locked_hint;
 }
 
-void session_set_locked_hint(Session *s, bool b) {
+int session_set_locked_hint(Session *s, bool b) {
         assert(s);
 
+        if (!SESSION_CLASS_CAN_LOCK(s->class))
+                return -ENOTTY;
+
         if (s->locked_hint == b)
-                return;
+                return 0;
 
         s->locked_hint = b;
+        (void) session_save(s);
+        (void) session_send_changed(s, "LockedHint", NULL);
 
-        session_send_changed(s, "LockedHint", NULL);
+        return 1;
 }
 
 void session_set_type(Session *s, SessionType t) {
index 3cc416bf682f552bbf08beb63e49949d7ba8b201..9cba60c18f6aad637b7aa9b081f435d6e34b27e6 100644 (file)
@@ -45,6 +45,15 @@ typedef enum SessionClass {
 /* Which session classes can pin our user tracking? */
 #define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY))
 
+/* Which session classes decide whether system is idle? (should only cover sessions that have input, and are not idle screens themselves)*/
+#define SESSION_CLASS_CAN_IDLE(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER))
+
+/* Which session classes have a lock screen concept? */
+#define SESSION_CLASS_CAN_LOCK(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY))
+
+/* Which sessions are candidates to become "display" sessions */
+#define SESSION_CLASS_CAN_DISPLAY(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER))
+
 typedef enum SessionType {
         SESSION_UNSPECIFIED,
         SESSION_TTY,
@@ -158,7 +167,7 @@ bool session_is_active(Session *s);
 int session_get_idle_hint(Session *s, dual_timestamp *t);
 int session_set_idle_hint(Session *s, bool b);
 int session_get_locked_hint(Session *s);
-void session_set_locked_hint(Session *s, bool b);
+int session_set_locked_hint(Session *s, bool b);
 void session_set_type(Session *s, SessionType t);
 int session_set_display(Session *s, const char *display);
 int session_set_tty(Session *s, const char *tty);
index 6e41ac6ef60b3bf7f4b1b01d31b85ddda112bd88..6de7c47c7a77d67c25649d193e333ea99905a0d0 100644 (file)
@@ -591,6 +591,9 @@ int user_get_idle_hint(User *u, dual_timestamp *t) {
                 dual_timestamp k;
                 int ih;
 
+                if (!SESSION_CLASS_CAN_IDLE(s->class))
+                        continue;
+
                 ih = session_get_idle_hint(s, &k);
                 if (ih < 0)
                         return ih;
@@ -783,7 +786,7 @@ static bool elect_display_filter(Session *s) {
         /* Return true if the session is a candidate for the user’s ‘primary session’ or ‘display’. */
         assert(s);
 
-        return IN_SET(s->class, SESSION_USER, SESSION_GREETER) && s->started && !s->stopping;
+        return SESSION_CLASS_CAN_DISPLAY(s->class) && s->started && !s->stopping;
 }
 
 static int elect_display_compare(Session *s1, Session *s2) {