chiark / gitweb /
systemctl: prefix list-units and list-machines output with a circle indicating a...
[elogind.git] / src / login / logind-seat.c
index c7f112afb77b8a4ff46435fe59d64c68724630ea..3f5efdc8ea706f8195b463163f838a5d4d34fd75 100644 (file)
@@ -168,14 +168,12 @@ int seat_load(Seat *s) {
 }
 
 static int vt_allocate(unsigned int vtnr) {
-        _cleanup_free_ char *p = NULL;
+        char p[sizeof("/dev/tty") + DECIMAL_STR_MAX(unsigned int)];
         _cleanup_close_ int fd = -1;
 
         assert(vtnr >= 1);
 
-        if (asprintf(&p, "/dev/tty%u", vtnr) < 0)
-                return -ENOMEM;
-
+        snprintf(p, sizeof(p), "/dev/tty%u", vtnr);
         fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 return -errno;
@@ -418,7 +416,7 @@ int seat_start(Seat *s) {
         return 0;
 }
 
-int seat_stop(Seat *s) {
+int seat_stop(Seat *s, bool force) {
         int r = 0;
 
         assert(s);
@@ -430,7 +428,7 @@ int seat_stop(Seat *s) {
                            "MESSAGE=Removed seat %s.", s->id,
                            NULL);
 
-        seat_stop_sessions(s);
+        seat_stop_sessions(s, force);
 
         unlink(s->state_file);
         seat_add_to_gc_queue(s);
@@ -443,14 +441,14 @@ int seat_stop(Seat *s) {
         return r;
 }
 
-int seat_stop_sessions(Seat *s) {
+int seat_stop_sessions(Seat *s, bool force) {
         Session *session;
         int r = 0, k;
 
         assert(s);
 
         LIST_FOREACH(sessions_by_seat, session, s->sessions) {
-                k = session_stop(session);
+                k = session_stop(session, force);
                 if (k < 0)
                         r = k;
         }
@@ -459,6 +457,7 @@ int seat_stop_sessions(Seat *s) {
 }
 
 void seat_evict_position(Seat *s, Session *session) {
+        Session *iter;
         unsigned int pos = session->pos;
 
         session->pos = 0;
@@ -466,8 +465,19 @@ void seat_evict_position(Seat *s, Session *session) {
         if (!pos)
                 return;
 
-        if (pos < s->position_count && s->positions[pos] == session)
+        if (pos < s->position_count && s->positions[pos] == session) {
                 s->positions[pos] = NULL;
+
+                /* There might be another session claiming the same
+                 * position (eg., during gdm->session transition), so lets look
+                 * for it and set it on the free slot. */
+                LIST_FOREACH(sessions_by_seat, iter, s->sessions) {
+                        if (iter->pos == pos) {
+                                s->positions[pos] = iter;
+                                break;
+                        }
+                }
+        }
 }
 
 void seat_claim_position(Seat *s, Session *session, unsigned int pos) {
@@ -475,7 +485,7 @@ void seat_claim_position(Seat *s, Session *session, unsigned int pos) {
         if (seat_has_vts(s))
                 pos = session->vtnr;
 
-        if (!GREEDY_REALLOC0(s->positions, s->position_count, pos + 1))
+        if (!GREEDY_REALLOC0_T(s->positions, s->position_count, pos + 1))
                 return;
 
         seat_evict_position(s, session);