logind-session.c revision 13f493dc9ace9861c1f27c4d37e8cd6d52fe6a32
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering/***
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering This file is part of systemd.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Copyright 2011 Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering systemd is free software; you can redistribute it and/or modify it
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering under the terms of the GNU Lesser General Public License as published by
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering (at your option) any later version.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering systemd is distributed in the hope that it will be useful, but
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Lesser General Public License for more details.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering You should have received a copy of the GNU Lesser General Public License
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering***/
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include <errno.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <fcntl.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include <linux/vt.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include <linux/kd.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include <signal.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include <string.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include <sys/ioctl.h>
13790add4bf648fed816361794d8277a75253410Lennart Poettering#include <unistd.h>
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "sd-id128.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "sd-messages.h"
a09561746f15b84da9471b5c4be74e53d19e4f3fLennart Poettering#include "strv.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "mkdir.h"
13790add4bf648fed816361794d8277a75253410Lennart Poettering#include "path-util.h"
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include "fileio.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "audit.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "bus-util.h"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek#include "bus-error.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "logind-session.h"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen#define RELEASE_USEC (20*USEC_PER_SEC)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic void session_remove_fifo(Session *s);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart PoetteringSession* session_new(Manager *m, const char *id) {
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering Session *s;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
7ccbd1ae843d77275f2c542582a9a80e5e058a70Lennart Poettering assert(m);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(session_id_valid(id));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s = new0(Session, 1);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->state_file = strappend("/run/systemd/sessions/", id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->state_file) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->devices = hashmap_new(devt_hash_func, devt_compare_func);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->devices) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s->state_file);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->id = basename(s->state_file);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (hashmap_put(m->sessions, s->id, s) < 0) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering hashmap_free(s->devices);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s->state_file);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->manager = m;
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->fifo_fd = -1;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering s->vtfd = -1;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return s;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringvoid session_free(Session *s) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering SessionDevice *sd;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->in_gc_queue)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_remove_fifo(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_drop_controller(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering while ((sd = hashmap_first(s->devices)))
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_device_free(sd);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering hashmap_free(s->devices);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->user) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_REMOVE(sessions_by_user, s->user->sessions, s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->user->display == s)
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->user->display = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat) {
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek if (s->seat->active == s)
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->seat->active = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat->pending_switch == s)
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->seat->pending_switch = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_evict_position(s->seat, s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->scope) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering hashmap_remove(s->manager->session_units, s->scope);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->scope);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->scope_job);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering sd_bus_message_unref(s->create_message);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->tty);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->display);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->remote_host);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->remote_user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->service);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->desktop);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering hashmap_remove(s->manager->sessions, s->id);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->state_file);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringvoid session_set_user(Session *s, User *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(!s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->user = u;
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_PREPEND(sessions_by_user, u->sessions, s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringint session_save(Session *s) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering _cleanup_free_ char *temp_path = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r = 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (!s->user)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -ESTALE;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!s->started)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering goto finish;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = fopen_temporary(s->state_file, &f, &temp_path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering goto finish;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering fchmod(fileno(f), 0644);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "# This is private data. Do not parse.\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "UID="UID_FMT"\n"
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering "USER=%s\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "ACTIVE=%i\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "STATE=%s\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "REMOTE=%i\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->user->uid,
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->user->name,
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_is_active(s),
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_state_to_string(session_get_state(s)),
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->remote);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->type >= 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->class >= 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->scope)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "SCOPE=%s\n", s->scope);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->scope_job)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->fifo_path)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "FIFO=%s\n", s->fifo_path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (s->seat)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f, "SEAT=%s\n", s->seat->id);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->tty)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering fprintf(f, "TTY=%s\n", s->tty);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->display)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering fprintf(f, "DISPLAY=%s\n", s->display);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->remote_host) {
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering _cleanup_free_ char *escaped;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering escaped = cescape(s->remote_host);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!escaped) {
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = -ENOMEM;
13790add4bf648fed816361794d8277a75253410Lennart Poettering goto finish;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering }
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering fprintf(f, "REMOTE_HOST=%s\n", escaped);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering }
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->remote_user) {
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering _cleanup_free_ char *escaped;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering escaped = cescape(s->remote_user);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!escaped) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = -ENOMEM;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering goto finish;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek }
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek fprintf(f, "REMOTE_USER=%s\n", escaped);
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek }
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->service) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering _cleanup_free_ char *escaped;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering escaped = cescape(s->service);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!escaped) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = -ENOMEM;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering goto finish;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
6f526243e6a638c2ea7bbdd07b963f57e110d120Evgeny Vereshchagin fprintf(f, "SERVICE=%s\n", escaped);
6f526243e6a638c2ea7bbdd07b963f57e110d120Evgeny Vereshchagin }
6f526243e6a638c2ea7bbdd07b963f57e110d120Evgeny Vereshchagin
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->desktop) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering _cleanup_free_ char *escaped;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering escaped = cescape(s->desktop);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!escaped) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = -ENOMEM;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering goto finish;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen fprintf(f, "DESKTOP=%s\n", escaped);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->seat && seat_has_vts(s->seat))
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek fprintf(f, "VTNR=%u\n", s->vtnr);
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->vtnr)
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek fprintf(f, "POS=%u\n", s->pos);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek if (s->leader > 0)
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek fprintf(f, "LEADER="PID_FMT"\n", s->leader);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->audit_id > 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (dual_timestamp_is_set(&s->timestamp))
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering fprintf(f,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "REALTIME="USEC_FMT"\n"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "MONOTONIC="USEC_FMT"\n",
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->timestamp.realtime,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->timestamp.monotonic);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek if (s->controller)
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek fprintf(f, "CONTROLLER=%s\n", s->controller);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering fflush(f);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (ferror(f) || rename(temp_path, s->state_file) < 0) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = -errno;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unlink(s->state_file);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unlink(temp_path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringfinish:
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringint session_load(Session *s) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering _cleanup_free_ char *remote = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *seat = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *vtnr = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *pos = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *leader = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *type = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *class = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *uid = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *realtime = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *monotonic = NULL,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *controller = NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering int k, r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = parse_env_file(s->state_file, NEWLINE,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "REMOTE", &remote,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "SCOPE", &s->scope,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "SCOPE_JOB", &s->scope_job,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "FIFO", &s->fifo_path,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "SEAT", &seat,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "TTY", &s->tty,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "DISPLAY", &s->display,
41891700e02daf0cab9e86908c76ac6f411bbd57Lennart Poettering "REMOTE_HOST", &s->remote_host,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "REMOTE_USER", &s->remote_user,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "SERVICE", &s->service,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "DESKTOP", &s->desktop,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "VTNR", &vtnr,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "POS", &pos,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "LEADER", &leader,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "TYPE", &type,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "CLASS", &class,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "UID", &uid,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "REALTIME", &realtime,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "MONOTONIC", &monotonic,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "CONTROLLER", &controller,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering NULL);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("Failed to read %s: %s", s->state_file, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->user) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering uid_t u;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering User *user;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!uid) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("UID not specified for session %s", s->id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -ENOENT;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = parse_uid(uid, &u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("Failed to parse UID value %s for session %s.", uid, s->id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!user) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("User of session %s not known.", s->id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -ENOENT;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering session_set_user(s, user);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (remote) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering k = parse_boolean(remote);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (k >= 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->remote = k;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (vtnr)
13790add4bf648fed816361794d8277a75253410Lennart Poettering safe_atou(vtnr, &s->vtnr);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (seat && !s->seat) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Seat *o;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering o = hashmap_get(s->manager->seats, seat);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (o)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = seat_attach_session(o, s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!o || r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_error("Cannot attach session %s to seat %s", s->id, seat);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->seat || !seat_has_vts(s->seat))
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->vtnr = 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (pos && s->seat) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned int npos;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering safe_atou(pos, &npos);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering seat_claim_position(s->seat, s, npos);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (leader) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering k = parse_pid(leader, &s->leader);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (k >= 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering audit_session_from_pid(s->leader, &s->audit_id);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (type) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering SessionType t;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering t = session_type_from_string(type);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (t >= 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->type = t;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (class) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering SessionClass c;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c = session_class_from_string(class);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c >= 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->class = c;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->fifo_path) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering int fd;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* If we open an unopened pipe for reading we will not
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering get an EOF. to trigger an EOF we hence open it for
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering reading, but close it right-away which then will
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering trigger the EOF. */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering fd = session_create_fifo(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering safe_close(fd);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (realtime) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned long long l;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->timestamp.realtime = l;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (monotonic) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned long long l;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->timestamp.monotonic = l;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (controller) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering session_set_controller(s, controller, false);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering else
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering session_restore_vt(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringint session_activate(Session *s) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt unsigned int num_pending;
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s->user);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering if (!s->seat)
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering return -ENOTSUP;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->seat->active == s)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* on seats with VTs, we let VTs manage session-switching */
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering if (seat_has_vts(s->seat)) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->vtnr)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -ENOTSUP;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering return chvt(s->vtnr);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* On seats without VTs, we implement session-switching in logind. We
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * try to pause all session-devices and wait until the session
13790add4bf648fed816361794d8277a75253410Lennart Poettering * controller acknowledged them. Once all devices are asleep, we simply
13790add4bf648fed816361794d8277a75253410Lennart Poettering * switch the active session and be done.
13790add4bf648fed816361794d8277a75253410Lennart Poettering * We save the session we want to switch to in seat->pending_switch and
13790add4bf648fed816361794d8277a75253410Lennart Poettering * seat_complete_switch() will perform the final switch. */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->seat->pending_switch = s;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* if no devices are running, immediately perform the session switch */
13790add4bf648fed816361794d8277a75253410Lennart Poettering num_pending = session_device_try_pause_all(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!num_pending)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering seat_complete_switch(s->seat);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int session_start_scope(Session *s) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek assert(s->user);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek assert(s->user->slice);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!s->scope) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering _cleanup_free_ char *description = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering char *scope, *job = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!description)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return log_oom();
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering scope = strjoin("session-", s->id, ".scope", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!scope)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return log_oom();
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error("Failed to start session scope %s: %s %s",
13790add4bf648fed816361794d8277a75253410Lennart Poettering scope, bus_error_message(&error, r), error.name);
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(scope);
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering } else {
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->scope = scope;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering free(s->scope_job);
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->scope_job = job;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->scope)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering hashmap_put(s->manager->session_units, s->scope, s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringint session_start(Session *s) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering int r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(s);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->user)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -ESTALE;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (s->started)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return 0;
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = user_start(s->user);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Create cgroup */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = session_start_scope(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
13790add4bf648fed816361794d8277a75253410Lennart Poettering MESSAGE_ID(SD_MESSAGE_SESSION_START),
13790add4bf648fed816361794d8277a75253410Lennart Poettering "SESSION_ID=%s", s->id,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "USER_ID=%s", s->user->name,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "LEADER="PID_FMT, s->leader,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "MESSAGE=New session %s of user %s.", s->id, s->user->name,
13790add4bf648fed816361794d8277a75253410Lennart Poettering NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!dual_timestamp_is_set(&s->timestamp))
13790add4bf648fed816361794d8277a75253410Lennart Poettering dual_timestamp_get(&s->timestamp);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat)
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_read_active_vt(s->seat);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->started = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_elect_display(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Save data */
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_save(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_save(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering seat_save(s->seat);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Send signals */
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_send_signal(s, true);
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_send_changed(s->user, "Sessions", "Display", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat->active == s)
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering else
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_send_changed(s->seat, "Sessions", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int session_stop_scope(Session *s, bool force) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering char *job = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!s->scope)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (force || manager_shall_kill(s->manager, s->user->name)) {
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering r = manager_stop_unit(s->manager, s->scope, &error, &job);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(s->scope_job);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->scope_job = job;
13790add4bf648fed816361794d8277a75253410Lennart Poettering } else {
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = manager_abandon_scope(s->manager, s->scope, &error);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return r;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringint session_stop(Session *s, bool force) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!s->user)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -ESTALE;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* We are going down, don't care about FIFOs anymore */
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_remove_fifo(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Kill cgroup */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = session_stop_scope(s, force);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->stopping = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_elect_display(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_save(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_save(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringint session_finalize(Session *s) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering int r = 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering SessionDevice *sd;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
15d91bff36c61d38df8edff258d1702a017a0e66Zbigniew Jędrzejewski-Szmek assert(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!s->user)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -ESTALE;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->started)
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
13790add4bf648fed816361794d8277a75253410Lennart Poettering MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
13790add4bf648fed816361794d8277a75253410Lennart Poettering "SESSION_ID=%s", s->id,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "USER_ID=%s", s->user->name,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "LEADER="PID_FMT, s->leader,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "MESSAGE=Removed session %s.", s->id,
13790add4bf648fed816361794d8277a75253410Lennart Poettering NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Kill session devices */
13790add4bf648fed816361794d8277a75253410Lennart Poettering while ((sd = hashmap_first(s->devices)))
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_device_free(sd);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering unlink(s->state_file);
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_add_to_gc_queue(s);
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_add_to_gc_queue(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->started) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_send_signal(s, false);
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->started = false;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (s->seat->active == s)
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_set_active(s->seat, NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_save(s->seat);
13790add4bf648fed816361794d8277a75253410Lennart Poettering seat_send_changed(s->seat, "Sessions", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_save(s->user);
13790add4bf648fed816361794d8277a75253410Lennart Poettering user_send_changed(s->user, "Sessions", "Display", NULL);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering Session *s = userdata;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(es);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s);
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering session_stop(s, false);
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid session_release(Session *s) {
15d91bff36c61d38df8edff258d1702a017a0e66Zbigniew Jędrzejewski-Szmek assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->started || s->stopping)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->timer_event_source)
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek sd_event_add_time(s->manager->event,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek &s->timer_event_source,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek CLOCK_MONOTONIC,
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering release_timeout_callback, s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidtbool session_is_active(Session *s) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!s->seat)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return true;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return s->seat->active == s;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringstatic int get_tty_atime(const char *tty, usec_t *atime) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt _cleanup_free_ char *p = NULL;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt struct stat st;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(tty);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(atime);
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (!path_is_absolute(tty)) {
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt p = strappend("/dev/", tty);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!p)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -ENOMEM;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt tty = p;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering } else if (!path_startswith(tty, "/dev/"))
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -ENOENT;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (lstat(tty, &st) < 0)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering return -errno;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering *atime = timespec_load(&st.st_atim);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering return 0;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering}
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poetteringstatic int get_process_ctty_atime(pid_t pid, usec_t *atime) {
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering _cleanup_free_ char *p = NULL;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering int r;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering assert(pid > 0);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering assert(atime);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering r = get_ctty(pid, NULL, &p);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (r < 0)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering return r;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering return get_tty_atime(p, atime);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering}
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poetteringint session_get_idle_hint(Session *s, dual_timestamp *t) {
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering usec_t atime = 0, n;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering int r;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering assert(s);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering /* Explicit idle hint is set */
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->idle_hint) {
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (t)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering *t = s->idle_hint_timestamp;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering return s->idle_hint;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering }
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering /* Graphical sessions should really implement a real
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering * idle hint logic */
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->display)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering goto dont_know;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering /* For sessions with an explicitly configured tty, let's check
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering * its atime */
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (s->tty) {
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering r = get_tty_atime(s->tty, &atime);
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering if (r >= 0)
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering goto found_atime;
e22aa3d3284709234f086ebebc13a905a295b7a7Lennart Poettering }
/* 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_swap_controller(Session *s, char *name) {
SessionDevice *sd;
char *c;
if (s->controller) {
c = s->controller;
s->controller = NULL;
manager_drop_busname(s->manager, c);
free(c);
/* 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;
}
/* 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) {
free(t);
return r;
}
session_swap_controller(s, t);
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_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);