chiark / gitweb /
machine: make sure unpriviliged "machinectl status" can show the machine's OS version
[elogind.git] / src / login / logind-user.c
index 9bbe879571e4c838214478e77e64e24dcdf9f0f3..fdbccb364c1814f45d07249253c9107b8bbee8c7 100644 (file)
@@ -35,6 +35,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "conf-parser.h"
+#include "clean-ipc.h"
 #include "logind-user.h"
 
 User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
@@ -51,7 +52,7 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
         if (!u->name)
                 goto fail;
 
-        if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
+        if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
                 goto fail;
 
         if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
@@ -353,8 +354,8 @@ static int user_start_slice(User *u) {
 
         if (!u->slice) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                char lu[DECIMAL_STR_MAX(unsigned long) + 1], *slice;
-                sprintf(lu, "%lu", (unsigned long) u->uid);
+                char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
+                sprintf(lu, UID_FMT, u->uid);
 
                 r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
                 if (r < 0)
@@ -386,8 +387,8 @@ static int user_start_service(User *u) {
         assert(u);
 
         if (!u->service) {
-                char lu[DECIMAL_STR_MAX(unsigned long) + 1], *service;
-                sprintf(lu, "%lu", (unsigned long) u->uid);
+                char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
+                sprintf(lu, UID_FMT, u->uid);
 
                 service = unit_name_build("user", lu, ".service");
                 if (!service)
@@ -572,6 +573,13 @@ int user_finalize(User *u) {
         if (k < 0)
                 r = k;
 
+        /* Clean SysV + POSIX IPC objects */
+        if (u->manager->remove_ipc) {
+                k = clean_ipc(u->uid);
+                if (k < 0)
+                        r = k;
+        }
+
         unlink(u->state_file);
         user_add_to_gc_queue(u);
 
@@ -705,6 +713,43 @@ int user_kill(User *u, int signo) {
         return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
 }
 
+void user_elect_display(User *u) {
+        Session *graphical = NULL, *text = NULL, *s;
+
+        assert(u);
+
+        /* This elects a primary session for each user, which we call
+         * the "display". We try to keep the assignment stable, but we
+         * "upgrade" to better choices. */
+
+        LIST_FOREACH(sessions_by_user, s, u->sessions) {
+
+                if (s->class != SESSION_USER)
+                        continue;
+
+                if (s->stopping)
+                        continue;
+
+                if (SESSION_TYPE_IS_GRAPHICAL(s->type))
+                        graphical = s;
+                else
+                        text = s;
+        }
+
+        if (graphical &&
+            (!u->display ||
+             u->display->class != SESSION_USER ||
+             u->display->stopping ||
+             !SESSION_TYPE_IS_GRAPHICAL(u->display->type)))
+                u->display = graphical;
+
+        if (text &&
+            (!u->display ||
+             u->display->class != SESSION_USER ||
+             u->display->stopping))
+                u->display = text;
+}
+
 static const char* const user_state_table[_USER_STATE_MAX] = {
         [USER_OFFLINE] = "offline",
         [USER_OPENING] = "opening",