1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/ioctl.h>
32 #include "sd-messages.h"
36 #include "path-util.h"
40 #include "bus-error.h"
41 #include "logind-session.h"
43 static unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
44 uint64_t u = *(const dev_t*)p;
46 return uint64_hash_func(&u, hash_key);
49 static int devt_compare_func(const void *_a, const void *_b) {
52 a = *(const dev_t*) _a;
53 b = *(const dev_t*) _b;
55 return a < b ? -1 : (a > b ? 1 : 0);
58 Session* session_new(Manager *m, const char *id) {
63 assert(session_id_valid(id));
69 s->state_file = strappend("/run/systemd/sessions/", id);
75 s->devices = hashmap_new(devt_hash_func, devt_compare_func);
82 s->id = basename(s->state_file);
84 if (hashmap_put(m->sessions, s->id, s) < 0) {
85 hashmap_free(s->devices);
98 void session_free(Session *s) {
104 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
106 session_remove_fifo(s);
108 session_drop_controller(s);
110 while ((sd = hashmap_first(s->devices)))
111 session_device_free(sd);
113 hashmap_free(s->devices);
116 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
118 if (s->user->display == s)
119 s->user->display = NULL;
123 if (s->seat->active == s)
124 s->seat->active = NULL;
125 if (s->seat->pending_switch == s)
126 s->seat->pending_switch = NULL;
128 seat_evict_position(s->seat, s);
129 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
133 hashmap_remove(s->manager->session_units, s->scope);
139 sd_bus_message_unref(s->create_message);
143 free(s->remote_host);
144 free(s->remote_user);
147 hashmap_remove(s->manager->sessions, s->id);
153 void session_set_user(Session *s, User *u) {
158 LIST_PREPEND(sessions_by_user, u->sessions, s);
161 int session_save(Session *s) {
162 _cleanup_free_ char *temp_path = NULL;
163 _cleanup_fclose_ FILE *f = NULL;
174 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
178 r = fopen_temporary(s->state_file, &f, &temp_path);
184 fchmod(fileno(f), 0644);
187 "# This is private data. Do not parse.\n"
193 (unsigned long) s->user->uid,
195 session_is_active(s),
196 session_state_to_string(session_get_state(s)),
200 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
203 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
206 fprintf(f, "SCOPE=%s\n", s->scope);
209 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
212 fprintf(f, "FIFO=%s\n", s->fifo_path);
215 fprintf(f, "SEAT=%s\n", s->seat->id);
218 fprintf(f, "TTY=%s\n", s->tty);
221 fprintf(f, "DISPLAY=%s\n", s->display);
224 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
227 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
230 fprintf(f, "SERVICE=%s\n", s->service);
232 if (s->seat && seat_has_vts(s->seat))
233 fprintf(f, "VTNR=%u\n", s->vtnr);
236 fprintf(f, "POS=%u\n", s->pos);
239 fprintf(f, "LEADER=%lu\n", (unsigned long) s->leader);
242 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
244 if (dual_timestamp_is_set(&s->timestamp))
248 (unsigned long long) s->timestamp.realtime,
249 (unsigned long long) s->timestamp.monotonic);
252 fprintf(f, "CONTROLLER=%s\n", s->controller);
256 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
258 unlink(s->state_file);
264 log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
269 int session_load(Session *s) {
270 _cleanup_free_ char *remote = NULL,
286 r = parse_env_file(s->state_file, NEWLINE,
289 "SCOPE_JOB", &s->scope_job,
290 "FIFO", &s->fifo_path,
293 "DISPLAY", &s->display,
294 "REMOTE_HOST", &s->remote_host,
295 "REMOTE_USER", &s->remote_user,
296 "SERVICE", &s->service,
303 "REALTIME", &realtime,
304 "MONOTONIC", &monotonic,
305 "CONTROLLER", &controller,
309 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
318 log_error("UID not specified for session %s", s->id);
322 r = parse_uid(uid, &u);
324 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
328 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
330 log_error("User of session %s not known.", s->id);
334 session_set_user(s, user);
338 k = parse_boolean(remote);
344 safe_atou(vtnr, &s->vtnr);
346 if (seat && !s->seat) {
349 o = hashmap_get(s->manager->seats, seat);
351 r = seat_attach_session(o, s);
353 log_error("Cannot attach session %s to seat %s", s->id, seat);
356 if (!s->seat || !seat_has_vts(s->seat))
359 if (pos && s->seat) {
362 safe_atou(pos, &npos);
363 seat_claim_position(s->seat, s, npos);
367 k = parse_pid(leader, &s->leader);
369 audit_session_from_pid(s->leader, &s->audit_id);
375 t = session_type_from_string(type);
383 c = session_class_from_string(class);
391 /* If we open an unopened pipe for reading we will not
392 get an EOF. to trigger an EOF we hence open it for
393 reading, but close it right-away which then will
396 fd = session_create_fifo(s);
398 close_nointr_nofail(fd);
402 unsigned long long l;
403 if (sscanf(realtime, "%llu", &l) > 0)
404 s->timestamp.realtime = l;
408 unsigned long long l;
409 if (sscanf(monotonic, "%llu", &l) > 0)
410 s->timestamp.monotonic = l;
414 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
415 session_set_controller(s, controller, false);
417 session_restore_vt(s);
423 int session_activate(Session *s) {
424 unsigned int num_pending;
432 if (s->seat->active == s)
435 /* on seats with VTs, we let VTs manage session-switching */
436 if (seat_has_vts(s->seat)) {
440 return chvt(s->vtnr);
443 /* On seats without VTs, we implement session-switching in logind. We
444 * try to pause all session-devices and wait until the session
445 * controller acknowledged them. Once all devices are asleep, we simply
446 * switch the active session and be done.
447 * We save the session we want to switch to in seat->pending_switch and
448 * seat_complete_switch() will perform the final switch. */
450 s->seat->pending_switch = s;
452 /* if no devices are running, immediately perform the session switch */
453 num_pending = session_device_try_pause_all(s);
455 seat_complete_switch(s->seat);
460 static int session_start_scope(Session *s) {
465 assert(s->user->slice);
468 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
469 _cleanup_free_ char *description = NULL;
470 const char *kill_mode;
473 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
477 scope = strjoin("session-", s->id, ".scope", NULL);
481 kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
483 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job);
485 log_error("Failed to start session scope %s: %s %s",
486 scope, bus_error_message(&error, r), error.name);
498 hashmap_put(s->manager->session_units, s->scope, s);
503 int session_start(Session *s) {
514 r = user_start(s->user);
519 r = session_start_scope(s);
523 log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
524 MESSAGE_ID(SD_MESSAGE_SESSION_START),
525 "SESSION_ID=%s", s->id,
526 "USER_ID=%s", s->user->name,
527 "LEADER=%lu", (unsigned long) s->leader,
528 "MESSAGE=New session %s of user %s.", s->id, s->user->name,
531 if (!dual_timestamp_is_set(&s->timestamp))
532 dual_timestamp_get(&s->timestamp);
535 seat_read_active_vt(s->seat);
539 /* Save session data */
543 session_send_signal(s, true);
548 if (s->seat->active == s)
549 seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
551 seat_send_changed(s->seat, "Sessions", NULL);
554 user_send_changed(s->user, "Sessions", NULL);
559 static int session_stop_scope(Session *s) {
560 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
569 r = manager_stop_unit(s->manager, s->scope, &error, &job);
571 log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
581 int session_stop(Session *s) {
590 r = session_stop_scope(s);
598 int session_finalize(Session *s) {
608 log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
609 MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
610 "SESSION_ID=%s", s->id,
611 "USER_ID=%s", s->user->name,
612 "LEADER=%lu", (unsigned long) s->leader,
613 "MESSAGE=Removed session %s.", s->id,
616 /* Kill session devices */
617 while ((sd = hashmap_first(s->devices)))
618 session_device_free(sd);
620 unlink(s->state_file);
621 session_add_to_gc_queue(s);
622 user_add_to_gc_queue(s->user);
625 session_send_signal(s, false);
630 if (s->seat->active == s)
631 seat_set_active(s->seat, NULL);
633 seat_send_changed(s->seat, "Sessions", NULL);
637 user_send_changed(s->user, "Sessions", NULL);
643 bool session_is_active(Session *s) {
649 return s->seat->active == s;
652 static int get_tty_atime(const char *tty, usec_t *atime) {
653 _cleanup_free_ char *p = NULL;
659 if (!path_is_absolute(tty)) {
660 p = strappend("/dev/", tty);
665 } else if (!path_startswith(tty, "/dev/"))
668 if (lstat(tty, &st) < 0)
671 *atime = timespec_load(&st.st_atim);
675 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
676 _cleanup_free_ char *p = NULL;
682 r = get_ctty(pid, NULL, &p);
686 return get_tty_atime(p, atime);
689 int session_get_idle_hint(Session *s, dual_timestamp *t) {
695 /* Explicit idle hint is set */
698 *t = s->idle_hint_timestamp;
703 /* Graphical sessions should really implement a real
708 /* For sessions with an explicitly configured tty, let's check
711 r = get_tty_atime(s->tty, &atime);
716 /* For sessions with a leader but no explicitly configured
717 * tty, let's check the controlling tty of the leader */
719 r = get_process_ctty_atime(s->leader, &atime);
726 *t = s->idle_hint_timestamp;
732 dual_timestamp_from_realtime(t, atime);
734 n = now(CLOCK_REALTIME);
736 if (s->manager->idle_action_usec <= 0)
739 return atime + s->manager->idle_action_usec <= n;
742 void session_set_idle_hint(Session *s, bool b) {
745 if (s->idle_hint == b)
749 dual_timestamp_get(&s->idle_hint_timestamp);
751 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
754 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
756 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
757 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
760 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
761 Session *s = userdata;
764 assert(s->fifo_fd == fd);
766 /* EOF on the FIFO means the session died abnormally. */
768 session_remove_fifo(s);
774 int session_create_fifo(Session *s) {
781 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
785 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
788 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
792 /* Open reading side */
793 if (s->fifo_fd < 0) {
794 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
800 if (!s->fifo_event_source) {
801 r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
805 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
810 /* Open writing side */
811 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
818 void session_remove_fifo(Session *s) {
821 if (s->fifo_event_source)
822 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
824 if (s->fifo_fd >= 0) {
825 close_nointr_nofail(s->fifo_fd);
830 unlink(s->fifo_path);
836 bool session_check_gc(Session *s, bool drop_not_started) {
841 if (drop_not_started && !s->started)
847 if (s->fifo_fd >= 0) {
848 r = pipe_eof(s->fifo_fd);
856 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
859 if (s->scope && manager_unit_is_active(s->manager, s->scope))
865 void session_add_to_gc_queue(Session *s) {
871 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
872 s->in_gc_queue = true;
875 SessionState session_get_state(Session *s) {
879 return SESSION_OPENING;
882 return SESSION_CLOSING;
884 if (session_is_active(s))
885 return SESSION_ACTIVE;
887 return SESSION_ONLINE;
890 int session_kill(Session *s, KillWho who, int signo) {
896 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
899 static int session_open_vt(Session *s) {
908 sprintf(path, "/dev/tty%u", s->vtnr);
909 s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
911 log_error("cannot open VT %s of session %s: %m", path, s->id);
918 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
922 ioctl(s->vtfd, VT_RELDISP, 1);
927 void session_mute_vt(Session *s) {
929 struct vt_mode mode = { 0 };
932 vt = session_open_vt(s);
936 r = ioctl(vt, KDSKBMODE, K_OFF);
940 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
945 sigaddset(&mask, SIGUSR1);
946 sigprocmask(SIG_BLOCK, &mask, NULL);
948 r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
952 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
953 * So we need a dummy handler here which just acknowledges *all* VT
954 * switch requests. */
955 mode.mode = VT_PROCESS;
956 mode.relsig = SIGUSR1;
957 mode.acqsig = SIGUSR1;
958 r = ioctl(vt, VT_SETMODE, &mode);
965 log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
966 session_restore_vt(s);
969 void session_restore_vt(Session *s) {
970 _cleanup_free_ char *utf8;
971 int vt, kb = K_XLATE;
972 struct vt_mode mode = { 0 };
974 vt = session_open_vt(s);
978 sd_event_source_unref(s->vt_source);
981 ioctl(vt, KDSETMODE, KD_TEXT);
983 if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
985 ioctl(vt, KDSKBMODE, kb);
988 ioctl(vt, VT_SETMODE, &mode);
990 close_nointr_nofail(vt);
994 bool session_is_controller(Session *s, const char *sender) {
997 return streq_ptr(s->controller, sender);
1000 static void session_swap_controller(Session *s, char *name) {
1003 if (s->controller) {
1004 manager_drop_busname(s->manager, s->controller);
1005 free(s->controller);
1006 s->controller = NULL;
1008 /* Drop all devices as they're now unused. Do that after the
1009 * controller is released to avoid sending out useles
1011 while ((sd = hashmap_first(s->devices)))
1012 session_device_free(sd);
1015 session_restore_vt(s);
1018 s->controller = name;
1022 int session_set_controller(Session *s, const char *sender, bool force) {
1029 if (session_is_controller(s, sender))
1031 if (s->controller && !force)
1038 r = manager_watch_busname(s->manager, sender);
1044 session_swap_controller(s, t);
1046 /* When setting a session controller, we forcibly mute the VT and set
1047 * it into graphics-mode. Applications can override that by changing
1048 * VT state after calling TakeControl(). However, this serves as a good
1049 * default and well-behaving controllers can now ignore VTs entirely.
1050 * Note that we reset the VT on ReleaseControl() and if the controller
1052 * If logind crashes/restarts, we restore the controller during restart
1053 * or reset the VT in case it crashed/exited, too. */
1059 void session_drop_controller(Session *s) {
1065 session_swap_controller(s, NULL);
1068 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1069 [SESSION_OPENING] = "opening",
1070 [SESSION_ONLINE] = "online",
1071 [SESSION_ACTIVE] = "active",
1072 [SESSION_CLOSING] = "closing"
1075 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1077 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1078 [SESSION_TTY] = "tty",
1079 [SESSION_X11] = "x11",
1080 [SESSION_UNSPECIFIED] = "unspecified"
1083 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1085 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1086 [SESSION_USER] = "user",
1087 [SESSION_GREETER] = "greeter",
1088 [SESSION_LOCK_SCREEN] = "lock-screen",
1089 [SESSION_BACKGROUND] = "background"
1092 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1094 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1095 [KILL_LEADER] = "leader",
1099 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);