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 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
132 hashmap_remove(s->manager->session_units, s->scope);
138 sd_bus_message_unref(s->create_message);
142 free(s->remote_host);
143 free(s->remote_user);
146 hashmap_remove(s->manager->sessions, s->id);
152 void session_set_user(Session *s, User *u) {
157 LIST_PREPEND(sessions_by_user, u->sessions, s);
160 int session_save(Session *s) {
161 _cleanup_free_ char *temp_path = NULL;
162 _cleanup_fclose_ FILE *f = NULL;
173 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
177 r = fopen_temporary(s->state_file, &f, &temp_path);
183 fchmod(fileno(f), 0644);
186 "# This is private data. Do not parse.\n"
192 (unsigned long) s->user->uid,
194 session_is_active(s),
195 session_state_to_string(session_get_state(s)),
199 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
202 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
205 fprintf(f, "SCOPE=%s\n", s->scope);
208 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
211 fprintf(f, "FIFO=%s\n", s->fifo_path);
214 fprintf(f, "SEAT=%s\n", s->seat->id);
217 fprintf(f, "TTY=%s\n", s->tty);
220 fprintf(f, "DISPLAY=%s\n", s->display);
223 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
226 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
229 fprintf(f, "SERVICE=%s\n", s->service);
231 if (s->seat && seat_has_vts(s->seat))
232 fprintf(f, "VTNR=%u\n", s->vtnr);
235 fprintf(f, "LEADER=%lu\n", (unsigned long) s->leader);
238 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
240 if (dual_timestamp_is_set(&s->timestamp))
244 (unsigned long long) s->timestamp.realtime,
245 (unsigned long long) s->timestamp.monotonic);
248 fprintf(f, "CONTROLLER=%s\n", s->controller);
252 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
254 unlink(s->state_file);
260 log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
265 int session_load(Session *s) {
266 _cleanup_free_ char *remote = NULL,
281 r = parse_env_file(s->state_file, NEWLINE,
284 "SCOPE_JOB", &s->scope_job,
285 "FIFO", &s->fifo_path,
288 "DISPLAY", &s->display,
289 "REMOTE_HOST", &s->remote_host,
290 "REMOTE_USER", &s->remote_user,
291 "SERVICE", &s->service,
297 "REALTIME", &realtime,
298 "MONOTONIC", &monotonic,
299 "CONTROLLER", &controller,
303 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
312 log_error("UID not specified for session %s", s->id);
316 r = parse_uid(uid, &u);
318 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
322 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
324 log_error("User of session %s not known.", s->id);
328 session_set_user(s, user);
332 k = parse_boolean(remote);
338 safe_atou(vtnr, &s->vtnr);
340 if (seat && !s->seat) {
343 o = hashmap_get(s->manager->seats, seat);
345 r = seat_attach_session(o, s);
347 log_error("Cannot attach session %s to seat %s", s->id, seat);
350 if (!s->seat || !seat_has_vts(s->seat))
354 k = parse_pid(leader, &s->leader);
356 audit_session_from_pid(s->leader, &s->audit_id);
362 t = session_type_from_string(type);
370 c = session_class_from_string(class);
378 /* If we open an unopened pipe for reading we will not
379 get an EOF. to trigger an EOF we hence open it for
380 reading, but close it right-away which then will
383 fd = session_create_fifo(s);
385 close_nointr_nofail(fd);
389 unsigned long long l;
390 if (sscanf(realtime, "%llu", &l) > 0)
391 s->timestamp.realtime = l;
395 unsigned long long l;
396 if (sscanf(monotonic, "%llu", &l) > 0)
397 s->timestamp.monotonic = l;
401 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
402 session_set_controller(s, controller, false);
404 session_restore_vt(s);
410 int session_activate(Session *s) {
411 unsigned int num_pending;
419 if (s->seat->active == s)
422 /* on seats with VTs, we let VTs manage session-switching */
423 if (seat_has_vts(s->seat)) {
427 return chvt(s->vtnr);
430 /* On seats without VTs, we implement session-switching in logind. We
431 * try to pause all session-devices and wait until the session
432 * controller acknowledged them. Once all devices are asleep, we simply
433 * switch the active session and be done.
434 * We save the session we want to switch to in seat->pending_switch and
435 * seat_complete_switch() will perform the final switch. */
437 s->seat->pending_switch = s;
439 /* if no devices are running, immediately perform the session switch */
440 num_pending = session_device_try_pause_all(s);
442 seat_complete_switch(s->seat);
447 static int session_start_scope(Session *s) {
452 assert(s->user->slice);
455 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
456 _cleanup_free_ char *description = NULL;
457 const char *kill_mode;
460 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
464 scope = strjoin("session-", s->id, ".scope", NULL);
468 kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
470 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job);
472 log_error("Failed to start session scope %s: %s %s",
473 scope, bus_error_message(&error, r), error.name);
485 hashmap_put(s->manager->session_units, s->scope, s);
490 int session_start(Session *s) {
501 r = user_start(s->user);
506 r = session_start_scope(s);
510 log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
511 MESSAGE_ID(SD_MESSAGE_SESSION_START),
512 "SESSION_ID=%s", s->id,
513 "USER_ID=%s", s->user->name,
514 "LEADER=%lu", (unsigned long) s->leader,
515 "MESSAGE=New session %s of user %s.", s->id, s->user->name,
518 if (!dual_timestamp_is_set(&s->timestamp))
519 dual_timestamp_get(&s->timestamp);
522 seat_read_active_vt(s->seat);
526 /* Save session data */
530 session_send_signal(s, true);
535 if (s->seat->active == s)
536 seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
538 seat_send_changed(s->seat, "Sessions", NULL);
541 user_send_changed(s->user, "Sessions", NULL);
546 static int session_stop_scope(Session *s) {
547 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
556 r = manager_stop_unit(s->manager, s->scope, &error, &job);
558 log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
568 int session_stop(Session *s) {
577 r = session_stop_scope(s);
585 int session_finalize(Session *s) {
595 log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
596 MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
597 "SESSION_ID=%s", s->id,
598 "USER_ID=%s", s->user->name,
599 "LEADER=%lu", (unsigned long) s->leader,
600 "MESSAGE=Removed session %s.", s->id,
603 /* Kill session devices */
604 while ((sd = hashmap_first(s->devices)))
605 session_device_free(sd);
607 unlink(s->state_file);
608 session_add_to_gc_queue(s);
609 user_add_to_gc_queue(s->user);
612 session_send_signal(s, false);
617 if (s->seat->active == s)
618 seat_set_active(s->seat, NULL);
620 seat_send_changed(s->seat, "Sessions", NULL);
624 user_send_changed(s->user, "Sessions", NULL);
630 bool session_is_active(Session *s) {
636 return s->seat->active == s;
639 static int get_tty_atime(const char *tty, usec_t *atime) {
640 _cleanup_free_ char *p = NULL;
646 if (!path_is_absolute(tty)) {
647 p = strappend("/dev/", tty);
652 } else if (!path_startswith(tty, "/dev/"))
655 if (lstat(tty, &st) < 0)
658 *atime = timespec_load(&st.st_atim);
662 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
663 _cleanup_free_ char *p = NULL;
669 r = get_ctty(pid, NULL, &p);
673 return get_tty_atime(p, atime);
676 int session_get_idle_hint(Session *s, dual_timestamp *t) {
682 /* Explicit idle hint is set */
685 *t = s->idle_hint_timestamp;
690 /* Graphical sessions should really implement a real
695 /* For sessions with an explicitly configured tty, let's check
698 r = get_tty_atime(s->tty, &atime);
703 /* For sessions with a leader but no explicitly configured
704 * tty, let's check the controlling tty of the leader */
706 r = get_process_ctty_atime(s->leader, &atime);
713 *t = s->idle_hint_timestamp;
719 dual_timestamp_from_realtime(t, atime);
721 n = now(CLOCK_REALTIME);
723 if (s->manager->idle_action_usec <= 0)
726 return atime + s->manager->idle_action_usec <= n;
729 void session_set_idle_hint(Session *s, bool b) {
732 if (s->idle_hint == b)
736 dual_timestamp_get(&s->idle_hint_timestamp);
738 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
741 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
743 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
744 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
747 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
748 Session *s = userdata;
751 assert(s->fifo_fd == fd);
753 /* EOF on the FIFO means the session died abnormally. */
755 session_remove_fifo(s);
761 int session_create_fifo(Session *s) {
768 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
772 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
775 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
779 /* Open reading side */
780 if (s->fifo_fd < 0) {
781 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
787 if (!s->fifo_event_source) {
788 r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
792 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
797 /* Open writing side */
798 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
805 void session_remove_fifo(Session *s) {
808 if (s->fifo_event_source)
809 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
811 if (s->fifo_fd >= 0) {
812 close_nointr_nofail(s->fifo_fd);
817 unlink(s->fifo_path);
823 bool session_check_gc(Session *s, bool drop_not_started) {
828 if (drop_not_started && !s->started)
834 if (s->fifo_fd >= 0) {
835 r = pipe_eof(s->fifo_fd);
843 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
846 if (s->scope && manager_unit_is_active(s->manager, s->scope))
852 void session_add_to_gc_queue(Session *s) {
858 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
859 s->in_gc_queue = true;
862 SessionState session_get_state(Session *s) {
866 return SESSION_OPENING;
869 return SESSION_CLOSING;
871 if (session_is_active(s))
872 return SESSION_ACTIVE;
874 return SESSION_ONLINE;
877 int session_kill(Session *s, KillWho who, int signo) {
883 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
886 static int session_open_vt(Session *s) {
895 sprintf(path, "/dev/tty%u", s->vtnr);
896 s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
898 log_error("cannot open VT %s of session %s: %m", path, s->id);
905 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
909 ioctl(s->vtfd, VT_RELDISP, 1);
914 void session_mute_vt(Session *s) {
916 struct vt_mode mode = { 0 };
919 vt = session_open_vt(s);
923 r = ioctl(vt, KDSKBMODE, K_OFF);
927 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
932 sigaddset(&mask, SIGUSR1);
933 sigprocmask(SIG_BLOCK, &mask, NULL);
935 r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
939 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
940 * So we need a dummy handler here which just acknowledges *all* VT
941 * switch requests. */
942 mode.mode = VT_PROCESS;
943 mode.relsig = SIGUSR1;
944 mode.acqsig = SIGUSR1;
945 r = ioctl(vt, VT_SETMODE, &mode);
952 log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
953 session_restore_vt(s);
956 void session_restore_vt(Session *s) {
957 _cleanup_free_ char *utf8;
958 int vt, kb = K_XLATE;
959 struct vt_mode mode = { 0 };
961 vt = session_open_vt(s);
965 sd_event_source_unref(s->vt_source);
968 ioctl(vt, KDSETMODE, KD_TEXT);
970 if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
972 ioctl(vt, KDSKBMODE, kb);
975 ioctl(vt, VT_SETMODE, &mode);
977 close_nointr_nofail(vt);
981 bool session_is_controller(Session *s, const char *sender) {
984 return streq_ptr(s->controller, sender);
987 static void session_swap_controller(Session *s, char *name) {
991 manager_drop_busname(s->manager, s->controller);
993 s->controller = NULL;
995 /* Drop all devices as they're now unused. Do that after the
996 * controller is released to avoid sending out useles
998 while ((sd = hashmap_first(s->devices)))
999 session_device_free(sd);
1002 session_restore_vt(s);
1005 s->controller = name;
1009 int session_set_controller(Session *s, const char *sender, bool force) {
1016 if (session_is_controller(s, sender))
1018 if (s->controller && !force)
1025 r = manager_watch_busname(s->manager, sender);
1031 session_swap_controller(s, t);
1033 /* When setting a session controller, we forcibly mute the VT and set
1034 * it into graphics-mode. Applications can override that by changing
1035 * VT state after calling TakeControl(). However, this serves as a good
1036 * default and well-behaving controllers can now ignore VTs entirely.
1037 * Note that we reset the VT on ReleaseControl() and if the controller
1039 * If logind crashes/restarts, we restore the controller during restart
1040 * or reset the VT in case it crashed/exited, too. */
1046 void session_drop_controller(Session *s) {
1052 session_swap_controller(s, NULL);
1055 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1056 [SESSION_OPENING] = "opening",
1057 [SESSION_ONLINE] = "online",
1058 [SESSION_ACTIVE] = "active",
1059 [SESSION_CLOSING] = "closing"
1062 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1064 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1065 [SESSION_TTY] = "tty",
1066 [SESSION_X11] = "x11",
1067 [SESSION_UNSPECIFIED] = "unspecified"
1070 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1072 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1073 [SESSION_USER] = "user",
1074 [SESSION_GREETER] = "greeter",
1075 [SESSION_LOCK_SCREEN] = "lock-screen",
1076 [SESSION_BACKGROUND] = "background"
1079 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1081 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1082 [KILL_LEADER] = "leader",
1086 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);