logind-seat.c revision 718d006a63f773c42106494e823250c48942cf08
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt/***
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt This file is part of systemd.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Copyright 2011 Lennart Poettering
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt systemd is free software; you can redistribute it and/or modify it
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt under the terms of the GNU Lesser General Public License as published by
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt (at your option) any later version.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt systemd is distributed in the hope that it will be useful, but
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Lesser General Public License for more details.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt You should have received a copy of the GNU Lesser General Public License
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt***/
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <assert.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <errno.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <unistd.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <fcntl.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <sys/ioctl.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <linux/vt.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <string.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include "systemd/sd-id128.h"
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt#include "systemd/sd-messages.h"
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt#include "logind-seat.h"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt#include "logind-acl.h"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt#include "util.h"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt#include "mkdir.h"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt#include "path-util.h"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom GundersenSeat *seat_new(Manager *m, const char *id) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt Seat *s;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(m);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(id);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt s = new0(Seat, 1);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (!s)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return NULL;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt s->state_file = strappend("/run/systemd/seats/", id);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (!s->state_file) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt free(s);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return NULL;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt }
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt s->id = path_get_file_name(s->state_file);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt s->manager = m;
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (hashmap_put(m->seats, s->id, s) < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt free(s->state_file);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt free(s);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return NULL;
200a0868fcdf7b95f3d8d1fda3aa2aef48d84fddTom Gundersen }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return s;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktvoid seat_free(Seat *s) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(s);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (s->in_gc_queue)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt LIST_REMOVE(Seat, gc_queue, s->manager->seat_gc_queue, s);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
f0213e3796b4dd66e546e2de4d677db319f9171bTom Gundersen while (s->sessions)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt session_free(s->sessions);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(!s->active);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt while (s->devices)
851c9f82736c89d423b244a292e153ec7124d309Patrik Flykt device_free(s->devices);
851c9f82736c89d423b244a292e153ec7124d309Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt hashmap_remove(s->manager->seats, s->id);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt free(s->state_file);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt free(s);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmannint seat_save(Seat *s) {
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann int r;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering FILE *f;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt char *temp_path;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(s);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (!s->started)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return 0;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt goto finish;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = fopen_temporary(s->state_file, &f, &temp_path);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt goto finish;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fchmod(fileno(f), 0644);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fprintf(f,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "# This is private data. Do not parse.\n"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "IS_VTCONSOLE=%i\n"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "CAN_MULTI_SESSION=%i\n"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "CAN_TTY=%i\n"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "CAN_GRAPHICAL=%i\n",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt seat_is_vtconsole(s),
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt seat_can_multi_session(s),
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt seat_can_tty(s),
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt seat_can_graphical(s));
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering if (s->active) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(s->active->user);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fprintf(f,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "ACTIVE=%s\n"
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt "ACTIVE_UID=%lu\n",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt s->active->id,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt (unsigned long) s->active->user->uid);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (s->sessions) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt Session *i;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fputs("SESSIONS=", f);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt LIST_FOREACH(sessions_by_seat, i, s->sessions) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fprintf(f,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt "%s%c",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt i->id,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt i->sessions_by_seat_next ? ' ' : '\n');
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt fputs("UIDS=", f);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt LIST_FOREACH(sessions_by_seat, i, s->sessions)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt fprintf(f,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt "%lu%c",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt (unsigned long) i->user->uid,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt i->sessions_by_seat_next ? ' ' : '\n');
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann fflush(f);
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt if (ferror(f) || rename(temp_path, s->state_file) < 0) {
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt r = -errno;
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt unlink(s->state_file);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt unlink(temp_path);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt fclose(f);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt free(temp_path);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktfinish:
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_error("Failed to save seat data for %s: %s", s->id, strerror(-r));
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktint seat_load(Seat *s) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(s);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt /* There isn't actually anything to read here ... */
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return 0;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic int vt_allocate(int vtnr) {
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering int fd, r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt char *p;
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(vtnr >= 1);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt if (asprintf(&p, "/dev/tty%i", vtnr) < 0)
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt return -ENOMEM;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt free(p);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = fd < 0 ? -errno : 0;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (fd >= 0)
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt close_nointr_nofail(fd);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flyktint seat_preallocate_vts(Seat *s) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt int r = 0;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt unsigned i;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt assert(s);
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering assert(s->manager);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt log_debug("Preallocating VTs...");
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt if (s->manager->n_autovts <= 0)
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt return 0;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering if (!seat_can_multi_session(s))
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt return 0;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt for (i = 1; i <= s->manager->n_autovts; i++) {
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt int q;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt q = vt_allocate(i);
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering if (q < 0) {
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt log_error("Failed to preallocate VT %i: %s", i, strerror(-q));
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt r = q;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt}
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flyktint seat_apply_acls(Seat *s, Session *old_active) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt int r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt assert(s);
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt
18d29550b5fbc4b0de334b8212d05decdd131f1bPatrik Flykt r = devnode_acl_all(s->manager->udev,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt s->id,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt false,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt !!old_active, old_active ? old_active->user->uid : 0,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt !!s->active, s->active ? s->active->user->uid : 0);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_error("Failed to apply ACLs: %s", strerror(-r));
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt return r;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktint seat_set_active(Seat *s, Session *session) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Session *old_active;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt assert(s);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt assert(!session || session->seat == s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (session == s->active)
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt return 0;
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt old_active = s->active;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt s->active = session;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt seat_apply_acls(s, old_active);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (session && session->started)
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann session_send_changed(session, "Active\0");
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (!session || session->started)
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt seat_send_changed(s, "ActiveSession\0");
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt seat_save(s);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (session) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt session_save(session);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt user_save(session->user);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt }
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (old_active) {
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt session_save(old_active);
e66040417b52be98d41ba1230f25dea65147e8eePatrik Flykt if (!session || session->user != old_active->user)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt user_save(old_active->user);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return 0;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt}
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flyktint seat_active_vt_changed(Seat *s, int vtnr) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt Session *i, *new_active = NULL;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt int r;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt assert(s);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt assert(vtnr >= 1);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (!seat_can_multi_session(s))
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return -EINVAL;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt log_debug("VT changed to %i", vtnr);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt LIST_FOREACH(sessions_by_seat, i, s->sessions)
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann if (i->vtnr == vtnr) {
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann new_active = i;
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering break;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt }
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt r = seat_set_active(s, new_active);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt manager_spawn_autovt(s->manager, vtnr);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return r;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt}
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flyktint seat_read_active_vt(Seat *s) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt char t[64];
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt ssize_t k;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt int r, vtnr;
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt assert(s);
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (!seat_can_multi_session(s))
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return 0;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt lseek(s->manager->console_active_fd, SEEK_SET, 0);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt k = read(s->manager->console_active_fd, t, sizeof(t)-1);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (k <= 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF");
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return k < 0 ? -errno : -EIO;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt t[k] = 0;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt truncate_nl(t);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (!startswith(t, "tty")) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_error("Hm, /sys/class/tty/tty0/active is badly formatted.");
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann return -EIO;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann r = safe_atoi(t+3, &vtnr);
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann if (r < 0) {
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann log_error("Failed to parse VT number %s", t+3);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (vtnr <= 0) {
575ac4c62e417cb3e963f2bee627e3c10b06691dDavid Herrmann log_error("VT number invalid: %s", t+3);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return -EIO;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt }
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return seat_active_vt_changed(s, vtnr);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktint seat_start(Seat *s) {
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering assert(s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering if (s->started)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return 0;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_struct(LOG_INFO,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt MESSAGE_ID(SD_MESSAGE_SEAT_START),
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt "SEAT_ID=%s", s->id,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt "MESSAGE=New seat %s.", s->id,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt NULL);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt /* Initialize VT magic stuff */
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt seat_preallocate_vts(s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt /* Read current VT */
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt seat_read_active_vt(s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt s->started = true;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt /* Save seat data */
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt seat_save(s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt seat_send_signal(s, true);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return 0;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktint seat_stop(Seat *s) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt int r = 0;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(s);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (s->started)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_struct(LOG_INFO,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt MESSAGE_ID(SD_MESSAGE_SEAT_STOP),
"SEAT_ID=%s", s->id,
"MESSAGE=Removed seat %s.", s->id,
NULL);
seat_stop_sessions(s);
unlink(s->state_file);
seat_add_to_gc_queue(s);
if (s->started)
seat_send_signal(s, false);
s->started = false;
return r;
}
int seat_stop_sessions(Seat *s) {
Session *session;
int r = 0, k;
assert(s);
LIST_FOREACH(sessions_by_seat, session, s->sessions) {
k = session_stop(session);
if (k < 0)
r = k;
}
return r;
}
int seat_attach_session(Seat *s, Session *session) {
assert(s);
assert(session);
assert(!session->seat);
session->seat = s;
LIST_PREPEND(Session, sessions_by_seat, s->sessions, session);
seat_send_changed(s, "Sessions\0");
/* Note that even if a seat is not multi-session capable it
* still might have multiple sessions on it since old, dead
* sessions might continue to be tracked until all their
* processes are gone. The most recently added session
* (i.e. the first in s->sessions) is the one that matters. */
if (!seat_can_multi_session(s))
seat_set_active(s, session);
return 0;
}
bool seat_is_vtconsole(Seat *s) {
assert(s);
return s->manager->vtconsole == s;
}
bool seat_can_multi_session(Seat *s) {
assert(s);
if (!seat_is_vtconsole(s))
return false;
/* If we can't watch which VT is in the foreground, we don't
* support VT switching */
return s->manager->console_active_fd >= 0;
}
bool seat_can_tty(Seat *s) {
assert(s);
return seat_is_vtconsole(s);
}
bool seat_has_master_device(Seat *s) {
assert(s);
/* device list is ordered by "master" flag */
return !!s->devices && s->devices->master;
}
bool seat_can_graphical(Seat *s) {
assert(s);
return seat_has_master_device(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, bool drop_not_started) {
assert(s);
if (drop_not_started && !s->started)
return 0;
if (seat_is_vtconsole(s))
return 1;
return seat_has_master_device(s);
}
void seat_add_to_gc_queue(Seat *s) {
assert(s);
if (s->in_gc_queue)
return;
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;
if (strlen(name) > 255)
return false;
return true;
}