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);
148 hashmap_remove(s->manager->sessions, s->id);
154 void session_set_user(Session *s, User *u) {
159 LIST_PREPEND(sessions_by_user, u->sessions, s);
162 int session_save(Session *s) {
163 _cleanup_free_ char *temp_path = NULL;
164 _cleanup_fclose_ FILE *f = NULL;
175 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
179 r = fopen_temporary(s->state_file, &f, &temp_path);
185 fchmod(fileno(f), 0644);
188 "# This is private data. Do not parse.\n"
194 (unsigned long) s->user->uid,
196 session_is_active(s),
197 session_state_to_string(session_get_state(s)),
201 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
204 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
207 fprintf(f, "SCOPE=%s\n", s->scope);
210 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
213 fprintf(f, "FIFO=%s\n", s->fifo_path);
216 fprintf(f, "SEAT=%s\n", s->seat->id);
219 fprintf(f, "TTY=%s\n", s->tty);
222 fprintf(f, "DISPLAY=%s\n", s->display);
225 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
228 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
231 fprintf(f, "SERVICE=%s\n", s->service);
234 fprintf(f, "DESKTOP=%s\n", s->desktop);
236 if (s->seat && seat_has_vts(s->seat))
237 fprintf(f, "VTNR=%u\n", s->vtnr);
240 fprintf(f, "POS=%u\n", s->pos);
243 fprintf(f, "LEADER=%lu\n", (unsigned long) s->leader);
246 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
248 if (dual_timestamp_is_set(&s->timestamp))
252 (unsigned long long) s->timestamp.realtime,
253 (unsigned long long) s->timestamp.monotonic);
256 fprintf(f, "CONTROLLER=%s\n", s->controller);
260 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
262 unlink(s->state_file);
268 log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
273 int session_load(Session *s) {
274 _cleanup_free_ char *remote = NULL,
290 r = parse_env_file(s->state_file, NEWLINE,
293 "SCOPE_JOB", &s->scope_job,
294 "FIFO", &s->fifo_path,
297 "DISPLAY", &s->display,
298 "REMOTE_HOST", &s->remote_host,
299 "REMOTE_USER", &s->remote_user,
300 "SERVICE", &s->service,
301 "DESKTOP", &s->desktop,
308 "REALTIME", &realtime,
309 "MONOTONIC", &monotonic,
310 "CONTROLLER", &controller,
314 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
323 log_error("UID not specified for session %s", s->id);
327 r = parse_uid(uid, &u);
329 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
333 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
335 log_error("User of session %s not known.", s->id);
339 session_set_user(s, user);
343 k = parse_boolean(remote);
349 safe_atou(vtnr, &s->vtnr);
351 if (seat && !s->seat) {
354 o = hashmap_get(s->manager->seats, seat);
356 r = seat_attach_session(o, s);
358 log_error("Cannot attach session %s to seat %s", s->id, seat);
361 if (!s->seat || !seat_has_vts(s->seat))
364 if (pos && s->seat) {
367 safe_atou(pos, &npos);
368 seat_claim_position(s->seat, s, npos);
372 k = parse_pid(leader, &s->leader);
374 audit_session_from_pid(s->leader, &s->audit_id);
380 t = session_type_from_string(type);
388 c = session_class_from_string(class);
396 /* If we open an unopened pipe for reading we will not
397 get an EOF. to trigger an EOF we hence open it for
398 reading, but close it right-away which then will
401 fd = session_create_fifo(s);
403 close_nointr_nofail(fd);
407 unsigned long long l;
408 if (sscanf(realtime, "%llu", &l) > 0)
409 s->timestamp.realtime = l;
413 unsigned long long l;
414 if (sscanf(monotonic, "%llu", &l) > 0)
415 s->timestamp.monotonic = l;
419 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
420 session_set_controller(s, controller, false);
422 session_restore_vt(s);
428 int session_activate(Session *s) {
429 unsigned int num_pending;
437 if (s->seat->active == s)
440 /* on seats with VTs, we let VTs manage session-switching */
441 if (seat_has_vts(s->seat)) {
445 return chvt(s->vtnr);
448 /* On seats without VTs, we implement session-switching in logind. We
449 * try to pause all session-devices and wait until the session
450 * controller acknowledged them. Once all devices are asleep, we simply
451 * switch the active session and be done.
452 * We save the session we want to switch to in seat->pending_switch and
453 * seat_complete_switch() will perform the final switch. */
455 s->seat->pending_switch = s;
457 /* if no devices are running, immediately perform the session switch */
458 num_pending = session_device_try_pause_all(s);
460 seat_complete_switch(s->seat);
465 static int session_start_scope(Session *s) {
470 assert(s->user->slice);
473 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
474 _cleanup_free_ char *description = NULL;
475 const char *kill_mode;
478 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
482 scope = strjoin("session-", s->id, ".scope", NULL);
486 kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
488 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job);
490 log_error("Failed to start session scope %s: %s %s",
491 scope, bus_error_message(&error, r), error.name);
503 hashmap_put(s->manager->session_units, s->scope, s);
508 int session_start(Session *s) {
519 r = user_start(s->user);
524 r = session_start_scope(s);
528 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
529 MESSAGE_ID(SD_MESSAGE_SESSION_START),
530 "SESSION_ID=%s", s->id,
531 "USER_ID=%s", s->user->name,
532 "LEADER=%lu", (unsigned long) s->leader,
533 "MESSAGE=New session %s of user %s.", s->id, s->user->name,
536 if (!dual_timestamp_is_set(&s->timestamp))
537 dual_timestamp_get(&s->timestamp);
540 seat_read_active_vt(s->seat);
544 /* Save session data */
548 session_send_signal(s, true);
553 if (s->seat->active == s)
554 seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
556 seat_send_changed(s->seat, "Sessions", NULL);
559 user_send_changed(s->user, "Sessions", NULL);
564 static int session_stop_scope(Session *s) {
565 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
574 r = manager_stop_unit(s->manager, s->scope, &error, &job);
576 log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
586 int session_stop(Session *s) {
595 r = session_stop_scope(s);
603 int session_finalize(Session *s) {
613 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
614 MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
615 "SESSION_ID=%s", s->id,
616 "USER_ID=%s", s->user->name,
617 "LEADER=%lu", (unsigned long) s->leader,
618 "MESSAGE=Removed session %s.", s->id,
621 /* Kill session devices */
622 while ((sd = hashmap_first(s->devices)))
623 session_device_free(sd);
625 unlink(s->state_file);
626 session_add_to_gc_queue(s);
627 user_add_to_gc_queue(s->user);
630 session_send_signal(s, false);
635 if (s->seat->active == s)
636 seat_set_active(s->seat, NULL);
638 seat_send_changed(s->seat, "Sessions", NULL);
642 user_send_changed(s->user, "Sessions", NULL);
648 bool session_is_active(Session *s) {
654 return s->seat->active == s;
657 static int get_tty_atime(const char *tty, usec_t *atime) {
658 _cleanup_free_ char *p = NULL;
664 if (!path_is_absolute(tty)) {
665 p = strappend("/dev/", tty);
670 } else if (!path_startswith(tty, "/dev/"))
673 if (lstat(tty, &st) < 0)
676 *atime = timespec_load(&st.st_atim);
680 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
681 _cleanup_free_ char *p = NULL;
687 r = get_ctty(pid, NULL, &p);
691 return get_tty_atime(p, atime);
694 int session_get_idle_hint(Session *s, dual_timestamp *t) {
700 /* Explicit idle hint is set */
703 *t = s->idle_hint_timestamp;
708 /* Graphical sessions should really implement a real
713 /* For sessions with an explicitly configured tty, let's check
716 r = get_tty_atime(s->tty, &atime);
721 /* For sessions with a leader but no explicitly configured
722 * tty, let's check the controlling tty of the leader */
724 r = get_process_ctty_atime(s->leader, &atime);
731 *t = s->idle_hint_timestamp;
737 dual_timestamp_from_realtime(t, atime);
739 n = now(CLOCK_REALTIME);
741 if (s->manager->idle_action_usec <= 0)
744 return atime + s->manager->idle_action_usec <= n;
747 void session_set_idle_hint(Session *s, bool b) {
750 if (s->idle_hint == b)
754 dual_timestamp_get(&s->idle_hint_timestamp);
756 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
759 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
761 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
762 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
765 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
766 Session *s = userdata;
769 assert(s->fifo_fd == fd);
771 /* EOF on the FIFO means the session died abnormally. */
773 session_remove_fifo(s);
779 int session_create_fifo(Session *s) {
786 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
790 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
793 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
797 /* Open reading side */
798 if (s->fifo_fd < 0) {
799 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
805 if (!s->fifo_event_source) {
806 r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
810 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
815 /* Open writing side */
816 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
823 void session_remove_fifo(Session *s) {
826 if (s->fifo_event_source)
827 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
829 if (s->fifo_fd >= 0) {
830 close_nointr_nofail(s->fifo_fd);
835 unlink(s->fifo_path);
841 bool session_check_gc(Session *s, bool drop_not_started) {
846 if (drop_not_started && !s->started)
852 if (s->fifo_fd >= 0) {
853 r = pipe_eof(s->fifo_fd);
861 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
864 if (s->scope && manager_unit_is_active(s->manager, s->scope))
870 void session_add_to_gc_queue(Session *s) {
876 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
877 s->in_gc_queue = true;
880 SessionState session_get_state(Session *s) {
884 return SESSION_OPENING;
887 return SESSION_CLOSING;
889 if (session_is_active(s))
890 return SESSION_ACTIVE;
892 return SESSION_ONLINE;
895 int session_kill(Session *s, KillWho who, int signo) {
901 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
904 static int session_open_vt(Session *s) {
913 sprintf(path, "/dev/tty%u", s->vtnr);
914 s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
916 log_error("cannot open VT %s of session %s: %m", path, s->id);
923 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
927 ioctl(s->vtfd, VT_RELDISP, 1);
932 void session_mute_vt(Session *s) {
934 struct vt_mode mode = { 0 };
937 vt = session_open_vt(s);
941 r = ioctl(vt, KDSKBMODE, K_OFF);
945 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
950 sigaddset(&mask, SIGUSR1);
951 sigprocmask(SIG_BLOCK, &mask, NULL);
953 r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
957 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
958 * So we need a dummy handler here which just acknowledges *all* VT
959 * switch requests. */
960 mode.mode = VT_PROCESS;
961 mode.relsig = SIGUSR1;
962 mode.acqsig = SIGUSR1;
963 r = ioctl(vt, VT_SETMODE, &mode);
970 log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
971 session_restore_vt(s);
974 void session_restore_vt(Session *s) {
975 _cleanup_free_ char *utf8;
976 int vt, kb = K_XLATE;
977 struct vt_mode mode = { 0 };
979 vt = session_open_vt(s);
983 sd_event_source_unref(s->vt_source);
986 ioctl(vt, KDSETMODE, KD_TEXT);
988 if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
990 ioctl(vt, KDSKBMODE, kb);
993 ioctl(vt, VT_SETMODE, &mode);
995 close_nointr_nofail(vt);
999 bool session_is_controller(Session *s, const char *sender) {
1002 return streq_ptr(s->controller, sender);
1005 static void session_swap_controller(Session *s, char *name) {
1008 if (s->controller) {
1009 manager_drop_busname(s->manager, s->controller);
1010 free(s->controller);
1011 s->controller = NULL;
1013 /* Drop all devices as they're now unused. Do that after the
1014 * controller is released to avoid sending out useles
1016 while ((sd = hashmap_first(s->devices)))
1017 session_device_free(sd);
1020 session_restore_vt(s);
1023 s->controller = name;
1027 int session_set_controller(Session *s, const char *sender, bool force) {
1034 if (session_is_controller(s, sender))
1036 if (s->controller && !force)
1043 r = manager_watch_busname(s->manager, sender);
1049 session_swap_controller(s, t);
1051 /* When setting a session controller, we forcibly mute the VT and set
1052 * it into graphics-mode. Applications can override that by changing
1053 * VT state after calling TakeControl(). However, this serves as a good
1054 * default and well-behaving controllers can now ignore VTs entirely.
1055 * Note that we reset the VT on ReleaseControl() and if the controller
1057 * If logind crashes/restarts, we restore the controller during restart
1058 * or reset the VT in case it crashed/exited, too. */
1064 void session_drop_controller(Session *s) {
1070 session_swap_controller(s, NULL);
1073 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1074 [SESSION_OPENING] = "opening",
1075 [SESSION_ONLINE] = "online",
1076 [SESSION_ACTIVE] = "active",
1077 [SESSION_CLOSING] = "closing"
1080 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1082 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1083 [SESSION_TTY] = "tty",
1084 [SESSION_X11] = "x11",
1085 [SESSION_WAYLAND] = "wayland",
1086 [SESSION_UNSPECIFIED] = "unspecified",
1089 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1091 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1092 [SESSION_USER] = "user",
1093 [SESSION_GREETER] = "greeter",
1094 [SESSION_LOCK_SCREEN] = "lock-screen",
1095 [SESSION_BACKGROUND] = "background"
1098 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1100 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1101 [KILL_LEADER] = "leader",
1105 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);