X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogind-seat.c;h=751f59a48d6f3d74239263f5be67e4761cccf8bd;hb=a185c5aa2d8bef98716f8cf160da263c17e588b2;hp=24a5d8f20bf6713d9594fbc2306ec6b9780476f5;hpb=14c3baca3eb8b32fc266e46127851585bee5aff2;p=elogind.git diff --git a/src/logind-seat.c b/src/logind-seat.c index 24a5d8f20..751f59a48 100644 --- a/src/logind-seat.c +++ b/src/logind-seat.c @@ -75,11 +75,7 @@ void seat_free(Seat *s) { hashmap_remove(s->manager->seats, s->id); - if (s->state_file) { - unlink(s->state_file); - free(s->state_file); - } - + free(s->state_file); free(s); } @@ -103,7 +99,7 @@ int seat_save(Seat *s) { fprintf(f, "# This is private data. Do not parse.\n" "IS_VTCONSOLE=%i\n", - s->manager->vtconsole == s); + seat_is_vtconsole(s)); if (s->active) { assert(s->active->user); @@ -162,6 +158,8 @@ finish: int seat_load(Seat *s) { assert(s); + /* There isn't actually anything to read here ... */ + return 0; } @@ -186,7 +184,8 @@ static int vt_allocate(int vtnr) { } static int seat_preallocate_vts(Seat *s) { - int i, r = 0; + int r = 0; + unsigned i; assert(s); assert(s->manager); @@ -194,7 +193,7 @@ static int seat_preallocate_vts(Seat *s) { if (s->manager->n_autovts <= 0) return 0; - if (s->manager->vtconsole != s) + if (!seat_is_vtconsole(s)) return 0; for (i = 1; i < s->manager->n_autovts; i++) { @@ -233,7 +232,7 @@ int seat_active_vt_changed(Seat *s, int vtnr) { assert(s); assert(vtnr >= 1); - if (s->manager->vtconsole != s) + if (!seat_is_vtconsole(s)) return -EINVAL; log_debug("VT changed to %i", vtnr); @@ -263,7 +262,7 @@ int seat_read_active_vt(Seat *s) { assert(s); - if (s->manager->vtconsole != s) + if (!seat_is_vtconsole(s)) return 0; lseek(s->manager->console_active_fd, SEEK_SET, 0); @@ -299,6 +298,11 @@ int seat_read_active_vt(Seat *s) { int seat_start(Seat *s) { assert(s); + if (s->started) + return 0; + + log_info("New seat %s.", s->id); + /* Initialize VT magic stuff */ seat_preallocate_vts(s); @@ -308,10 +312,32 @@ int seat_start(Seat *s) { /* Save seat data */ seat_save(s); + s->started = true; + return 0; } int seat_stop(Seat *s) { + int r = 0; + + assert(s); + + if (!s->started) + return 0; + + log_info("Removed seat %s.", s->id); + + seat_stop_sessions(s); + + unlink(s->state_file); + seat_add_to_gc_queue(s); + + s->started = false; + + return r; +} + +int seat_stop_sessions(Seat *s) { Session *session; int r = 0, k; @@ -323,16 +349,74 @@ int seat_stop(Seat *s) { r = k; } - seat_save(s); - seat_add_to_gc_queue(s); - return r; } +int seat_attach_session(Seat *s, Session *session) { + assert(s); + assert(session); + assert(!session->seat); + + if (!seat_is_vtconsole(s)) { + if (s->sessions) + return -EEXIST; + + assert(!s->active); + s->active = session; + } + + session->seat = s; + LIST_PREPEND(Session, sessions_by_seat, s->sessions, session); + + return 0; +} + +bool seat_is_vtconsole(Seat *s) { + assert(s); + + return s->manager->vtconsole == s; +} + +int seat_get_idle_hint(Seat *s, dual_timestamp *t) { + Session *session; + bool idle_hint = true; + dual_timestamp ts = { 0, 0 }; + + assert(s); + + LIST_FOREACH(sessions_by_seat, session, s->sessions) { + dual_timestamp k; + int ih; + + ih = session_get_idle_hint(session, &k); + if (ih < 0) + return ih; + + if (!ih) { + if (!idle_hint) { + if (k.monotonic < ts.monotonic) + ts = k; + } else { + idle_hint = false; + ts = k; + } + } else if (idle_hint) { + + if (k.monotonic > ts.monotonic) + ts = k; + } + } + + if (t) + *t = ts; + + return idle_hint; +} + int seat_check_gc(Seat *s) { assert(s); - if (s->manager->vtconsole == s) + if (seat_is_vtconsole(s)) return 1; return !!s->devices; @@ -347,3 +431,30 @@ void seat_add_to_gc_queue(Seat *s) { LIST_PREPEND(Seat, gc_queue, s->manager->seat_gc_queue, s); s->in_gc_queue = true; } + +static bool seat_name_valid_char(char c) { + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '-' || + c == '_'; +} + +bool seat_name_is_valid(const char *name) { + const char *p; + + assert(name); + + if (!startswith(name, "seat")) + return false; + + if (!name[4]) + return false; + + for (p = name; *p; p++) + if (!seat_name_valid_char(*p)) + return false; + + return true; +}