logind-session.c revision bf7825ae69f53a7e80a740547919833e49ed1df4
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering/***
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering This file is part of systemd.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Copyright 2011 Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering systemd is free software; you can redistribute it and/or modify it
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering under the terms of the GNU Lesser General Public License as published by
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering (at your option) any later version.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering systemd is distributed in the hope that it will be useful, but
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Lesser General Public License for more details.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering You should have received a copy of the GNU Lesser General Public License
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering***/
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <string.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <unistd.h>
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include <sys/epoll.h>
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include <fcntl.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <systemd/sd-id128.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <systemd/sd-messages.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "strv.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "util.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "mkdir.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "path-util.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "fileio.h"
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering#include "dbus-common.h"
93cc7779e0c121b75183920173f37cd1ee9d59cfThomas Hindoe Paaboel Andersen#include "logind-session.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart PoetteringSession* session_new(Manager *m, const char *id) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Session *s;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering assert(m);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(session_id_valid(id));
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s = new0(Session, 1);
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (!s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->state_file = strappend("/run/systemd/sessions/", id);
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (!s->state_file) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->id = path_get_file_name(s->state_file);
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (hashmap_put(m->sessions, s->id, s) < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->state_file);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering s->manager = m;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->fifo_fd = -1;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringvoid session_free(Session *s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->in_gc_queue)
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering LIST_REMOVE(Session, gc_queue, s->manager->session_gc_queue, s);
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering session_drop_controller(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->user) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering LIST_REMOVE(Session, sessions_by_user, s->user->sessions, s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->user->display == s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->user->display = NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->seat) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->seat->active == s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->seat->active = NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->scope) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering hashmap_remove(s->manager->session_units, s->scope);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->scope);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->scope_job);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (s->create_message)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering dbus_message_unref(s->create_message);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->tty);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->display);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->remote_host);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->remote_user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->service);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering hashmap_remove(s->manager->sessions, s->id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering session_remove_fifo(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s->state_file);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering free(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringvoid session_set_user(Session *s, User *u) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(!s->user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->user = u;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering LIST_PREPEND(Session, sessions_by_user, u->sessions, s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint session_save(Session *s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering _cleanup_free_ char *temp_path = NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int r = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s->user)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ESTALE;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s->started)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering goto finish;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering r = fopen_temporary(s->state_file, &f, &temp_path);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering goto finish;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s->user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fchmod(fileno(f), 0644);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "# This is private data. Do not parse.\n"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "UID=%lu\n"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "USER=%s\n"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "ACTIVE=%i\n"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "STATE=%s\n"
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering "REMOTE=%i\n",
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering (unsigned long) s->user->uid,
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering s->user->name,
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering session_is_active(s),
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering session_state_to_string(session_get_state(s)),
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering s->remote);
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (s->type >= 0)
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->class >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->scope)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "SCOPE=%s\n", s->scope);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->scope_job)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->fifo_path)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "FIFO=%s\n", s->fifo_path);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->seat)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "SEAT=%s\n", s->seat->id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->tty)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "TTY=%s\n", s->tty);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->display)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "DISPLAY=%s\n", s->display);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->remote_host)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->remote_user)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->service)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "SERVICE=%s\n", s->service);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->seat && seat_has_vts(s->seat))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "VTNR=%i\n", s->vtnr);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->leader > 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "LEADER=%lu\n", (unsigned long) s->leader);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->audit_id > 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (dual_timestamp_is_set(&s->timestamp))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fprintf(f,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "REALTIME=%llu\n"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "MONOTONIC=%llu\n",
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering (unsigned long long) s->timestamp.realtime,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering (unsigned long long) s->timestamp.monotonic);
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering fflush(f);
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (ferror(f) || rename(temp_path, s->state_file) < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering r = -errno;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering unlink(s->state_file);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering unlink(temp_path);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringfinish:
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return r;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint session_load(Session *s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering _cleanup_free_ char *remote = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *seat = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *vtnr = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *leader = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *audit_id = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *type = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *class = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *uid = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *realtime = NULL,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering *monotonic = NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering int k, r;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering assert(s);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering r = parse_env_file(s->state_file, NEWLINE,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "REMOTE", &remote,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "SCOPE", &s->scope,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "SCOPE_JOB", &s->scope_job,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "FIFO", &s->fifo_path,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "SEAT", &seat,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "TTY", &s->tty,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "DISPLAY", &s->display,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "REMOTE_HOST", &s->remote_host,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "REMOTE_USER", &s->remote_user,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "SERVICE", &s->service,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "VTNR", &vtnr,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "LEADER", &leader,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "TYPE", &type,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering "CLASS", &class,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "UID", &uid,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "REALTIME", &realtime,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering "MONOTONIC", &monotonic,
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering NULL);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering log_error("Failed to read %s: %s", s->state_file, strerror(-r));
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (!s->user) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering uid_t u;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering User *user;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (!uid) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering log_error("UID not specified for session %s", s->id);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return -ENOENT;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering r = parse_uid(uid, &u);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (r < 0) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering log_error("Failed to parse UID value %s for session %s.", uid, s->id);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return r;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (!user) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering log_error("User of session %s not known.", s->id);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return -ENOENT;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering session_set_user(s, user);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (remote) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering k = parse_boolean(remote);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (k >= 0)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering s->remote = k;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (seat && !s->seat) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Seat *o;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering o = hashmap_get(s->manager->seats, seat);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (o)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering seat_attach_session(o, s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (vtnr && s->seat && seat_has_vts(s->seat)) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int v;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering k = safe_atoi(vtnr, &v);
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (k >= 0 && v >= 1)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->vtnr = v;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (leader) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering k = parse_pid(leader, &s->leader);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (k >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering audit_session_from_pid(s->leader, &s->audit_id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (type) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering SessionType t;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering t = session_type_from_string(type);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (t >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->type = t;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (class) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering SessionClass c;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering c = session_class_from_string(class);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (c >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->class = c;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->fifo_path) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int fd;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* If we open an unopened pipe for reading we will not
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering get an EOF. to trigger an EOF we hence open it for
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering reading, but close it right-away which then will
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering trigger the EOF. */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering fd = session_create_fifo(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (fd >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering close_nointr_nofail(fd);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (realtime) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering unsigned long long l;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->timestamp.realtime = l;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (monotonic) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering unsigned long long l;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->timestamp.monotonic = l;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint session_activate(Session *s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s->user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->vtnr <= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOTSUP;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s->seat)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOTSUP;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->seat->active == s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(seat_has_vts(s->seat));
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return chvt(s->vtnr);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringstatic int session_link_x11_socket(Session *s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering _cleanup_free_ char *t = NULL, *f = NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering char *c;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering size_t k;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s->user);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s->user->runtime_path);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (s->user->display)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s->display || !display_is_local(s->display))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering k = strspn(s->display+1, "0123456789");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering f = new(char, sizeof("/tmp/.X11-unix/X") + k);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!f)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return log_oom();
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering c = stpcpy(f, "/tmp/.X11-unix/X");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering memcpy(c, s->display+1, k);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering c[k] = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (access(f, F_OK) < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering log_warning("Session %s has display %s with non-existing socket %s.", s->id, s->display, f);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOENT;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Note that this cannot be in a subdir to avoid
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * vulnerabilities since we are privileged but the runtime
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * path is owned by the user */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering t = strappend(s->user->runtime_path, "/X11-display");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!t)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return log_oom();
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (link(f, t) < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (errno == EEXIST) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering unlink(t);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (link(f, t) >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering goto done;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (symlink(f, t) < 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (errno == EEXIST) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering unlink(t);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (symlink(f, t) >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering goto done;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering log_error("Failed to link %s to %s: %m", f, t);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -errno;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringdone:
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering log_info("Linked %s to %s.", f, t);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s->user->display = s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return 0;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering}
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poetteringstatic int session_start_scope(Session *s) {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering DBusError error;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering int r;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering assert(s);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering assert(s->user);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering assert(s->user->slice);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering dbus_error_init(&error);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (!s->scope) {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering _cleanup_free_ char *description = NULL;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering const char *kill_mode;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering char *scope, *job;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (!description)
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return log_oom();
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering scope = strjoin("session-", s->id, ".scope", NULL);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (!scope)
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return log_oom();
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (r < 0) {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering log_error("Failed to start session scope %s: %s %s",
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering scope, bus_error(&error, r), error.name);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering dbus_error_free(&error);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering free(scope);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return r;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering } else {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering s->scope = scope;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering free(s->scope_job);
s->scope_job = job;
}
}
if (s->scope)
hashmap_put(s->manager->session_units, s->scope, s);
return 0;
}
int session_start(Session *s) {
int r;
assert(s);
if (!s->user)
return -ESTALE;
if (s->started)
return 0;
r = user_start(s->user);
if (r < 0)
return r;
/* Create cgroup */
r = session_start_scope(s);
if (r < 0)
return r;
log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
MESSAGE_ID(SD_MESSAGE_SESSION_START),
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER=%lu", (unsigned long) s->leader,
"MESSAGE=New session %s of user %s.", s->id, s->user->name,
NULL);
/* Create X11 symlink */
session_link_x11_socket(s);
if (!dual_timestamp_is_set(&s->timestamp))
dual_timestamp_get(&s->timestamp);
if (s->seat)
seat_read_active_vt(s->seat);
s->started = true;
/* Save session data */
session_save(s);
user_save(s->user);
session_send_signal(s, true);
if (s->seat) {
seat_save(s->seat);
if (s->seat->active == s)
seat_send_changed(s->seat, "Sessions\0ActiveSession\0");
else
seat_send_changed(s->seat, "Sessions\0");
}
user_send_changed(s->user, "Sessions\0");
return 0;
}
static int session_stop_scope(Session *s) {
DBusError error;
char *job;
int r;
assert(s);
dbus_error_init(&error);
if (!s->scope)
return 0;
r = manager_stop_unit(s->manager, s->scope, &error, &job);
if (r < 0) {
log_error("Failed to stop session scope: %s", bus_error(&error, r));
dbus_error_free(&error);
return r;
}
free(s->scope_job);
s->scope_job = job;
return 0;
}
static int session_unlink_x11_socket(Session *s) {
_cleanup_free_ char *t = NULL;
int r;
assert(s);
assert(s->user);
if (s->user->display != s)
return 0;
s->user->display = NULL;
t = strappend(s->user->runtime_path, "/X11-display");
if (!t)
return log_oom();
r = unlink(t);
return r < 0 ? -errno : 0;
}
int session_stop(Session *s) {
int r;
assert(s);
if (!s->user)
return -ESTALE;
/* Kill cgroup */
r = session_stop_scope(s);
session_save(s);
return r;
}
int session_finalize(Session *s) {
int r = 0;
assert(s);
if (!s->user)
return -ESTALE;
if (s->started)
log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
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);
/* Remove X11 symlink */
session_unlink_x11_socket(s);
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_send_changed(s->seat, "Sessions\0");
seat_save(s->seat);
}
user_send_changed(s->user, "Sessions\0");
user_save(s->user);
return r;
}
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\0"
"IdleSinceHint\0"
"IdleSinceHintMonotonic\0");
if (s->seat)
seat_send_changed(s->seat,
"IdleHint\0"
"IdleSinceHint\0"
"IdleSinceHintMonotonic\0");
user_send_changed(s->user,
"IdleHint\0"
"IdleSinceHint\0"
"IdleSinceHintMonotonic\0");
manager_send_changed(s->manager,
"IdleHint\0"
"IdleSinceHint\0"
"IdleSinceHintMonotonic\0");
}
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) {
struct epoll_event ev = {};
s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
if (s->fifo_fd < 0)
return -errno;
r = hashmap_put(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1), s);
if (r < 0)
return r;
ev.events = 0;
ev.data.u32 = FD_OTHER_BASE + s->fifo_fd;
if (epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_ADD, s->fifo_fd, &ev) < 0)
return -errno;
}
/* Open writing side */
r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
if (r < 0)
return -errno;
return r;
}
void session_remove_fifo(Session *s) {
assert(s);
if (s->fifo_fd >= 0) {
assert_se(hashmap_remove(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1)) == s);
assert_se(epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->fifo_fd, NULL) == 0);
close_nointr_nofail(s->fifo_fd);
s->fifo_fd = -1;
session_save(s);
user_save(s->user);
}
if (s->fifo_path) {
unlink(s->fifo_path);
free(s->fifo_path);
s->fifo_path = NULL;
}
}
int session_check_gc(Session *s, bool drop_not_started) {
int r;
assert(s);
if (drop_not_started && !s->started)
return 0;
if (!s->user)
return 0;
if (s->fifo_fd >= 0) {
r = pipe_eof(s->fifo_fd);
if (r < 0)
return r;
if (r == 0)
return 1;
}
if (s->scope_job)
return 1;
if (s->scope)
return manager_unit_is_active(s->manager, s->scope) != 0;
return 0;
}
void session_add_to_gc_queue(Session *s) {
assert(s);
if (s->in_gc_queue)
return;
LIST_PREPEND(Session, gc_queue, s->manager->session_gc_queue, s);
s->in_gc_queue = true;
}
SessionState session_get_state(Session *s) {
assert(s);
if (s->closing)
return SESSION_CLOSING;
if (s->scope_job)
return SESSION_OPENING;
if (s->fifo_fd < 0)
return SESSION_CLOSING;
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);
}
bool session_is_controller(Session *s, const char *sender)
{
assert(s);
return streq_ptr(s->controller, sender);
}
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_drop_controller(s);
s->controller = t;
return 0;
}
void session_drop_controller(Session *s) {
assert(s);
if (!s->controller)
return;
manager_drop_busname(s->manager, s->controller);
free(s->controller);
s->controller = 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_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);