64dea3a
From 14c8069bcc228db3e92132d6baa5edaf3387d83b Mon Sep 17 00:00:00 2001
64dea3a
From: Lennart Poettering <lennart@poettering.net>
64dea3a
Date: Thu, 21 Jun 2012 16:14:53 +0200
64dea3a
Subject: [PATCH] logind: introduce a state for session, being one of online,
64dea3a
 active, closing
64dea3a
64dea3a
online = logged in
64dea3a
active = logged in and session is in the fg
64dea3a
closing = nominally logged out but some left-over processes still around
64dea3a
64dea3a
Related to:
64dea3a
64dea3a
https://bugzilla.gnome.org/show_bug.cgi?id=677556
64dea3a
(cherry picked from commit 0604381b9dbef4cc498b5a77311e1da99c1430b8)
64dea3a
64dea3a
Conflicts:
64dea3a
	TODO
64dea3a
---
64dea3a
 src/login/libsystemd-login.sym  |    5 +++++
64dea3a
 src/login/loginctl.c            |   10 +++++-----
64dea3a
 src/login/logind-session-dbus.c |   22 ++++++++++++++++++++--
64dea3a
 src/login/logind-session.c      |   22 ++++++++++++++++++++++
64dea3a
 src/login/logind-session.h      |   13 +++++++++++++
64dea3a
 src/login/logind-user.h         |   10 +++++-----
64dea3a
 src/login/sd-login.c            |   24 ++++++++++++++++++++++++
64dea3a
 src/login/test-login.c          |    5 +++++
64dea3a
 src/systemd/sd-login.h          |    9 +++++++--
64dea3a
 9 files changed, 106 insertions(+), 14 deletions(-)
64dea3a
64dea3a
diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym
64dea3a
index a5e6c1e..e43ee17 100644
64dea3a
--- a/src/login/libsystemd-login.sym
64dea3a
+++ b/src/login/libsystemd-login.sym
64dea3a
@@ -46,3 +46,8 @@ global:
64dea3a
         sd_session_get_class;
64dea3a
         sd_session_get_display;
64dea3a
 } LIBSYSTEMD_LOGIN_38;
64dea3a
+
64dea3a
+LIBSYSTEMD_LOGIN_186 {
64dea3a
+global:
64dea3a
+        sd_session_get_state;
64dea3a
+} LIBSYSTEMD_LOGIN_43;
64dea3a
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
64dea3a
index a494447..9a43685 100644
64dea3a
--- a/src/login/loginctl.c
64dea3a
+++ b/src/login/loginctl.c
64dea3a
@@ -364,7 +364,7 @@ typedef struct SessionStatusInfo {
64dea3a
         pid_t leader;
64dea3a
         const char *type;
64dea3a
         const char *class;
64dea3a
-        bool active;
64dea3a
+        const char *state;
64dea3a
 } SessionStatusInfo;
64dea3a
 
