X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Flogind-seat.c;h=33fd3afacae4ff38af25d10fc71fa4205dc4cbdc;hp=631be5f7409830d87592f6b278ce3057911e1b6a;hb=ad0ff86c7c90c3d652edb7c81ebd3f07f70a9a07;hpb=9bb69af4f2823fdd30902f5ffd959e9b041feb53;ds=sidebyside diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 631be5f74..33fd3afac 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,21 +17,25 @@ along with systemd; If not, see . ***/ -#include #include -#include #include -#include -#include #include +#include -#include "sd-id128.h" #include "sd-messages.h" -#include "logind-seat.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "formats-util.h" #include "logind-acl.h" -#include "util.h" +#include "logind-seat.h" #include "mkdir.h" -#include "path-util.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "util.h" Seat *seat_new(Manager *m, const char *id) { Seat *s; @@ -96,11 +98,11 @@ int seat_save(Seat *s) { r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0); if (r < 0) - goto finish; + goto fail; r = fopen_temporary(s->state_file, &f, &temp_path); if (r < 0) - goto finish; + goto fail; fchmod(fileno(f), 0644); @@ -120,9 +122,9 @@ int seat_save(Seat *s) { fprintf(f, "ACTIVE=%s\n" - "ACTIVE_UID=%lu\n", + "ACTIVE_UID="UID_FMT"\n", s->active->id, - (unsigned long) s->active->user->uid); + s->active->user->uid); } if (s->sessions) { @@ -144,19 +146,24 @@ int seat_save(Seat *s) { i->sessions_by_seat_next ? ' ' : '\n'); } - fflush(f); + r = fflush_and_check(f); + if (r < 0) + goto fail; - if (ferror(f) || rename(temp_path, s->state_file) < 0) { + if (rename(temp_path, s->state_file) < 0) { r = -errno; - unlink(s->state_file); - unlink(temp_path); + goto fail; } -finish: - if (r < 0) - log_error("Failed to save seat data %s: %s", s->state_file, strerror(-r)); + return 0; - return r; +fail: + (void) unlink(s->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save seat data %s: %m", s->state_file); } int seat_load(Seat *s) { @@ -167,15 +174,14 @@ int seat_load(Seat *s) { return 0; } +#if 0 /// UNNEEDED by elogind 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; - + xsprintf(p, "/dev/tty%u", vtnr); fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; @@ -203,13 +209,14 @@ int seat_preallocate_vts(Seat *s) { q = vt_allocate(i); if (q < 0) { - log_error("Failed to preallocate VT %i: %s", i, strerror(-q)); + log_error_errno(q, "Failed to preallocate VT %u: %m", i); r = q; } } return r; } +#endif // 0 int seat_apply_acls(Seat *s, Session *old_active) { int r; @@ -223,7 +230,7 @@ int seat_apply_acls(Seat *s, Session *old_active) { !!s->active, s->active ? s->active->user->uid : 0); if (r < 0) - log_error("Failed to apply ACLs: %s", strerror(-r)); + log_error_errno(r, "Failed to apply ACLs: %m"); return r; } @@ -274,11 +281,16 @@ int seat_set_active(Seat *s, Session *session) { int seat_switch_to(Seat *s, unsigned int num) { /* Public session positions skip 0 (there is only F1-F12). Maybe it * will get reassigned in the future, so return error for now. */ - if (!num) + if (num == 0) return -EINVAL; - if (num >= s->position_count || !s->positions[num]) + if (num >= s->position_count || !s->positions[num]) { + /* allow switching to unused VTs to trigger auto-activate */ + if (seat_has_vts(s) && num < 64) + return chvt(num); + return -EINVAL; + } return session_activate(s->positions[num]); } @@ -286,12 +298,12 @@ int seat_switch_to(Seat *s, unsigned int num) { int seat_switch_to_next(Seat *s) { unsigned int start, i; - if (!s->position_count) + if (s->position_count == 0) return -EINVAL; start = 1; - if (s->active && s->active->pos > 0) - start = s->active->pos; + if (s->active && s->active->position > 0) + start = s->active->position; for (i = start + 1; i < s->position_count; ++i) if (s->positions[i]) @@ -307,12 +319,12 @@ int seat_switch_to_next(Seat *s) { int seat_switch_to_previous(Seat *s) { unsigned int start, i; - if (!s->position_count) + if (s->position_count == 0) return -EINVAL; start = 1; - if (s->active && s->active->pos > 0) - start = s->active->pos; + if (s->active && s->active->position > 0) + start = s->active->position; for (i = start - 1; i > 0; --i) if (s->positions[i]) @@ -337,14 +349,29 @@ int seat_active_vt_changed(Seat *s, unsigned int vtnr) { log_debug("VT changed to %u", vtnr); + /* we might have earlier closing sessions on the same VT, so try to + * find a running one first */ LIST_FOREACH(sessions_by_seat, i, s->sessions) - if (i->vtnr == vtnr) { + if (i->vtnr == vtnr && !i->stopping) { new_active = i; break; } + if (!new_active) { + /* no running one? then we can't decide which one is the + * active one, let the first one win */ + LIST_FOREACH(sessions_by_seat, i, s->sessions) + if (i->vtnr == vtnr) { + new_active = i; + break; + } + } + r = seat_set_active(s, new_active); + +#if 0 /// elogind does not spawn autovt manager_spawn_autovt(s->manager, vtnr); +#endif // 0 return r; } @@ -397,13 +424,15 @@ int seat_start(Seat *s) { return 0; log_struct(LOG_INFO, - MESSAGE_ID(SD_MESSAGE_SEAT_START), + LOG_MESSAGE_ID(SD_MESSAGE_SEAT_START), "SEAT_ID=%s", s->id, - "MESSAGE=New seat %s.", s->id, + LOG_MESSAGE("New seat %s.", s->id), NULL); /* Initialize VT magic stuff */ +#if 0 /// elogind does not support autospawning vts seat_preallocate_vts(s); +#endif // 0 /* Read current VT */ seat_read_active_vt(s); @@ -425,9 +454,9 @@ int seat_stop(Seat *s, bool force) { if (s->started) log_struct(LOG_INFO, - MESSAGE_ID(SD_MESSAGE_SEAT_STOP), + LOG_MESSAGE_ID(SD_MESSAGE_SEAT_STOP), "SEAT_ID=%s", s->id, - "MESSAGE=Removed seat %s.", s->id, + LOG_MESSAGE("Removed seat %s.", s->id), NULL); seat_stop_sessions(s, force); @@ -459,15 +488,27 @@ int seat_stop_sessions(Seat *s, bool force) { } void seat_evict_position(Seat *s, Session *session) { - unsigned int pos = session->pos; + Session *iter; + unsigned int pos = session->position; - session->pos = 0; + session->position = 0; - if (!pos) + if (pos == 0) 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 let's look + * for it and set it on the free slot. */ + LIST_FOREACH(sessions_by_seat, iter, s->sessions) { + if (iter->position == pos && session_get_state(iter) != SESSION_CLOSING) { + s->positions[pos] = iter; + break; + } + } + } } void seat_claim_position(Seat *s, Session *session, unsigned int pos) { @@ -480,15 +521,15 @@ void seat_claim_position(Seat *s, Session *session, unsigned int pos) { seat_evict_position(s, session); - session->pos = pos; - if (pos > 0 && !s->positions[pos]) + session->position = pos; + if (pos > 0) s->positions[pos] = session; } static void seat_assign_position(Seat *s, Session *session) { unsigned int pos; - if (session->pos > 0) + if (session->position > 0) return; for (pos = 1; pos < s->position_count; ++pos) @@ -575,7 +616,7 @@ bool seat_can_graphical(Seat *s) { int seat_get_idle_hint(Seat *s, dual_timestamp *t) { Session *session; bool idle_hint = true; - dual_timestamp ts = { 0, 0 }; + dual_timestamp ts = DUAL_TIMESTAMP_NULL; assert(s);