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 #define RELEASE_USEC (20*USEC_PER_SEC)
45 static void session_remove_fifo(Session *s);
47 static unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
48 uint64_t u = *(const dev_t*)p;
50 return uint64_hash_func(&u, hash_key);
53 static int devt_compare_func(const void *_a, const void *_b) {
56 a = *(const dev_t*) _a;
57 b = *(const dev_t*) _b;
59 return a < b ? -1 : (a > b ? 1 : 0);
62 Session* session_new(Manager *m, const char *id) {
67 assert(session_id_valid(id));
73 s->state_file = strappend("/run/systemd/sessions/", id);
79 s->devices = hashmap_new(devt_hash_func, devt_compare_func);
86 s->id = basename(s->state_file);
88 if (hashmap_put(m->sessions, s->id, s) < 0) {
89 hashmap_free(s->devices);
102 void session_free(Session *s) {
108 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
110 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
112 session_remove_fifo(s);
114 session_drop_controller(s);
116 while ((sd = hashmap_first(s->devices)))
117 session_device_free(sd);
119 hashmap_free(s->devices);
122 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
124 if (s->user->display == s)
125 s->user->display = NULL;
129 if (s->seat->active == s)
130 s->seat->active = NULL;
131 if (s->seat->pending_switch == s)
132 s->seat->pending_switch = NULL;
134 seat_evict_position(s->seat, s);
135 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
139 hashmap_remove(s->manager->session_units, s->scope);
145 sd_bus_message_unref(s->create_message);
149 free(s->remote_host);
150 free(s->remote_user);
154 hashmap_remove(s->manager->sessions, s->id);
156 s->vt_source = sd_event_source_unref(s->vt_source);
162 void session_set_user(Session *s, User *u) {
167 LIST_PREPEND(sessions_by_user, u->sessions, s);
170 int session_save(Session *s) {
171 _cleanup_free_ char *temp_path = NULL;
172 _cleanup_fclose_ FILE *f = NULL;
183 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
187 r = fopen_temporary(s->state_file, &f, &temp_path);
193 fchmod(fileno(f), 0644);
196 "# This is private data. Do not parse.\n"
204 session_is_active(s),
205 session_state_to_string(session_get_state(s)),
209 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
212 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
215 fprintf(f, "SCOPE=%s\n", s->scope);
218 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
221 fprintf(f, "FIFO=%s\n", s->fifo_path);
224 fprintf(f, "SEAT=%s\n", s->seat->id);
227 fprintf(f, "TTY=%s\n", s->tty);
230 fprintf(f, "DISPLAY=%s\n", s->display);
233 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
236 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
239 fprintf(f, "SERVICE=%s\n", s->service);
242 fprintf(f, "DESKTOP=%s\n", s->desktop);
244 if (s->seat && seat_has_vts(s->seat))
245 fprintf(f, "VTNR=%u\n", s->vtnr);
248 fprintf(f, "POS=%u\n", s->pos);
251 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
254 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
256 if (dual_timestamp_is_set(&s->timestamp))
258 "REALTIME="USEC_FMT"\n"
259 "MONOTONIC="USEC_FMT"\n",
260 s->timestamp.realtime,
261 s->timestamp.monotonic);
264 fprintf(f, "CONTROLLER=%s\n", s->controller);
268 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
270 unlink(s->state_file);
276 log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
281 int session_load(Session *s) {
282 _cleanup_free_ char *remote = NULL,
298 r = parse_env_file(s->state_file, NEWLINE,
301 "SCOPE_JOB", &s->scope_job,
302 "FIFO", &s->fifo_path,
305 "DISPLAY", &s->display,
306 "REMOTE_HOST", &s->remote_host,
307 "REMOTE_USER", &s->remote_user,
308 "SERVICE", &s->service,
309 "DESKTOP", &s->desktop,
316 "REALTIME", &realtime,
317 "MONOTONIC", &monotonic,
318 "CONTROLLER", &controller,
322 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
331 log_error("UID not specified for session %s", s->id);
335 r = parse_uid(uid, &u);
337 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
341 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
343 log_error("User of session %s not known.", s->id);
347 session_set_user(s, user);
351 k = parse_boolean(remote);
357 safe_atou(vtnr, &s->vtnr);
359 if (seat && !s->seat) {
362 o = hashmap_get(s->manager->seats, seat);
364 r = seat_attach_session(o, s);
366 log_error("Cannot attach session %s to seat %s", s->id, seat);
369 if (!s->seat || !seat_has_vts(s->seat))
372 if (pos && s->seat) {
375 safe_atou(pos, &npos);
376 seat_claim_position(s->seat, s, npos);
380 k = parse_pid(leader, &s->leader);
382 audit_session_from_pid(s->leader, &s->audit_id);
388 t = session_type_from_string(type);
396 c = session_class_from_string(class);
404 /* If we open an unopened pipe for reading we will not
405 get an EOF. to trigger an EOF we hence open it for
406 reading, but close it right-away which then will
409 fd = session_create_fifo(s);
411 close_nointr_nofail(fd);
415 unsigned long long l;
416 if (sscanf(realtime, "%llu", &l) > 0)
417 s->timestamp.realtime = l;
421 unsigned long long l;
422 if (sscanf(monotonic, "%llu", &l) > 0)
423 s->timestamp.monotonic = l;
427 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
428 session_set_controller(s, controller, false);
430 session_restore_vt(s);
436 int session_activate(Session *s) {
437 unsigned int num_pending;
445 if (s->seat->active == s)
448 /* on seats with VTs, we let VTs manage session-switching */
449 if (seat_has_vts(s->seat)) {
453 return chvt(s->vtnr);
456 /* On seats without VTs, we implement session-switching in logind. We
457 * try to pause all session-devices and wait until the session
458 * controller acknowledged them. Once all devices are asleep, we simply
459 * switch the active session and be done.
460 * We save the session we want to switch to in seat->pending_switch and
461 * seat_complete_switch() will perform the final switch. */
463 s->seat->pending_switch = s;
465 /* if no devices are running, immediately perform the session switch */
466 num_pending = session_device_try_pause_all(s);
468 seat_complete_switch(s->seat);
473 static int session_start_scope(Session *s) {
478 assert(s->user->slice);
481 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
482 _cleanup_free_ char *description = NULL;
485 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
489 scope = strjoin("session-", s->id, ".scope", NULL);
493 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-session.service", &error, &job);
495 log_error("Failed to start session scope %s: %s %s",
496 scope, bus_error_message(&error, r), error.name);
508 hashmap_put(s->manager->session_units, s->scope, s);
513 int session_start(Session *s) {
524 r = user_start(s->user);
529 r = session_start_scope(s);
533 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
534 MESSAGE_ID(SD_MESSAGE_SESSION_START),
535 "SESSION_ID=%s", s->id,
536 "USER_ID=%s", s->user->name,
537 "LEADER=%lu", (unsigned long) s->leader,
538 "MESSAGE=New session %s of user %s.", s->id, s->user->name,
541 if (!dual_timestamp_is_set(&s->timestamp))
542 dual_timestamp_get(&s->timestamp);
545 seat_read_active_vt(s->seat);
556 session_send_signal(s, true);
557 user_send_changed(s->user, "Sessions", NULL);
559 if (s->seat->active == s)
560 seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
562 seat_send_changed(s->seat, "Sessions", NULL);
568 static int session_stop_scope(Session *s, bool force) {
569 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
578 if (force || manager_shall_kill(s->manager, s->user->name)) {
579 r = manager_stop_unit(s->manager, s->scope, &error, &job);
581 log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
588 r = manager_abandon_scope(s->manager, s->scope, &error);
590 log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
598 int session_stop(Session *s, bool force) {
606 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
608 /* We are going down, don't care about FIFOs anymore */
609 session_remove_fifo(s);
612 r = session_stop_scope(s, force);
622 int session_finalize(Session *s) {
632 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
633 MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
634 "SESSION_ID=%s", s->id,
635 "USER_ID=%s", s->user->name,
636 "LEADER=%lu", (unsigned long) s->leader,
637 "MESSAGE=Removed session %s.", s->id,
640 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
642 /* Kill session devices */
643 while ((sd = hashmap_first(s->devices)))
644 session_device_free(sd);
646 unlink(s->state_file);
647 session_add_to_gc_queue(s);
648 user_add_to_gc_queue(s->user);
651 session_send_signal(s, false);
656 if (s->seat->active == s)
657 seat_set_active(s->seat, NULL);
660 seat_send_changed(s->seat, "Sessions", NULL);
664 user_send_changed(s->user, "Sessions", NULL);
669 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
670 Session *s = userdata;
675 session_stop(s, false);
679 void session_release(Session *s) {
682 if (!s->started || s->stopping)
685 if (!s->timer_event_source)
686 sd_event_add_monotonic(s->manager->event, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s, &s->timer_event_source);
689 bool session_is_active(Session *s) {
695 return s->seat->active == s;
698 static int get_tty_atime(const char *tty, usec_t *atime) {
699 _cleanup_free_ char *p = NULL;
705 if (!path_is_absolute(tty)) {
706 p = strappend("/dev/", tty);
711 } else if (!path_startswith(tty, "/dev/"))
714 if (lstat(tty, &st) < 0)
717 *atime = timespec_load(&st.st_atim);
721 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
722 _cleanup_free_ char *p = NULL;
728 r = get_ctty(pid, NULL, &p);
732 return get_tty_atime(p, atime);
735 int session_get_idle_hint(Session *s, dual_timestamp *t) {
741 /* Explicit idle hint is set */
744 *t = s->idle_hint_timestamp;
749 /* Graphical sessions should really implement a real
754 /* For sessions with an explicitly configured tty, let's check
757 r = get_tty_atime(s->tty, &atime);
762 /* For sessions with a leader but no explicitly configured
763 * tty, let's check the controlling tty of the leader */
765 r = get_process_ctty_atime(s->leader, &atime);
772 *t = s->idle_hint_timestamp;
778 dual_timestamp_from_realtime(t, atime);
780 n = now(CLOCK_REALTIME);
782 if (s->manager->idle_action_usec <= 0)
785 return atime + s->manager->idle_action_usec <= n;
788 void session_set_idle_hint(Session *s, bool b) {
791 if (s->idle_hint == b)
795 dual_timestamp_get(&s->idle_hint_timestamp);
797 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
800 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
802 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
803 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
806 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
807 Session *s = userdata;
810 assert(s->fifo_fd == fd);
812 /* EOF on the FIFO means the session died abnormally. */
814 session_remove_fifo(s);
815 session_stop(s, false);
820 int session_create_fifo(Session *s) {
827 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
831 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
834 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
838 /* Open reading side */
839 if (s->fifo_fd < 0) {
840 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
846 if (!s->fifo_event_source) {
847 r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
851 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
856 /* Open writing side */
857 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
864 static void session_remove_fifo(Session *s) {
867 if (s->fifo_event_source)
868 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
870 if (s->fifo_fd >= 0) {
871 close_nointr_nofail(s->fifo_fd);
876 unlink(s->fifo_path);
882 bool session_check_gc(Session *s, bool drop_not_started) {
885 if (drop_not_started && !s->started)
891 if (s->fifo_fd >= 0) {
892 if (pipe_eof(s->fifo_fd) <= 0)
896 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
899 if (s->scope && manager_unit_is_active(s->manager, s->scope))
905 void session_add_to_gc_queue(Session *s) {
911 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
912 s->in_gc_queue = true;
915 SessionState session_get_state(Session *s) {
918 if (s->stopping || s->timer_event_source)
919 return SESSION_CLOSING;
922 return SESSION_OPENING;
924 if (session_is_active(s))
925 return SESSION_ACTIVE;
927 return SESSION_ONLINE;
930 int session_kill(Session *s, KillWho who, int signo) {
936 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
939 static int session_open_vt(Session *s) {
940 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
948 sprintf(path, "/dev/tty%u", s->vtnr);
949 s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
951 log_error("cannot open VT %s of session %s: %m", path, s->id);
958 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
962 ioctl(s->vtfd, VT_RELDISP, 1);
967 void session_mute_vt(Session *s) {
969 struct vt_mode mode = { 0 };
972 vt = session_open_vt(s);
976 r = ioctl(vt, KDSKBMODE, K_OFF);
980 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
985 sigaddset(&mask, SIGUSR1);
986 sigprocmask(SIG_BLOCK, &mask, NULL);
988 r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
992 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
993 * So we need a dummy handler here which just acknowledges *all* VT
994 * switch requests. */
995 mode.mode = VT_PROCESS;
996 mode.relsig = SIGUSR1;
997 mode.acqsig = SIGUSR1;
998 r = ioctl(vt, VT_SETMODE, &mode);
1005 log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1006 session_restore_vt(s);
1009 void session_restore_vt(Session *s) {
1010 _cleanup_free_ char *utf8;
1011 int vt, kb = K_XLATE;
1012 struct vt_mode mode = { 0 };
1014 vt = session_open_vt(s);
1018 s->vt_source = sd_event_source_unref(s->vt_source);
1020 ioctl(vt, KDSETMODE, KD_TEXT);
1022 if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1024 ioctl(vt, KDSKBMODE, kb);
1026 mode.mode = VT_AUTO;
1027 ioctl(vt, VT_SETMODE, &mode);
1029 close_nointr_nofail(vt);
1033 bool session_is_controller(Session *s, const char *sender) {
1036 return streq_ptr(s->controller, sender);
1039 static void session_swap_controller(Session *s, char *name) {
1042 if (s->controller) {
1043 manager_drop_busname(s->manager, s->controller);
1044 free(s->controller);
1045 s->controller = NULL;
1047 /* Drop all devices as they're now unused. Do that after the
1048 * controller is released to avoid sending out useles
1050 while ((sd = hashmap_first(s->devices)))
1051 session_device_free(sd);
1054 session_restore_vt(s);
1057 s->controller = name;
1061 int session_set_controller(Session *s, const char *sender, bool force) {
1068 if (session_is_controller(s, sender))
1070 if (s->controller && !force)
1077 r = manager_watch_busname(s->manager, sender);
1083 session_swap_controller(s, t);
1085 /* When setting a session controller, we forcibly mute the VT and set
1086 * it into graphics-mode. Applications can override that by changing
1087 * VT state after calling TakeControl(). However, this serves as a good
1088 * default and well-behaving controllers can now ignore VTs entirely.
1089 * Note that we reset the VT on ReleaseControl() and if the controller
1091 * If logind crashes/restarts, we restore the controller during restart
1092 * or reset the VT in case it crashed/exited, too. */
1098 void session_drop_controller(Session *s) {
1104 session_swap_controller(s, NULL);
1107 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1108 [SESSION_OPENING] = "opening",
1109 [SESSION_ONLINE] = "online",
1110 [SESSION_ACTIVE] = "active",
1111 [SESSION_CLOSING] = "closing"
1114 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1116 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1117 [SESSION_TTY] = "tty",
1118 [SESSION_X11] = "x11",
1119 [SESSION_WAYLAND] = "wayland",
1120 [SESSION_UNSPECIFIED] = "unspecified",
1123 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1125 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1126 [SESSION_USER] = "user",
1127 [SESSION_GREETER] = "greeter",
1128 [SESSION_LOCK_SCREEN] = "lock-screen",
1129 [SESSION_BACKGROUND] = "background"
1132 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1134 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1135 [KILL_LEADER] = "leader",
1139 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);