logind-session.c revision 5f41d1f10fd97e93517b6a762b1bec247f4d1171
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2011 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <errno.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <fcntl.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <linux/vt.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <linux/kd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <signal.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <string.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/ioctl.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <unistd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "sd-id128.h"
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack#include "sd-messages.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "strv.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "mkdir.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "path-util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "fileio.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "audit.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "bus-util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "bus-error.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "logind-session.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#define RELEASE_USEC (20*USEC_PER_SEC)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void session_remove_fifo(Session *s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poetteringstatic unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint64_t u = *(const dev_t*)p;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return uint64_hash_func(&u, hash_key);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int devt_compare_func(const void *_a, const void *_b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dev_t a, b;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering a = *(const dev_t*) _a;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b = *(const dev_t*) _b;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return a < b ? -1 : (a > b ? 1 : 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringSession* session_new(Manager *m, const char *id) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Session *s;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(m);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(session_id_valid(id));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s = new0(Session, 1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->state_file = strappend("/run/systemd/sessions/", id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->state_file) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->devices = hashmap_new(devt_hash_func, devt_compare_func);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->devices) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->state_file);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->id = basename(s->state_file);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (hashmap_put(m->sessions, s->id, s) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_free(s->devices);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->state_file);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->manager = m;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->fifo_fd = -1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->vtfd = -1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return s;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackvoid session_free(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SessionDevice *sd;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert(s);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (s->in_gc_queue)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack s->timer_event_source = sd_event_source_unref(s->timer_event_source);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_remove_fifo(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_drop_controller(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering while ((sd = hashmap_first(s->devices)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_device_free(sd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_free(s->devices);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->user) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(sessions_by_user, s->user->sessions, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->user->display == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->user->display = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat->active == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->seat->active = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat->pending_switch == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->seat->pending_switch = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering seat_evict_position(s->seat, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->scope) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_remove(s->manager->session_units, s->scope);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->scope);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->scope_job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_bus_message_unref(s->create_message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->tty);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->display);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->remote_host);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->remote_user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->service);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->desktop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_remove(s->manager->sessions, s->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->vt_source = sd_event_source_unref(s->vt_source);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->state_file);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringvoid session_set_user(Session *s, User *u) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(!s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->user = u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_PREPEND(sessions_by_user, u->sessions, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_save(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *temp_path = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (!s->user)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return -ESTALE;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->started)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = fopen_temporary(s->state_file, &f, &temp_path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fchmod(fileno(f), 0644);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "# This is private data. Do not parse.\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "UID="UID_FMT"\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "USER=%s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "ACTIVE=%i\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "STATE=%s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REMOTE=%i\n",
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering s->user->uid,
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering s->user->name,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_is_active(s),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_state_to_string(session_get_state(s)),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->remote);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->type >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->class >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->scope)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "SCOPE=%s\n", s->scope);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->scope_job)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->fifo_path)
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering fprintf(f, "FIFO=%s\n", s->fifo_path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "SEAT=%s\n", s->seat->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->tty)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "TTY=%s\n", s->tty);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->display)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "DISPLAY=%s\n", s->display);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->remote_host)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->remote_user)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (s->service)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack fprintf(f, "SERVICE=%s\n", s->service);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->desktop)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "DESKTOP=%s\n", s->desktop);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat && seat_has_vts(s->seat))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "VTNR=%u\n", s->vtnr);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->vtnr)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "POS=%u\n", s->pos);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->leader > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "LEADER="PID_FMT"\n", s->leader);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->audit_id > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (dual_timestamp_is_set(&s->timestamp))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REALTIME="USEC_FMT"\n"
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "MONOTONIC="USEC_FMT"\n",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->timestamp.realtime,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->timestamp.monotonic);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->controller)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "CONTROLLER=%s\n", s->controller);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fflush(f);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (ferror(f) || rename(temp_path, s->state_file) < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unlink(s->state_file);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unlink(temp_path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringfinish:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_load(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *remote = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *seat = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *vtnr = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *pos = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *leader = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *type = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *class = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *uid = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *realtime = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *monotonic = NULL,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *controller = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int k, r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = parse_env_file(s->state_file, NEWLINE,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REMOTE", &remote,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "SCOPE", &s->scope,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "SCOPE_JOB", &s->scope_job,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "FIFO", &s->fifo_path,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "SEAT", &seat,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "TTY", &s->tty,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "DISPLAY", &s->display,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REMOTE_HOST", &s->remote_host,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REMOTE_USER", &s->remote_user,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "SERVICE", &s->service,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "DESKTOP", &s->desktop,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "VTNR", &vtnr,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "POS", &pos,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "LEADER", &leader,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "TYPE", &type,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "CLASS", &class,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "UID", &uid,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "REALTIME", &realtime,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "MONOTONIC", &monotonic,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "CONTROLLER", &controller,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack NULL);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (r < 0) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_error("Failed to read %s: %s", s->state_file, strerror(-r));
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return r;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (!s->user) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uid_t u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering User *user;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!uid) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("UID not specified for session %s", s->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOENT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = parse_uid(uid, &u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to parse UID value %s for session %s.", uid, s->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!user) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_error("User of session %s not known.", s->id);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return -ENOENT;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_set_user(s, user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (remote) {
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering k = parse_boolean(remote);
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering if (k >= 0)
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering s->remote = k;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering }
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (vtnr)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering safe_atou(vtnr, &s->vtnr);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (seat && !s->seat) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Seat *o;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering o = hashmap_get(s->manager->seats, seat);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (o)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = seat_attach_session(o, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!o || r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Cannot attach session %s to seat %s", s->id, seat);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->seat || !seat_has_vts(s->seat))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->vtnr = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (pos && s->seat) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned int npos;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering safe_atou(pos, &npos);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering seat_claim_position(s->seat, s, npos);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (leader) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering k = parse_pid(leader, &s->leader);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (k >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering audit_session_from_pid(s->leader, &s->audit_id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (type) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack SessionType t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = session_type_from_string(type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (t >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->type = t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (class) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SessionClass c;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering c = session_class_from_string(class);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (c >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->class = c;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->fifo_path) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int fd;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* If we open an unopened pipe for reading we will not
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering get an EOF. to trigger an EOF we hence open it for
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering reading, but close it right-away which then will
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering trigger the EOF. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack fd = session_create_fifo(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (fd >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (realtime) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned long long l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->timestamp.realtime = l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (monotonic) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned long long l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->timestamp.monotonic = l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (controller) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_set_controller(s, controller, false);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_restore_vt(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_activate(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned int num_pending;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->seat)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOTSUP;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat->active == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* on seats with VTs, we let VTs manage session-switching */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (seat_has_vts(s->seat)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->vtnr)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOTSUP;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return chvt(s->vtnr);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* On seats without VTs, we implement session-switching in logind. We
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * try to pause all session-devices and wait until the session
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * controller acknowledged them. Once all devices are asleep, we simply
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * switch the active session and be done.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * We save the session we want to switch to in seat->pending_switch and
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * seat_complete_switch() will perform the final switch. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->seat->pending_switch = s;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* if no devices are running, immediately perform the session switch */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering num_pending = session_device_try_pause_all(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!num_pending)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering seat_complete_switch(s->seat);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int session_start_scope(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s->user->slice);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->scope) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *description = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char *scope, *job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!description)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering scope = strjoin("session-", s->id, ".scope", NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!scope)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", &error, &job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to start session scope %s: %s %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering scope, bus_error_message(&error, r), error.name);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(scope);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->scope = scope;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->scope_job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->scope_job = job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->scope)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering hashmap_put(s->manager->session_units, s->scope, s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_start(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->user)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ESTALE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->started)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = user_start(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Create cgroup */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = session_start_scope(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MESSAGE_ID(SD_MESSAGE_SESSION_START),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "SESSION_ID=%s", s->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "USER_ID=%s", s->user->name,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "LEADER=%lu", (unsigned long) s->leader,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "MESSAGE=New session %s of user %s.", s->id, s->user->name,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering if (!dual_timestamp_is_set(&s->timestamp))
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering dual_timestamp_get(&s->timestamp);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering if (s->seat)
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering seat_read_active_vt(s->seat);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering s->started = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Save data */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_save(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering user_save(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack seat_save(s->seat);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Send signals */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_send_signal(s, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering user_send_changed(s->user, "Sessions", NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (s->seat->active == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering seat_send_changed(s->seat, "Sessions", NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
700ff4d97311902a440109a2c081731ab6ae8a20Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int session_stop_scope(Session *s) {
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack char *job;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack int r;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack assert(s);
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack if (!s->scope)
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (manager_shall_kill(s->manager, s->user->name)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = manager_stop_unit(s->manager, s->scope, &error, &job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(s->scope_job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->scope_job = job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = manager_abandon_scope(s->manager, s->scope, &error);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_stop(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!s->user)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ESTALE;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We are going down, don't care about FIFOs anymore */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_remove_fifo(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Kill cgroup */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = session_stop_scope(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s->stopping = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering session_save(s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering user_save(s->user);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint session_finalize(Session *s) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r = 0;
SessionDevice *sd;
assert(s);
if (!s->user)
return -ESTALE;
if (s->started)
log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER=%lu", (unsigned long) s->leader,
"MESSAGE=Removed session %s.", s->id,
NULL);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
/* Kill session devices */
while ((sd = hashmap_first(s->devices)))
session_device_free(sd);
unlink(s->state_file);
session_add_to_gc_queue(s);
user_add_to_gc_queue(s->user);
if (s->started) {
session_send_signal(s, false);
s->started = false;
}
if (s->seat) {
if (s->seat->active == s)
seat_set_active(s->seat, NULL);
seat_save(s->seat);
seat_send_changed(s->seat, "Sessions", NULL);
}
user_save(s->user);
user_send_changed(s->user, "Sessions", 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);
return 0;
}
void session_release(Session *s) {
assert(s);
if (!s->started || s->stopping)
return;
if (!s->timer_event_source)
sd_event_add_monotonic(s->manager->event, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s, &s->timer_event_source);
}
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);
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_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
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);
if (s->fifo_event_source)
s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
if (s->fifo_fd >= 0) {
close_nointr_nofail(s->fifo_fd);
s->fifo_fd = -1;
}
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);
if (s->stopping || s->timer_event_source)
return SESSION_CLOSING;
if (s->scope_job)
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)
return -1;
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 -1;
}
return s->vtfd;
}
static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
Session *s = data;
if (s->vtfd >= 0)
ioctl(s->vtfd, VT_RELDISP, 1);
return 0;
}
void session_mute_vt(Session *s) {
int vt, r;
struct vt_mode mode = { 0 };
sigset_t mask;
vt = session_open_vt(s);
if (vt < 0)
return;
r = ioctl(vt, KDSKBMODE, K_OFF);
if (r < 0)
goto error;
r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
if (r < 0)
goto error;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, NULL);
r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
if (r < 0)
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 = SIGUSR1;
mode.acqsig = SIGUSR1;
r = ioctl(vt, VT_SETMODE, &mode);
if (r < 0)
goto error;
return;
error:
log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
session_restore_vt(s);
}
void session_restore_vt(Session *s) {
_cleanup_free_ char *utf8;
int vt, kb = K_XLATE;
struct vt_mode mode = { 0 };
vt = session_open_vt(s);
if (vt < 0)
return;
s->vt_source = sd_event_source_unref(s->vt_source);
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);
close_nointr_nofail(vt);
s->vtfd = -1;
}
bool session_is_controller(Session *s, const char *sender) {
assert(s);
return streq_ptr(s->controller, sender);
}
static void session_swap_controller(Session *s, char *name) {
SessionDevice *sd;
if (s->controller) {
manager_drop_busname(s->manager, s->controller);
free(s->controller);
s->controller = NULL;
/* Drop all devices as they're now unused. Do that after the
* controller is released to avoid sending out useles
* dbus signals. */
while ((sd = hashmap_first(s->devices)))
session_device_free(sd);
if (!name)
session_restore_vt(s);
}
s->controller = name;
session_save(s);
}
int session_set_controller(Session *s, const char *sender, bool force) {
char *t;
int r;
assert(s);
assert(sender);
if (session_is_controller(s, sender))
return 0;
if (s->controller && !force)
return -EBUSY;
t = strdup(sender);
if (!t)
return -ENOMEM;
r = manager_watch_busname(s->manager, sender);
if (r) {
free(t);
return r;
}
session_swap_controller(s, t);
/* 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. */
session_mute_vt(s);
return 0;
}
void session_drop_controller(Session *s) {
assert(s);
if (!s->controller)
return;
session_swap_controller(s, NULL);
}
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_TTY] = "tty",
[SESSION_X11] = "x11",
[SESSION_WAYLAND] = "wayland",
[SESSION_UNSPECIFIED] = "unspecified",
};
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);