logind-session.c revision b12e56156e5f363ebb8dc4ea5c10f5fd0665dc9d
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/***
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2011 Lennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering***/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <errno.h>
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner#include <fcntl.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <linux/vt.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <linux/kd.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <signal.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <string.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <sys/ioctl.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <unistd.h>
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers#include "sd-id128.h"
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers#include "sd-messages.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "strv.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "mkdir.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "path-util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "fileio.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "audit.h"
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek#include "bus-util.h"
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar#include "bus-error.h"
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar#include "logind-session.h"
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#define RELEASE_USEC (20*USEC_PER_SEC)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic void session_remove_fifo(Session *s);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
7085053a437456ab87d726f3697002dd811fdf7aDaniel WallaceSession* session_new(Manager *m, const char *id) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Session *s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(session_id_valid(id));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = new0(Session, 1);
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->state_file = strappend("/run/systemd/sessions/", id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s->state_file) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering s->devices = hashmap_new(devt_hash_func, devt_compare_func);
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering if (!s->devices) {
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering free(s->state_file);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->id = basename(s->state_file);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (hashmap_put(m->sessions, s->id, s) < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering hashmap_free(s->devices);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->state_file);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
ff9b60f38bf68eba4a47cabff14547d92e083214Torstein Husebø s->manager = m;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar s->fifo_fd = -1;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar s->vtfd = -1;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar return s;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar}
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletarvoid session_free(Session *s) {
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar SessionDevice *sd;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar assert(s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->in_gc_queue)
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar s->timer_event_source = sd_event_source_unref(s->timer_event_source);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar session_remove_fifo(s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar session_drop_controller(s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar while ((sd = hashmap_first(s->devices)))
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar session_device_free(sd);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar hashmap_free(s->devices);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->user) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt LIST_REMOVE(sessions_by_user, s->user->sessions, s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->user->display == s)
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar s->user->display = NULL;
63229aa1abdb98aa69fda9819ed2f40c8082762bLennart Poettering }
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->seat) {
b344bcbbfda8fbe14dadc5aa4b5dfb3ced6d76e2Lennart Poettering if (s->seat->active == s)
ff49bc3212cb07d850dcfd59940539773a0be26fMichal Schmidt s->seat->active = NULL;
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->seat->pending_switch == s)
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar s->seat->pending_switch = NULL;
b344bcbbfda8fbe14dadc5aa4b5dfb3ced6d76e2Lennart Poettering
ff49bc3212cb07d850dcfd59940539773a0be26fMichal Schmidt seat_evict_position(s->seat, s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar }
63229aa1abdb98aa69fda9819ed2f40c8082762bLennart Poettering
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar if (s->scope) {
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar hashmap_remove(s->manager->session_units, s->scope);
a34286684ebb78dd3db0d7f34feb2c121c9d00ccMichal Sekletar free(s->scope);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->scope_job);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_message_unref(s->create_message);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->tty);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->display);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->remote_host);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->remote_user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->service);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->desktop);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering hashmap_remove(s->manager->sessions, s->id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->state_file);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringvoid session_set_user(Session *s, User *u) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(!s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->user = u;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering LIST_PREPEND(sessions_by_user, u->sessions, s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmekint session_save(Session *s) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_free_ char *temp_path = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_fclose_ FILE *f = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int r = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(s);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!s->user)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return -ESTALE;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (!s->started)
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers return 0;
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers r = fopen_temporary(s->state_file, &f, &temp_path);
ffc06c3513d9a0693c7f810d03b20705127ba55aKay Sievers if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers goto finish;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
6046278f405b3ebaf84fcf17f6e834c4c4bd6a42Djalal Harouni assert(s->user);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers fchmod(fileno(f), 0644);
6046278f405b3ebaf84fcf17f6e834c4c4bd6a42Djalal Harouni
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f,
ff9b60f38bf68eba4a47cabff14547d92e083214Torstein Husebø "# This is private data. Do not parse.\n"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "UID="UID_FMT"\n"
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers "USER=%s\n"
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers "ACTIVE=%i\n"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "STATE=%s\n"
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers "REMOTE=%i\n",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->user->uid,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->user->name,
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers session_is_active(s),
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers session_state_to_string(session_get_state(s)),
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers s->remote);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->type >= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->class >= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering if (s->scope)
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering fprintf(f, "SCOPE=%s\n", s->scope);
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering if (s->scope_job)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->fifo_path)
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering fprintf(f, "FIFO=%s\n", s->fifo_path);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering if (s->seat)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "SEAT=%s\n", s->seat->id);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (s->tty)
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering fprintf(f, "TTY=%s\n", s->tty);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (s->display)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "DISPLAY=%s\n", s->display);
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->remote_host) {
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering _cleanup_free_ char *escaped;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering escaped = cescape(s->remote_host);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (!escaped) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "REMOTE_HOST=%s\n", escaped);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (s->remote_user) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna _cleanup_free_ char *escaped;
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna escaped = cescape(s->remote_user);
7568345034f2890af745747783c5abfbf6eccf0fLennart Poettering if (!escaped) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = -ENOMEM;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen fprintf(f, "REMOTE_USER=%s\n", escaped);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->service) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *escaped;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers escaped = cescape(s->service);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!escaped) {
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering r = -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "SERVICE=%s\n", escaped);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->desktop) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *escaped;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering escaped = cescape(s->desktop);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!escaped) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering }
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "DESKTOP=%s\n", escaped);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->seat && seat_has_vts(s->seat))
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers fprintf(f, "VTNR=%u\n", s->vtnr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (!s->vtnr)
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering fprintf(f, "POS=%u\n", s->pos);
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering if (s->leader > 0)
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering fprintf(f, "LEADER="PID_FMT"\n", s->leader);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->audit_id > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (dual_timestamp_is_set(&s->timestamp))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "REALTIME="USEC_FMT"\n"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "MONOTONIC="USEC_FMT"\n",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->timestamp.realtime,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->timestamp.monotonic);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->controller)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fprintf(f, "CONTROLLER=%s\n", s->controller);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fflush(f);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (ferror(f) || rename(temp_path, s->state_file) < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = -errno;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unlink(s->state_file);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unlink(temp_path);
2b6bf07dd23bb467099d213c97b3875c5e453491Zbigniew Jędrzejewski-Szmek }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint session_load(Session *s) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *remote = NULL,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *seat = NULL,
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek *vtnr = NULL,
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt *pos = NULL,
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt *leader = NULL,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *type = NULL,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *class = NULL,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *uid = NULL,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *realtime = NULL,
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers *monotonic = NULL,
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer *controller = NULL;
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int k, r;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = parse_env_file(s->state_file, NEWLINE,
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek "REMOTE", &remote,
0732ef7acf37473847992888bcb6446726d9d877Zbigniew Jędrzejewski-Szmek "SCOPE", &s->scope,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SCOPE_JOB", &s->scope_job,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "FIFO", &s->fifo_path,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SEAT", &seat,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "TTY", &s->tty,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "DISPLAY", &s->display,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "REMOTE_HOST", &s->remote_host,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "REMOTE_USER", &s->remote_user,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SERVICE", &s->service,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "DESKTOP", &s->desktop,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "VTNR", &vtnr,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "POS", &pos,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "LEADER", &leader,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "TYPE", &type,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "CLASS", &class,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "UID", &uid,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "REALTIME", &realtime,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "MONOTONIC", &monotonic,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "CONTROLLER", &controller,
7c2d80944afb4196f2eff614e8da1450dffcbeaaThomas Hindoe Paaboel Andersen NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to read %s: %s", s->state_file, strerror(-r));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s->user) {
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering uid_t u;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering User *user;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!uid) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("UID not specified for session %s", s->id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = parse_uid(uid, &u);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to parse UID value %s for session %s.", uid, s->id);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
6b2b6f30e38d67b032d6bdc6b47ae05e143e96c5Michal Schmidt if (!user) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("User of session %s not known.", s->id);
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering return -ENOENT;
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering session_set_user(s, user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (remote) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering k = parse_boolean(remote);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (k >= 0)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers s->remote = k;
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering }
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering if (vtnr)
e1636421f46db6d06fbd028ef20a3113fa3e11f8Lennart Poettering safe_atou(vtnr, &s->vtnr);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (seat && !s->seat) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers Seat *o;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer o = hashmap_get(s->manager->seats, seat);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (o)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = seat_attach_session(o, s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!o || r < 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering log_error("Cannot attach session %s to seat %s", s->id, seat);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!s->seat || !seat_has_vts(s->seat))
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s->vtnr = 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (pos && s->seat) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering unsigned int npos;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering safe_atou(pos, &npos);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering seat_claim_position(s->seat, s, npos);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
c62e11ce3966c55d23520b9f0785c7e839cf7f37Lennart Poettering
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (leader) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt k = parse_pid(leader, &s->leader);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (k >= 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering audit_session_from_pid(s->leader, &s->audit_id);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (type) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering SessionType t;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering t = session_type_from_string(type);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (t >= 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s->type = t;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (class) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering SessionClass c;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering c = session_class_from_string(class);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (c >= 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s->class = c;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (s->fifo_path) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int fd;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* If we open an unopened pipe for reading we will not
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering get an EOF. to trigger an EOF we hence open it for
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering reading, but close it right-away which then will
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering trigger the EOF. */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering fd = session_create_fifo(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering safe_close(fd);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (realtime) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering unsigned long long l;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s->timestamp.realtime = l;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (monotonic) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering unsigned long long l;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering s->timestamp.monotonic = l;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (controller) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering session_set_controller(s, controller, false);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering else
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering session_restore_vt(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering}
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringint session_activate(Session *s) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering unsigned int num_pending;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(s->user);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!s->seat)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -ENOTSUP;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (s->seat->active == s)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* on seats with VTs, we let VTs manage session-switching */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (seat_has_vts(s->seat)) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!s->vtnr)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return -ENOTSUP;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return chvt(s->vtnr);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering }
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* On seats without VTs, we implement session-switching in logind. We
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * try to pause all session-devices and wait until the session
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * controller acknowledged them. Once all devices are asleep, we simply
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * switch the active session and be done.
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * We save the session we want to switch to in seat->pending_switch and
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * seat_complete_switch() will perform the final switch. */
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->seat->pending_switch = s;
82c1d8f4eb74ddd9be2c9b9b56d9dc564c599effLennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* if no devices are running, immediately perform the session switch */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering num_pending = session_device_try_pause_all(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!num_pending)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering seat_complete_switch(s->seat);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering return 0;
a86a47ce1f63476631635fbcbc10af8877172114Lennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic int session_start_scope(Session *s) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
2ebcf936702e8e511098711b4add885372360018Zbigniew Jędrzejewski-Szmek assert(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(s->user);
31cf921abbeafc9dae2d5c777f3e2285e6f4c19dJan Synacek assert(s->user->slice);
2ebcf936702e8e511098711b4add885372360018Zbigniew Jędrzejewski-Szmek
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!s->scope) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering _cleanup_free_ char *description = NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering char *scope, *job = NULL;
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!description)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return log_oom();
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering scope = strjoin("session-", s->id, ".scope", NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!scope)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return log_oom();
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to start session scope %s: %s %s",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering scope, bus_error_message(&error, r), error.name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(scope);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers return r;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers } else {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers s->scope = scope;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers free(s->scope_job);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers s->scope_job = job;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->scope)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering hashmap_put(s->manager->session_units, s->scope, s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmekint session_start(Session *s) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek if (!s->user)
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek return -ESTALE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->started)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = user_start(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Create cgroup */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = session_start_scope(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen MESSAGE_ID(SD_MESSAGE_SESSION_START),
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen "SESSION_ID=%s", s->id,
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen "USER_ID=%s", s->user->name,
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen "LEADER="PID_FMT, s->leader,
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers "MESSAGE=New session %s of user %s.", s->id, s->user->name,
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers NULL);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (!dual_timestamp_is_set(&s->timestamp))
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers dual_timestamp_get(&s->timestamp);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
de33fc625725d199629ed074d6278504deb23debLennart Poettering if (s->seat)
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers seat_read_active_vt(s->seat);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers s->started = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_elect_display(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Save data */
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering session_save(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_save(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->seat)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_save(s->seat);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Send signals */
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers session_send_signal(s, true);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_send_changed(s->user, "Sessions", "Display", NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->seat) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->seat->active == s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_send_changed(s->seat, "Sessions", NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic int session_stop_scope(Session *s, bool force) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering char *job = NULL;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering int r;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering assert(s);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (!s->scope)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering return 0;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (force || manager_shall_kill(s->manager, s->user->name)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = manager_stop_unit(s->manager, s->scope, &error, &job);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(s->scope_job);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->scope_job = job;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = manager_abandon_scope(s->manager, s->scope, &error);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint session_stop(Session *s, bool force) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s->user)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ESTALE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We are going down, don't care about FIFOs anymore */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering session_remove_fifo(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Kill cgroup */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = session_stop_scope(s, force);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s->stopping = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_elect_display(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering session_save(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_save(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint session_finalize(Session *s) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering SessionDevice *sd;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s->user)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ESTALE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->started)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "SESSION_ID=%s", s->id,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "USER_ID=%s", s->user->name,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "LEADER="PID_FMT, s->leader,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "MESSAGE=Removed session %s.", s->id,
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers NULL);
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner /* Kill session devices */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering while ((sd = hashmap_first(s->devices)))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering session_device_free(sd);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unlink(s->state_file);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering session_add_to_gc_queue(s);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering user_add_to_gc_queue(s->user);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (s->started) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers session_send_signal(s, false);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt s->started = false;
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (s->seat) {
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers if (s->seat->active == s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_set_active(s->seat, NULL);
4d7859d173282e16bb75254c2b4ec14a915ef30bKay Sievers
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_save(s->seat);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering seat_send_changed(s->seat, "Sessions", NULL);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
user_save(s->user);
user_send_changed(s->user, "Sessions", "Display", NULL);
return r;
}
static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
Session *s = userdata;
assert(es);
assert(s);
session_stop(s, false);
return 0;
}
void session_release(Session *s) {
assert(s);
if (!s->started || s->stopping)
return;
if (!s->timer_event_source)
sd_event_add_time(s->manager->event,
&s->timer_event_source,
CLOCK_MONOTONIC,
now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
release_timeout_callback, s);
}
bool session_is_active(Session *s) {
assert(s);
if (!s->seat)
return true;
return s->seat->active == s;
}
static int get_tty_atime(const char *tty, usec_t *atime) {
_cleanup_free_ char *p = NULL;
struct stat st;
assert(tty);
assert(atime);
if (!path_is_absolute(tty)) {
p = strappend("/dev/", tty);
if (!p)
return -ENOMEM;
tty = p;
} else if (!path_startswith(tty, "/dev/"))
return -ENOENT;
if (lstat(tty, &st) < 0)
return -errno;
*atime = timespec_load(&st.st_atim);
return 0;
}
static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
_cleanup_free_ char *p = NULL;
int r;
assert(pid > 0);
assert(atime);
r = get_ctty(pid, NULL, &p);
if (r < 0)
return r;
return get_tty_atime(p, atime);
}
int session_get_idle_hint(Session *s, dual_timestamp *t) {
usec_t atime = 0, n;
int r;
assert(s);
/* Explicit idle hint is set */
if (s->idle_hint) {
if (t)
*t = s->idle_hint_timestamp;
return s->idle_hint;
}
/* Graphical sessions should really implement a real
* idle hint logic */
if (s->display)
goto dont_know;
/* For sessions with an explicitly configured tty, let's check
* its atime */
if (s->tty) {
r = get_tty_atime(s->tty, &atime);
if (r >= 0)
goto found_atime;
}
/* For sessions with a leader but no explicitly configured
* tty, let's check the controlling tty of the leader */
if (s->leader > 0) {
r = get_process_ctty_atime(s->leader, &atime);
if (r >= 0)
goto found_atime;
}
dont_know:
if (t)
*t = s->idle_hint_timestamp;
return 0;
found_atime:
if (t)
dual_timestamp_from_realtime(t, atime);
n = now(CLOCK_REALTIME);
if (s->manager->idle_action_usec <= 0)
return 0;
return atime + s->manager->idle_action_usec <= n;
}
void session_set_idle_hint(Session *s, bool b) {
assert(s);
if (s->idle_hint == b)
return;
s->idle_hint = b;
dual_timestamp_get(&s->idle_hint_timestamp);
session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
if (s->seat)
seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
}
static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Session *s = userdata;
assert(s);
assert(s->fifo_fd == fd);
/* EOF on the FIFO means the session died abnormally. */
session_remove_fifo(s);
session_stop(s, false);
return 1;
}
int session_create_fifo(Session *s) {
int r;
assert(s);
/* Create FIFO */
if (!s->fifo_path) {
r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
if (r < 0)
return r;
if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
return -ENOMEM;
if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
return -errno;
}
/* Open reading side */
if (s->fifo_fd < 0) {
s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
if (s->fifo_fd < 0)
return -errno;
}
if (!s->fifo_event_source) {
r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
if (r < 0)
return r;
r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0)
return r;
}
/* Open writing side */
r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
if (r < 0)
return -errno;
return r;
}
static void session_remove_fifo(Session *s) {
assert(s);
s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
s->fifo_fd = safe_close(s->fifo_fd);
if (s->fifo_path) {
unlink(s->fifo_path);
free(s->fifo_path);
s->fifo_path = NULL;
}
}
bool session_check_gc(Session *s, bool drop_not_started) {
assert(s);
if (drop_not_started && !s->started)
return false;
if (!s->user)
return false;
if (s->fifo_fd >= 0) {
if (pipe_eof(s->fifo_fd) <= 0)
return true;
}
if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
return true;
if (s->scope && manager_unit_is_active(s->manager, s->scope))
return true;
return false;
}
void session_add_to_gc_queue(Session *s) {
assert(s);
if (s->in_gc_queue)
return;
LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
s->in_gc_queue = true;
}
SessionState session_get_state(Session *s) {
assert(s);
/* always check closing first */
if (s->stopping || s->timer_event_source)
return SESSION_CLOSING;
if (s->scope_job || s->fifo_fd < 0)
return SESSION_OPENING;
if (session_is_active(s))
return SESSION_ACTIVE;
return SESSION_ONLINE;
}
int session_kill(Session *s, KillWho who, int signo) {
assert(s);
if (!s->scope)
return -ESRCH;
return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
}
static int session_open_vt(Session *s) {
char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
if (s->vtnr < 1)
return -ENODEV;
if (s->vtfd >= 0)
return s->vtfd;
sprintf(path, "/dev/tty%u", s->vtnr);
s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
if (s->vtfd < 0) {
log_error("cannot open VT %s of session %s: %m", path, s->id);
return -errno;
}
return s->vtfd;
}
int session_prepare_vt(Session *s) {
int vt, r;
struct vt_mode mode = { 0 };
if (s->vtnr < 1)
return 0;
vt = session_open_vt(s);
if (vt < 0)
return vt;
r = fchown(vt, s->user->uid, -1);
if (r < 0) {
r = -errno;
log_error("Cannot change owner of /dev/tty%u: %m", s->vtnr);
goto error;
}
r = ioctl(vt, KDSKBMODE, K_OFF);
if (r < 0) {
r = -errno;
log_error("Cannot set K_OFF on /dev/tty%u: %m", s->vtnr);
goto error;
}
r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
if (r < 0) {
r = -errno;
log_error("Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr);
goto error;
}
/* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
* So we need a dummy handler here which just acknowledges *all* VT
* switch requests. */
mode.mode = VT_PROCESS;
mode.relsig = SIGRTMIN;
mode.acqsig = SIGRTMIN + 1;
r = ioctl(vt, VT_SETMODE, &mode);
if (r < 0) {
r = -errno;
log_error("Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr);
goto error;
}
return 0;
error:
session_restore_vt(s);
return r;
}
void session_restore_vt(Session *s) {
_cleanup_free_ char *utf8 = NULL;
int vt, kb = K_XLATE;
struct vt_mode mode = { 0 };
vt = session_open_vt(s);
if (vt < 0)
return;
ioctl(vt, KDSETMODE, KD_TEXT);
if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
kb = K_UNICODE;
ioctl(vt, KDSKBMODE, kb);
mode.mode = VT_AUTO;
ioctl(vt, VT_SETMODE, &mode);
fchown(vt, 0, -1);
s->vtfd = safe_close(s->vtfd);
}
bool session_is_controller(Session *s, const char *sender) {
assert(s);
return streq_ptr(s->controller, sender);
}
static void session_release_controller(Session *s, bool notify) {
_cleanup_free_ char *name = NULL;
SessionDevice *sd;
if (!s->controller)
return;
name = s->controller;
/* By resetting the controller before releasing the devices, we won't
* send notification signals. This avoids sending useless notifications
* if the controller is released on disconnects. */
if (!notify)
s->controller = NULL;
while ((sd = hashmap_first(s->devices)))
session_device_free(sd);
s->controller = NULL;
manager_drop_busname(s->manager, name);
}
int session_set_controller(Session *s, const char *sender, bool force) {
_cleanup_free_ char *name = NULL;
int r;
assert(s);
assert(sender);
if (session_is_controller(s, sender))
return 0;
if (s->controller && !force)
return -EBUSY;
name = strdup(sender);
if (!name)
return -ENOMEM;
r = manager_watch_busname(s->manager, name);
if (r)
return r;
/* When setting a session controller, we forcibly mute the VT and set
* it into graphics-mode. Applications can override that by changing
* VT state after calling TakeControl(). However, this serves as a good
* default and well-behaving controllers can now ignore VTs entirely.
* Note that we reset the VT on ReleaseControl() and if the controller
* exits.
* If logind crashes/restarts, we restore the controller during restart
* or reset the VT in case it crashed/exited, too. */
r = session_prepare_vt(s);
if (r < 0) {
manager_drop_busname(s->manager, name);
return r;
}
session_release_controller(s, true);
s->controller = name;
name = NULL;
session_save(s);
return 0;
}
void session_drop_controller(Session *s) {
assert(s);
if (!s->controller)
return;
session_release_controller(s, false);
session_save(s);
session_restore_vt(s);
}
static const char* const session_state_table[_SESSION_STATE_MAX] = {
[SESSION_OPENING] = "opening",
[SESSION_ONLINE] = "online",
[SESSION_ACTIVE] = "active",
[SESSION_CLOSING] = "closing"
};
DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
static const char* const session_type_table[_SESSION_TYPE_MAX] = {
[SESSION_UNSPECIFIED] = "unspecified",
[SESSION_TTY] = "tty",
[SESSION_X11] = "x11",
[SESSION_WAYLAND] = "wayland",
[SESSION_MIR] = "mir",
[SESSION_WEB] = "web",
};
DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
static const char* const session_class_table[_SESSION_CLASS_MAX] = {
[SESSION_USER] = "user",
[SESSION_GREETER] = "greeter",
[SESSION_LOCK_SCREEN] = "lock-screen",
[SESSION_BACKGROUND] = "background"
};
DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
static const char* const kill_who_table[_KILL_WHO_MAX] = {
[KILL_LEADER] = "leader",
[KILL_ALL] = "all"
};
DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);