logind-session.c revision 38599489e49e840291516488a3ef1b4a56198c58
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen This file is part of systemd.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Copyright 2011 Lennart Poettering
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is free software; you can redistribute it and/or modify it
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen under the terms of the GNU Lesser General Public License as published by
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen (at your option) any later version.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen systemd is distributed in the hope that it will be useful, but
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen Lesser General Public License for more details.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen You should have received a copy of the GNU Lesser General Public License
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
e3dca0089b7b50e2ec21409d1292727921d06102Tom GundersenSession* session_new(Manager *m, const char *id) {
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen s->state_file = strappend("/run/systemd/sessions/", id);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen s->timer_event_source = sd_event_source_unref(s->timer_event_source);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen LIST_REMOVE(sessions_by_user, s->user->sessions, s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen hashmap_remove(s->manager->session_units, s->scope);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen LIST_PREPEND(sessions_by_user, u->sessions, s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = fopen_temporary(s->state_file, &f, &temp_path);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "# This is private data. Do not parse.\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "ACTIVE=%i\n"
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen "REMOTE=%i\n",
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen session_state_to_string(session_get_state(s)),
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen return log_error_errno(r, "Failed to read %s: %m", s->state_file);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_error("UID not specified for session %s", s->id);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_error("Failed to parse UID value %s for session %s.", uid, s->id);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen user = hashmap_get(s->manager->users, UID_TO_PTR(u));
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_error("User of session %s not known.", s->id);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (!o || r < 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen log_error("Cannot attach session %s to seat %s", s->id, seat);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned int npos;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen audit_session_from_pid(s->leader, &s->audit_id);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* If we open an unopened pipe for reading we will not
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen get an EOF. to trigger an EOF we hence open it for
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen writing, but close it right away which then will
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen trigger the EOF. This will happen immediately if no
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen other process has the FIFO open for writing, i. e.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen when the session died before logind (re)started. */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned long long l;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen unsigned long long l;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* on seats with VTs, we let VTs manage session-switching */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* On seats without VTs, we implement session-switching in logind. We
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * try to pause all session-devices and wait until the session
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * controller acknowledged them. Once all devices are asleep, we simply
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * switch the active session and be done.
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * We save the session we want to switch to in seat->pending_switch and
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen * seat_complete_switch() will perform the final switch. */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen /* if no devices are running, immediately perform the session switch */
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen num_pending = session_device_try_pause_all(s);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen scope = strjoin("session-", s->id, ".scope", NULL);
e3dca0089b7b50e2ec21409d1292727921d06102Tom Gundersen r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
if (s->scope)
assert(s);
if (!s->user)
return -ESTALE;
if (s->started)
r = session_start_scope(s);
NULL);
if (s->seat)
s->started = true;
session_save(s);
if (s->seat)
session_send_signal(s, true);
if (s->seat) {
assert(s);
if (!s->scope)
assert(s);
if (!s->user)
return -ESTALE;
if (s->seat)
s->stopping = true;
session_save(s);
assert(s);
if (!s->user)
return -ESTALE;
if (s->started)
NULL);
if (s->seat)
if (s->started) {
session_send_signal(s, false);
s->started = false;
if (s->seat) {
assert(s);
session_stop(s, false);
assert(s);
if (s->timer_event_source)
&s->timer_event_source,
assert(s);
if (!s->seat)
return -ENOMEM;
tty = p;
return -ENOENT;
return -errno;
assert(s);
if (s->idle_hint) {
*t = s->idle_hint_timestamp;
return s->idle_hint;
if (s->display)
goto dont_know;
if (s->tty) {
goto found_atime;
if (s->leader > 0) {
goto found_atime;
*t = s->idle_hint_timestamp;
assert(s);
if (s->idle_hint == b)
s->idle_hint = b;
if (s->seat)
assert(s);
session_stop(s, false);
assert(s);
if (!s->fifo_path) {
return -ENOMEM;
return -errno;
if (s->fifo_fd < 0) {
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);
return -errno;
assert(s);
if (s->fifo_path) {
assert(s);
if (!s->user)
if (s->fifo_fd >= 0) {
assert(s);
if (s->in_gc_queue)
s->in_gc_queue = true;
assert(s);
return SESSION_CLOSING;
return SESSION_OPENING;
if (session_is_active(s))
return SESSION_ACTIVE;
return SESSION_ONLINE;
assert(s);
if (!s->scope)
return -ESRCH;
return -ENODEV;
if (s->vtfd >= 0)
return s->vtfd;
if (s->vtfd < 0)
return s->vtfd;
int vt, r;
if (vt < 0)
return vt;
s->vtnr);
goto error;
s->vtnr);
goto error;
s->vtnr);
goto error;
s->vtnr);
goto error;
if (vt < 0)
assert(s);
if (s->vtfd < 0)
assert(s);
if (!s->controller)
if (!notify)
assert(s);
assert(s);
return -EBUSY;
if (!name)
return -ENOMEM;
r = session_prepare_vt(s);
session_release_controller(s, true);
session_save(s);
assert(s);
if (!s->controller)
session_release_controller(s, false);
session_save(s);