64dea3a
 typedef struct UserStatusInfo {
64dea3a
@@ -458,8 +458,8 @@ static void print_session_status_info(SessionStatusInfo *i) {
64dea3a
         } else if (i->class)
64dea3a
                 printf("\t   Class: %s\n", i->class);
64dea3a
 
64dea3a
-
64dea3a
-        printf("\t  Active: %s\n", yes_no(i->active));
64dea3a
+        if (i->state)
64dea3a
+                printf("\t   State: %s\n", i->state);
64dea3a
 
64dea3a
         if (i->default_control_group) {
64dea3a
                 unsigned c;
64dea3a
@@ -597,6 +597,8 @@ static int status_property_session(const char *name, DBusMessageIter *iter, Sess
64dea3a
                                 i->type = s;
64dea3a
                         else if (streq(name, "Class"))
64dea3a
                                 i->class = s;
64dea3a
+                        else if (streq(name, "State"))
64dea3a
+                                i->state = s;
64dea3a
                 }
64dea3a
                 break;
64dea3a
         }
64dea3a
@@ -621,8 +623,6 @@ static int status_property_session(const char *name, DBusMessageIter *iter, Sess
64dea3a
 
64dea3a
                 if (streq(name, "Remote"))
64dea3a
                         i->remote = b;
64dea3a
-                else if (streq(name, "Active"))
64dea3a
-                        i->active = b;
64dea3a
 
64dea3a
                 break;
64dea3a
         }
64dea3a
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
64dea3a
index e9fd5a3..c1704d1 100644
64dea3a
--- a/src/login/logind-session-dbus.c
64dea3a
+++ b/src/login/logind-session-dbus.c
64dea3a
@@ -53,12 +53,13 @@
64dea3a
         "  <property name=\"Remote\" type=\"b\" access=\"read\"/>\n"    \
64dea3a
         "  <property name=\"RemoteHost\" type=\"s\" access=\"read\"/>\n" \
64dea3a
         "  <property name=\"RemoteUser\" type=\"s\" access=\"read\"/>\n" \
64dea3a
-        "  <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
64dea3a
+        "  <property name=\"Service\" type=\"s\" access=\"read\"/>\n"   \
64dea3a
         "  <property name=\"Leader\" type=\"u\" access=\"read\"/>\n"    \
64dea3a
         "  <property name=\"Audit\" type=\"u\" access=\"read\"/>\n"     \
64dea3a
         "  <property name=\"Type\" type=\"s\" access=\"read\"/>\n"      \
64dea3a
-        "  <property name=\"Class\" type=\"s\" access=\"read\"/>\n"      \
64dea3a
+        "  <property name=\"Class\" type=\"s\" access=\"read\"/>\n"     \
64dea3a
         "  <property name=\"Active\" type=\"b\" access=\"read\"/>\n"    \
64dea3a
+        "  <property name=\"State\" type=\"s\" access=\"read\"/>\n"     \
64dea3a
         "  <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
64dea3a
         "  <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
64dea3a
         "  <property name=\"KillProcesses\" type=\"b\" access=\"read\"/>\n" \
64dea3a
@@ -219,6 +220,22 @@ static int bus_session_append_default_cgroup(DBusMessageIter *i, const char *pro
64dea3a
 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_type, session_type, SessionType);
64dea3a
 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_class, session_class, SessionClass);
64dea3a
 
64dea3a
+static int bus_session_append_state(DBusMessageIter *i, const char *property, void *data) {
64dea3a
+        Session *s = data;
64dea3a
+        const char *state;
64dea3a
+
64dea3a
+        assert(i);
64dea3a
+        assert(property);
64dea3a
+        assert(s);
64dea3a
+
64dea3a
+        state = session_state_to_string(session_get_state(s));
64dea3a
+
64dea3a
+        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
64dea3a
+                return -ENOMEM;
64dea3a
+
64dea3a
+        return 0;
64dea3a
+}
64dea3a
+
64dea3a
 static int get_session_for_path(Manager *m, const char *path, Session **_s) {
64dea3a
         Session *s;
64dea3a
         char *id;
64dea3a
@@ -262,6 +279,7 @@ static const BusProperty bus_login_session_properties[] = {
64dea3a
         { "Type",                   bus_session_append_type,            "s", offsetof(Session, type)                },
64dea3a
         { "Class",                  bus_session_append_class,           "s", offsetof(Session, class)               },
64dea3a
         { "Active",                 bus_session_append_active,          "b", 0 },
64dea3a
+        { "State",                  bus_session_append_state,           "s", 0 },
64dea3a
         { "Controllers",            bus_property_append_strv,          "as", offsetof(Session, controllers),        true },
64dea3a
         { "ResetControllers",       bus_property_append_strv,          "as", offsetof(Session, reset_controllers),  true },
64dea3a
         { "KillProcesses",          bus_property_append_bool,           "b", offsetof(Session, kill_processes)      },
64dea3a
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
64dea3a
index 49e1e5c..1945041 100644
64dea3a
--- a/src/login/logind-session.c
64dea3a
+++ b/src/login/logind-session.c
64dea3a
@@ -133,11 +133,13 @@ int session_save(Session *s) {
64dea3a
                 "UID=%lu\n"
64dea3a
                 "USER=%s\n"
64dea3a
                 "ACTIVE=%i\n"
64dea3a
+                "STATE=%s\n"
64dea3a
                 "REMOTE=%i\n"
64dea3a
                 "KILL_PROCESSES=%i\n",
64dea3a
                 (unsigned long) s->user->uid,
64dea3a
                 s->user->name,
64dea3a
                 session_is_active(s),
64dea3a
+                session_state_to_string(session_get_state(s)),
64dea3a
                 s->remote,
64dea3a
                 s->kill_processes);
64dea3a
 
64dea3a
@@ -913,6 +915,18 @@ void session_add_to_gc_queue(Session *s) {
64dea3a
         s->in_gc_queue = true;
64dea3a
 }
64dea3a
 
64dea3a
+SessionState session_get_state(Session *s) {
64dea3a
+        assert(s);
64dea3a
+
64dea3a
+        if (s->fifo_fd < 0)
64dea3a
+                return SESSION_CLOSING;
64dea3a
+
64dea3a
+        if (session_is_active(s))
64dea3a
+                return SESSION_ACTIVE;
64dea3a
+
64dea3a
+        return SESSION_ONLINE;
64dea3a
+}
64dea3a
+
64dea3a
 int session_kill(Session *s, KillWho who, int signo) {
64dea3a
         int r = 0;
64dea3a
         Set *pid_set = NULL;
64dea3a
@@ -954,6 +968,14 @@ int session_kill(Session *s, KillWho who, int signo) {
64dea3a
         return r;
64dea3a
 }
64dea3a
 
64dea3a
+static const char* const session_state_table[_SESSION_TYPE_MAX] = {
64dea3a
+        [SESSION_ONLINE] = "online",
64dea3a
+        [SESSION_ACTIVE] = "active",
64dea3a
+        [SESSION_CLOSING] = "closing"
64dea3a
+};
64dea3a
+
64dea3a
+DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
64dea3a
+
64dea3a
 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
64dea3a
         [SESSION_TTY] = "tty",
64dea3a
         [SESSION_X11] = "x11",
64dea3a
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
64dea3a
index d0b8c87..77a12af 100644
64dea3a
--- a/src/login/logind-session.h
64dea3a
+++ b/src/login/logind-session.h
64dea3a
@@ -30,6 +30,14 @@ typedef struct Session Session;
64dea3a
 #include "logind-seat.h"
64dea3a
 #include "logind-user.h"
64dea3a
 
64dea3a
+typedef enum SessionState {
64dea3a
+        SESSION_ONLINE,   /* Logged in */
64dea3a
+        SESSION_ACTIVE,   /* Logged in and in the fg */
64dea3a
+        SESSION_CLOSING,  /* Logged out, but processes still remain */
64dea3a
+        _SESSION_STATE_MAX,
64dea3a
+        _SESSION_STATE_INVALID = -1
64dea3a
+} SessionState;
64dea3a
+
64dea3a
 typedef enum SessionType {
64dea3a
         SESSION_UNSPECIFIED,
64dea3a
         SESSION_TTY,
64dea3a
@@ -118,12 +126,17 @@ int session_kill(Session *s, KillWho who, int signo);
64dea3a
 
64dea3a
 char *session_bus_path(Session *s);
64dea3a
 
64dea3a
+SessionState session_get_state(Session *u);
64dea3a
+
64dea3a
 extern const DBusObjectPathVTable bus_session_vtable;
64dea3a
 
64dea3a
 int session_send_signal(Session *s, bool new_session);
64dea3a
 int session_send_changed(Session *s, const char *properties);
64dea3a
 int session_send_lock(Session *s, bool lock);
64dea3a
 
64dea3a
+const char* session_state_to_string(SessionState t);
64dea3a
+SessionState session_state_from_string(const char *s);
64dea3a
+
64dea3a
 const char* session_type_to_string(SessionType t);
64dea3a
 SessionType session_type_from_string(const char *s);
64dea3a
 
64dea3a
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
64dea3a
index 802f1ed..23e409c 100644
64dea3a
--- a/src/login/logind-user.h
64dea3a
+++ b/src/login/logind-user.h
64dea3a
@@ -30,11 +30,11 @@ typedef struct User User;
64dea3a
 #include "logind-session.h"
64dea3a
 
64dea3a
 typedef enum UserState {
64dea3a
-        USER_OFFLINE,
64dea3a
-        USER_LINGERING,
64dea3a
-        USER_ONLINE,
64dea3a
-        USER_ACTIVE,
64dea3a
-        USER_CLOSING,
64dea3a
+        USER_OFFLINE,    /* Not logged in at all */
64dea3a
+        USER_LINGERING,  /* Lingering has been enabled by the admin for this user */
64dea3a
+        USER_ONLINE,     /* User logged in */
64dea3a
+        USER_ACTIVE,     /* User logged in and has a session in the fg */
64dea3a
+        USER_CLOSING,    /* User logged out, but processes still remain and lingering is not enabled */
64dea3a
         _USER_STATE_MAX,
64dea3a
         _USER_STATE_INVALID = -1
64dea3a
 } UserState;
64dea3a
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
64dea3a
index a17c1d4..2effe7d 100644
64dea3a
--- a/src/login/sd-login.c
64dea3a
+++ b/src/login/sd-login.c
64dea3a
@@ -317,6 +317,30 @@ _public_ int sd_session_is_active(const char *session) {
64dea3a
         return r;
64dea3a
 }
64dea3a
 
64dea3a
+_public_ int sd_session_get_state(const char *session, char **state) {
64dea3a
+        char *p, *s = NULL;
64dea3a
+        int r;
64dea3a
+
64dea3a
+        if (!state)
64dea3a
+                return -EINVAL;
64dea3a
+
64dea3a
+        r = file_of_session(session, &p);
64dea3a
+        if (r < 0)
64dea3a
+                return r;
64dea3a
+
64dea3a
+        r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
64dea3a
+        free(p);
64dea3a
+
64dea3a
+        if (r < 0) {
64dea3a
+                free(s);
64dea3a
+                return r;
64dea3a
+        } else if (!s)
64dea3a
+                return -EIO;
64dea3a
+
64dea3a
+        *state = s;
64dea3a
+        return 0;
64dea3a
+}
64dea3a
+
64dea3a
 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
64dea3a
         int r;
64dea3a
         char *p, *s = NULL;
64dea3a
diff --git a/src/login/test-login.c b/src/login/test-login.c
64dea3a
index dd84042..2e0e257 100644
64dea3a
--- a/src/login/test-login.c
64dea3a
+++ b/src/login/test-login.c
64dea3a
@@ -71,6 +71,11 @@ int main(int argc, char* argv[]) {
64dea3a
         assert_se(r >= 0);
64dea3a
         printf("active = %s\n", yes_no(r));
64dea3a
 
64dea3a
+        r = sd_session_get_state(session, &state);
64dea3a
+        assert_se(r >= 0);
64dea3a
+        printf("state = %s\n", state);
64dea3a
+        free(state);
64dea3a
+
64dea3a
         assert_se(sd_session_get_uid(session, &u) >= 0);
64dea3a
         printf("uid = %lu\n", (unsigned long) u);
64dea3a
         assert_se(u == u2);
64dea3a
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
64dea3a
index 315700e..1d5b657 100644
64dea3a
--- a/src/systemd/sd-login.h
64dea3a
+++ b/src/systemd/sd-login.h
64dea3a
@@ -63,7 +63,7 @@ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid);
64dea3a
  * error for non-service processes. */
64dea3a
 int sd_pid_get_unit(pid_t, char **unit);
64dea3a
 
64dea3a
-/* Get state from uid. Possible states: offline, lingering, online, active */
64dea3a
+/* Get state from uid. Possible states: offline, lingering, online, active, closing */
64dea3a
 int sd_uid_get_state(uid_t uid, char**state);
64dea3a
 
64dea3a
 /* Return 1 if uid has session on seat. If require_active is true will
64dea3a
@@ -80,9 +80,14 @@ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions);
64dea3a
  * just return number of seats.*/
64dea3a
 int sd_uid_get_seats(uid_t uid, int require_active, char ***seats);
64dea3a
 
64dea3a
-/* Return 1 if the session is a active */
64dea3a
+/* Return 1 if the session is a active. */
64dea3a
 int sd_session_is_active(const char *session);
64dea3a
 
64dea3a
+/* Get state from session. Possible states: online, active, closing
64dea3a
+ * (This function is a more generic version of
64dea3a
+ * sd_session_is_active().) */
64dea3a
+int sd_session_get_state(const char *sessio, char **state);
64dea3a
+
64dea3a
 /* Determine user id of session */
64dea3a
 int sd_session_get_uid(const char *session, uid_t *uid);
64dea3a