]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/login/logind-session.c
presets: Disable by default for initrd presets
[thirdparty/systemd.git] / src / login / logind-session.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <fcntl.h>
4#include <linux/kd.h>
5#include <linux/vt.h>
6#include <signal.h>
7#include <sys/ioctl.h>
8#include <sys/stat.h>
9#include <unistd.h>
10
11#include "sd-bus.h"
12#include "sd-event.h"
13#include "sd-messages.h"
14#include "sd-varlink.h"
15
16#include "alloc-util.h"
17#include "audit-util.h"
18#include "bus-error.h"
19#include "bus-util.h"
20#include "daemon-util.h"
21#include "devnum-util.h"
22#include "env-file.h"
23#include "errno-util.h"
24#include "extract-word.h"
25#include "fd-util.h"
26#include "format-util.h"
27#include "fs-util.h"
28#include "hashmap.h"
29#include "login-util.h"
30#include "logind.h"
31#include "logind-dbus.h"
32#include "logind-seat.h"
33#include "logind-seat-dbus.h"
34#include "logind-session.h"
35#include "logind-session-dbus.h"
36#include "logind-session-device.h"
37#include "logind-user.h"
38#include "logind-user-dbus.h"
39#include "logind-varlink.h"
40#include "mkdir-label.h"
41#include "parse-util.h"
42#include "path-util.h"
43#include "process-util.h"
44#include "serialize.h"
45#include "string-table.h"
46#include "terminal-util.h"
47#include "tmpfile-util.h"
48#include "user-record.h"
49#include "user-util.h"
50
51#define RELEASE_USEC (20*USEC_PER_SEC)
52
53static void session_restore_vt(Session *s);
54
55int session_new(Manager *m, const char *id, Session **ret) {
56 _cleanup_(session_freep) Session *s = NULL;
57 int r;
58
59 assert(m);
60 assert(id);
61 assert(ret);
62
63 if (!session_id_valid(id))
64 return -EINVAL;
65
66 s = new(Session, 1);
67 if (!s)
68 return -ENOMEM;
69
70 *s = (Session) {
71 .manager = m,
72 .id = strdup(id),
73 .state_file = path_join("/run/systemd/sessions/", id),
74 .vtfd = -EBADF,
75 .audit_id = AUDIT_SESSION_INVALID,
76 .tty_validity = _TTY_VALIDITY_INVALID,
77 .leader = PIDREF_NULL,
78 };
79 if (!s->id || !s->state_file)
80 return -ENOMEM;
81
82 s->devices = hashmap_new(&devt_hash_ops);
83 if (!s->devices)
84 return -ENOMEM;
85
86 r = hashmap_put(m->sessions, s->id, s);
87 if (r < 0)
88 return r;
89
90 *ret = TAKE_PTR(s);
91 return 0;
92}
93
94static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
95 Session *s = ASSERT_PTR(userdata);
96
97 assert(s->leader.fd == fd);
98
99 s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
100
101 session_stop(s, /* force= */ false);
102
103 session_add_to_gc_queue(s);
104
105 return 1;
106}
107
108static int session_watch_pidfd(Session *s) {
109 int r;
110
111 assert(s);
112 assert(s->manager);
113 assert(pidref_is_set(&s->leader));
114 assert(s->leader.fd >= 0);
115 assert(!s->leader_pidfd_event_source);
116
117 r = sd_event_add_io(s->manager->event, &s->leader_pidfd_event_source, s->leader.fd, EPOLLIN, session_dispatch_leader_pidfd, s);
118 if (r < 0)
119 return r;
120
121 r = sd_event_source_set_priority(s->leader_pidfd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
122 if (r < 0)
123 return r;
124
125 (void) sd_event_source_set_description(s->leader_pidfd_event_source, "session-pidfd");
126
127 return 0;
128}
129
130static void session_reset_leader(Session *s, bool keep_fdstore) {
131 assert(s);
132
133 if (!keep_fdstore) {
134 /* Clear fdstore if we're asked to, no matter if s->leader is set or not, so that when
135 * initially deserializing leader fd we clear the old fd too. */
136 (void) notify_remove_fd_warnf("session-%s-leader-fd", s->id);
137 s->leader_fd_saved = false;
138 }
139
140 if (!pidref_is_set(&s->leader))
141 return;
142
143 s->leader_pidfd_event_source = sd_event_source_disable_unref(s->leader_pidfd_event_source);
144
145 (void) hashmap_remove_value(s->manager->sessions_by_leader, &s->leader, s);
146
147 return pidref_done(&s->leader);
148}
149
150Session* session_free(Session *s) {
151 SessionDevice *sd;
152
153 if (!s)
154 return NULL;
155
156 sd_event_source_unref(s->stop_on_idle_event_source);
157
158 if (s->in_gc_queue) {
159 assert(s->manager);
160 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
161 }
162
163 sd_event_source_unref(s->timer_event_source);
164
165 session_drop_controller(s);
166
167 while ((sd = hashmap_first(s->devices)))
168 session_device_free(sd);
169
170 hashmap_free(s->devices);
171
172 if (s->user) {
173 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
174
175 if (s->user->display == s)
176 s->user->display = NULL;
177
178 user_update_last_session_timer(s->user);
179 }
180
181 if (s->seat) {
182 if (s->seat->active == s)
183 s->seat->active = NULL;
184 if (s->seat->pending_switch == s)
185 s->seat->pending_switch = NULL;
186
187 seat_evict_position(s->seat, s);
188 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
189 }
190
191 if (s->scope) {
192 hashmap_remove(s->manager->session_units, s->scope);
193 free(s->scope);
194 }
195
196 free(s->scope_job);
197
198 session_reset_leader(s, /* keep_fdstore = */ true);
199
200 sd_bus_message_unref(s->create_message);
201 sd_bus_message_unref(s->upgrade_message);
202
203 sd_varlink_unref(s->create_link);
204
205 free(s->tty);
206 free(s->display);
207 free(s->remote_host);
208 free(s->remote_user);
209 free(s->service);
210 free(s->desktop);
211
212 hashmap_remove(s->manager->sessions, s->id);
213
214 /* Note that we don't remove the state file here, since it's supposed to survive daemon restarts */
215 free(s->state_file);
216 free(s->id);
217
218 return mfree(s);
219}
220
221void session_set_user(Session *s, User *u) {
222 assert(s);
223 assert(!s->user);
224
225 s->user = u;
226 LIST_PREPEND(sessions_by_user, u->sessions, s);
227
228 user_update_last_session_timer(u);
229}
230
231int session_set_leader_consume(Session *s, PidRef _leader) {
232 _cleanup_(pidref_done) PidRef pidref = _leader;
233 int r;
234
235 assert(s);
236 assert(pidref_is_set(&pidref));
237 assert(pidref.fd >= 0);
238
239 if (pidref_equal(&s->leader, &pidref))
240 return 0;
241
242 session_reset_leader(s, /* keep_fdstore = */ false);
243
244 s->leader = TAKE_PIDREF(pidref);
245
246 r = session_watch_pidfd(s);
247 if (r < 0)
248 return log_error_errno(r, "Failed to watch leader pidfd for session '%s': %m", s->id);
249
250 r = hashmap_ensure_put(&s->manager->sessions_by_leader, &pidref_hash_ops, &s->leader, s);
251 if (r < 0)
252 return r;
253 assert(r > 0);
254
255 if (s->leader.fd >= 0) {
256 r = notify_push_fdf(s->leader.fd, "session-%s-leader-fd", s->id);
257 if (r < 0)
258 log_warning_errno(r, "Failed to push leader pidfd for session '%s', ignoring: %m", s->id);
259 else
260 s->leader_fd_saved = true;
261 }
262
263 (void) audit_session_from_pid(&s->leader, &s->audit_id);
264
265 return 1;
266}
267
268static void session_save_devices(Session *s, FILE *f) {
269 SessionDevice *sd;
270
271 if (!hashmap_isempty(s->devices)) {
272 fprintf(f, "DEVICES=");
273 HASHMAP_FOREACH(sd, s->devices)
274 fprintf(f, DEVNUM_FORMAT_STR " ", DEVNUM_FORMAT_VAL(sd->dev));
275 fprintf(f, "\n");
276 }
277}
278
279int session_save(Session *s) {
280 int r;
281
282 assert(s);
283
284 if (!s->user)
285 return -ESTALE;
286
287 if (!s->started)
288 return 0;
289
290 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
291 if (r < 0)
292 return log_error_errno(r, "Failed to create /run/systemd/sessions/: %m");
293
294 _cleanup_(unlink_and_freep) char *temp_path = NULL;
295 _cleanup_fclose_ FILE *f = NULL;
296 r = fopen_tmpfile_linkable(s->state_file, O_WRONLY|O_CLOEXEC, &temp_path, &f);
297 if (r < 0)
298 return log_error_errno(r, "Failed to create state file '%s': %m", s->state_file);
299
300 if (fchmod(fileno(f), 0644) < 0)
301 return log_error_errno(errno, "Failed to set access mode for state file '%s' to 0644: %m", s->state_file);
302
303 fprintf(f,
304 "# This is private data. Do not parse.\n"
305 "UID="UID_FMT"\n"
306 "ACTIVE=%s\n"
307 "IS_DISPLAY=%s\n"
308 "STATE=%s\n"
309 "REMOTE=%s\n"
310 "LEADER_FD_SAVED=%s\n",
311 s->user->user_record->uid,
312 one_zero(session_is_active(s)),
313 one_zero(s->user->display == s),
314 session_state_to_string(session_get_state(s)),
315 one_zero(s->remote),
316 one_zero(s->leader_fd_saved));
317
318 env_file_fputs_assignment(f, "USER=", s->user->user_record->user_name);
319
320 if (s->type >= 0)
321 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
322
323 if (s->original_type >= 0)
324 fprintf(f, "ORIGINAL_TYPE=%s\n", session_type_to_string(s->original_type));
325
326 if (s->class >= 0)
327 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
328
329 env_file_fputs_assignment(f, "SCOPE=", s->scope);
330 env_file_fputs_assignment(f, "SCOPE_JOB=", s->scope_job);
331 if (s->seat)
332 env_file_fputs_assignment(f, "SEAT=", s->seat->id);
333 env_file_fputs_assignment(f, "TTY=", s->tty);
334
335 if (s->tty_validity >= 0)
336 fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
337
338 env_file_fputs_assignment(f, "DISPLAY=", s->display);
339 env_file_fputs_assignment(f, "REMOTE_HOST=", s->remote_host);
340 env_file_fputs_assignment(f, "REMOTE_USER=", s->remote_user);
341 env_file_fputs_assignment(f, "SERVICE=", s->service);
342 env_file_fputs_assignment(f, "DESKTOP=", s->desktop);
343
344 if (s->seat) {
345 if (!seat_has_vts(s->seat))
346 fprintf(f, "POSITION=%u\n", s->position);
347 else if (s->vtnr > 0)
348 fprintf(f, "VTNR=%u\n", s->vtnr);
349 }
350
351 if (pidref_is_set(&s->leader)) {
352 fprintf(f, "LEADER="PID_FMT"\n", s->leader.pid);
353 (void) pidref_acquire_pidfd_id(&s->leader);
354 if (s->leader.fd_id != 0)
355 fprintf(f, "LEADER_PIDFDID=%" PRIu64 "\n", s->leader.fd_id);
356 }
357
358 if (audit_session_is_valid(s->audit_id))
359 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
360
361 if (dual_timestamp_is_set(&s->timestamp))
362 fprintf(f,
363 "REALTIME="USEC_FMT"\n"
364 "MONOTONIC="USEC_FMT"\n",
365 s->timestamp.realtime,
366 s->timestamp.monotonic);
367
368 if (s->controller) {
369 env_file_fputs_assignment(f, "CONTROLLER=", s->controller);
370 session_save_devices(s, f);
371 }
372
373 r = flink_tmpfile(f, temp_path, s->state_file, LINK_TMPFILE_REPLACE);
374 if (r < 0)
375 return log_error_errno(r, "Failed to move '%s' into place: %m", s->state_file);
376
377 temp_path = mfree(temp_path); /* disarm auto-destroy: temporary file does not exist anymore */
378 return 0;
379}
380
381static int session_load_devices(Session *s, const char *devices) {
382 int r = 0;
383
384 assert(s);
385
386 for (const char *p = devices;;) {
387 _cleanup_free_ char *word = NULL;
388 dev_t dev;
389 int k;
390
391 k = extract_first_word(&p, &word, NULL, 0);
392 if (k <= 0) {
393 RET_GATHER(r, k);
394 break;
395 }
396
397 k = parse_devnum(word, &dev);
398 if (k < 0) {
399 RET_GATHER(r, k);
400 continue;
401 }
402
403 /* The file descriptors for loaded devices will be reattached later. */
404 RET_GATHER(r, session_device_new(s, dev, /* open_device = */ false, /* ret = */ NULL));
405 }
406
407 if (r < 0)
408 log_error_errno(r, "Failed to load some session devices for session '%s': %m", s->id);
409 return r;
410}
411
412int session_load(Session *s) {
413 _cleanup_free_ char *remote = NULL,
414 *seat = NULL,
415 *tty_validity = NULL,
416 *vtnr = NULL,
417 *state = NULL,
418 *position = NULL,
419 *leader_pid = NULL,
420 *leader_fd_saved = NULL,
421 *type = NULL,
422 *original_type = NULL,
423 *class = NULL,
424 *uid = NULL,
425 *realtime = NULL,
426 *monotonic = NULL,
427 *controller = NULL,
428 *active = NULL,
429 *devices = NULL,
430 *is_display = NULL,
431 *fifo_path = NULL; /* compat only, not used */
432
433 int k, r;
434
435 assert(s);
436
437 r = parse_env_file(NULL, s->state_file,
438 "REMOTE", &remote,
439 "SCOPE", &s->scope,
440 "SCOPE_JOB", &s->scope_job,
441 "FIFO", &fifo_path,
442 "SEAT", &seat,
443 "TTY", &s->tty,
444 "TTY_VALIDITY", &tty_validity,
445 "DISPLAY", &s->display,
446 "REMOTE_HOST", &s->remote_host,
447 "REMOTE_USER", &s->remote_user,
448 "SERVICE", &s->service,
449 "DESKTOP", &s->desktop,
450 "VTNR", &vtnr,
451 "STATE", &state,
452 "POSITION", &position,
453 "LEADER", &leader_pid,
454 "LEADER_FD_SAVED", &leader_fd_saved,
455 "TYPE", &type,
456 "ORIGINAL_TYPE", &original_type,
457 "CLASS", &class,
458 "UID", &uid,
459 "REALTIME", &realtime,
460 "MONOTONIC", &monotonic,
461 "CONTROLLER", &controller,
462 "ACTIVE", &active,
463 "DEVICES", &devices,
464 "IS_DISPLAY", &is_display);
465 if (r < 0)
466 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
467
468 if (!s->user) {
469 uid_t u;
470 User *user;
471
472 if (!uid)
473 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
474 "UID not specified for session %s",
475 s->id);
476
477 r = parse_uid(uid, &u);
478 if (r < 0) {
479 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
480 return r;
481 }
482
483 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
484 if (!user)
485 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
486 "User of session %s not known.",
487 s->id);
488
489 session_set_user(s, user);
490 }
491
492 if (remote) {
493 k = parse_boolean(remote);
494 if (k >= 0)
495 s->remote = k;
496 }
497
498 if (vtnr)
499 (void) safe_atou(vtnr, &s->vtnr);
500
501 if (seat && !s->seat) {
502 Seat *o;
503
504 o = hashmap_get(s->manager->seats, seat);
505 if (o)
506 r = seat_attach_session(o, s);
507 if (!o || r < 0)
508 log_error("Cannot attach session %s to seat %s", s->id, seat);
509 }
510
511 if (!s->seat || !seat_has_vts(s->seat))
512 s->vtnr = 0;
513
514 if (position && s->seat) {
515 unsigned npos;
516
517 (void) safe_atou(position, &npos);
518 seat_claim_position(s->seat, s, npos);
519 }
520
521 if (tty_validity) {
522 TTYValidity v;
523
524 v = tty_validity_from_string(tty_validity);
525 if (v < 0)
526 log_debug("Failed to parse TTY validity: %s", tty_validity);
527 else
528 s->tty_validity = v;
529 }
530
531 if (type) {
532 SessionType t;
533
534 t = session_type_from_string(type);
535 if (t >= 0)
536 s->type = t;
537 }
538
539 if (original_type) {
540 SessionType ot;
541
542 ot = session_type_from_string(original_type);
543 if (ot >= 0)
544 s->original_type = ot;
545 } else
546 /* Pre-v246 compat: initialize original_type if not set in the state file */
547 s->original_type = s->type;
548
549 if (class) {
550 SessionClass c;
551
552 c = session_class_from_string(class);
553 if (c >= 0)
554 s->class = c;
555 }
556
557 if (streq_ptr(state, "closing"))
558 s->stopping = true;
559
560 /* logind before v258 used a fifo for session close notification. Since v258 we fully employ
561 * pidfd for the job, hence just unlink the legacy fifo. */
562 if (fifo_path)
563 (void) unlink(fifo_path);
564
565 if (realtime)
566 (void) deserialize_usec(realtime, &s->timestamp.realtime);
567 if (monotonic)
568 (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
569
570 if (active) {
571 k = parse_boolean(active);
572 if (k >= 0)
573 s->was_active = k;
574 }
575
576 if (is_display) {
577 /* Note that when enumerating users are loaded before sessions, hence the display session to use is
578 * something we have to store along with the session and not the user, as in that case we couldn't
579 * apply it at the time we load the user. */
580
581 k = parse_boolean(is_display);
582 if (k < 0)
583 log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
584 else if (k > 0)
585 s->user->display = s;
586 }
587
588 if (controller) {
589 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
590 session_set_controller(s, controller, false, false);
591 session_load_devices(s, devices);
592 } else
593 session_restore_vt(s);
594 }
595
596 if (leader_pid) {
597 assert(!pidref_is_set(&s->leader));
598
599 r = parse_pid(leader_pid, &s->deserialized_pid);
600 if (r < 0)
601 return log_error_errno(r, "Failed to parse LEADER=%s: %m", leader_pid);
602
603 if (leader_fd_saved) {
604 r = parse_boolean(leader_fd_saved);
605 if (r < 0)
606 return log_error_errno(r, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved);
607 s->leader_fd_saved = r > 0;
608
609 if (s->leader_fd_saved)
610 /* The leader fd will be acquired from fdstore later */
611 return 0;
612 }
613
614 _cleanup_(pidref_done) PidRef p = PIDREF_NULL;
615
616 r = pidref_set_pid(&p, s->deserialized_pid);
617 if (r < 0)
618 return log_error_errno(r, "Failed to deserialize leader PID for session '%s': %m", s->id);
619 if (p.fd < 0)
620 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
621 "Failed to acquire pidfd for session leader '" PID_FMT "', refusing.",
622 p.pid);
623
624 r = session_set_leader_consume(s, TAKE_PIDREF(p));
625 if (r < 0)
626 return log_error_errno(r, "Failed to set leader PID for session '%s': %m", s->id);
627 }
628
629 return 0;
630}
631
632int session_activate(Session *s) {
633 unsigned num_pending;
634
635 assert(s);
636 assert(s->user);
637
638 if (!s->seat)
639 return -EOPNOTSUPP;
640
641 if (s->seat->active == s)
642 return 0;
643
644 /* on seats with VTs, we let VTs manage session-switching */
645 if (seat_has_vts(s->seat)) {
646 if (s->vtnr == 0)
647 return -EOPNOTSUPP;
648
649 return chvt(s->vtnr);
650 }
651
652 /* On seats without VTs, we implement session-switching in logind. We
653 * try to pause all session-devices and wait until the session
654 * controller acknowledged them. Once all devices are asleep, we simply
655 * switch the active session and be done.
656 * We save the session we want to switch to in seat->pending_switch and
657 * seat_complete_switch() will perform the final switch. */
658
659 s->seat->pending_switch = s;
660
661 /* if no devices are running, immediately perform the session switch */
662 num_pending = session_device_try_pause_all(s);
663 if (!num_pending)
664 seat_complete_switch(s->seat);
665
666 return 0;
667}
668
669static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
670 _cleanup_free_ char *scope = NULL;
671 const char *description;
672 int r;
673
674 assert(s);
675 assert(s->user);
676
677 if (!SESSION_CLASS_WANTS_SCOPE(s->class))
678 return 0;
679
680 if (s->scope)
681 goto finish;
682
683 s->scope_job = mfree(s->scope_job);
684
685 scope = strjoin("session-", s->id, ".scope");
686 if (!scope)
687 return log_oom();
688
689 description = strjoina("Session ", s->id, " of User ", s->user->user_record->user_name);
690
691 r = manager_start_scope(
692 s->manager,
693 scope,
694 &s->leader,
695 /* allow_pidfd = */ true,
696 s->user->slice,
697 description,
698 /* These should have been pulled in explicitly in user_start(). Just to be sure. */
699 /* requires = */ STRV_MAKE_CONST(s->user->runtime_dir_unit),
700 /* wants = */ STRV_MAKE_CONST(SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) ? s->user->service_manager_unit : NULL),
701 /* We usually want to order session scopes after systemd-user-sessions.service
702 * since the unit is used as login session barrier for unprivileged users. However
703 * the barrier doesn't apply for root as sysadmin should always be able to log in
704 * (and without waiting for any timeout to expire) in case something goes wrong
705 * during the boot process. */
706 /* extra_after = */ STRV_MAKE_CONST("systemd-logind.service",
707 SESSION_CLASS_IS_EARLY(s->class) ? NULL : "systemd-user-sessions.service"),
708 user_record_home_directory(s->user->user_record),
709 properties,
710 error,
711 &s->scope_job);
712 if (r < 0)
713 return log_error_errno(r, "Failed to start session scope %s: %s",
714 scope, bus_error_message(error, r));
715
716 s->scope = TAKE_PTR(scope);
717
718finish:
719 (void) hashmap_put(s->manager->session_units, s->scope, s);
720 return 0;
721}
722
723static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, void *userdata) {
724 Session *s = userdata;
725 dual_timestamp ts;
726 int r, idle;
727
728 assert(s);
729
730 if (s->stopping)
731 return 0;
732
733 idle = session_get_idle_hint(s, &ts);
734 if (idle) {
735 log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
736
737 return session_stop(s, /* force */ true);
738 }
739
740 r = sd_event_source_set_time(
741 source,
742 usec_add(dual_timestamp_is_set(&ts) ? ts.monotonic : now(CLOCK_MONOTONIC),
743 s->manager->stop_idle_session_usec));
744 if (r < 0)
745 return log_error_errno(r, "Failed to configure stop on idle session event source: %m");
746
747 r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
748 if (r < 0)
749 return log_error_errno(r, "Failed to enable stop on idle session event source: %m");
750
751 return 1;
752}
753
754static int session_setup_stop_on_idle_timer(Session *s) {
755 int r;
756
757 assert(s);
758
759 if (s->manager->stop_idle_session_usec == USEC_INFINITY || !SESSION_CLASS_CAN_STOP_ON_IDLE(s->class))
760 return 0;
761
762 r = sd_event_add_time_relative(
763 s->manager->event,
764 &s->stop_on_idle_event_source,
765 CLOCK_MONOTONIC,
766 s->manager->stop_idle_session_usec,
767 0,
768 session_dispatch_stop_on_idle, s);
769 if (r < 0)
770 return log_error_errno(r, "Failed to add stop on idle session event source: %m");
771
772 return 0;
773}
774
775int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
776 int r;
777
778 assert(s);
779
780 if (!s->user)
781 return -ESTALE;
782
783 if (s->stopping)
784 return -EINVAL;
785
786 if (s->started)
787 return 0;
788
789 r = user_start(s->user);
790 if (r < 0)
791 return r;
792
793 r = session_start_scope(s, properties, error);
794 if (r < 0)
795 return r;
796
797 r = session_setup_stop_on_idle_timer(s);
798 if (r < 0)
799 return r;
800
801 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
802 LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START_STR),
803 LOG_ITEM("SESSION_ID=%s", s->id),
804 LOG_ITEM("USER_ID=%s", s->user->user_record->user_name),
805 LOG_ITEM("LEADER="PID_FMT, s->leader.pid),
806 LOG_ITEM("CLASS=%s", session_class_to_string(s->class)),
807 LOG_ITEM("TYPE=%s", session_type_to_string(s->type)),
808 LOG_MESSAGE("New session '%s' of user '%s' with class '%s' and type '%s'.",
809 s->id,
810 s->user->user_record->user_name,
811 session_class_to_string(s->class),
812 session_type_to_string(s->type)));
813
814 if (!dual_timestamp_is_set(&s->timestamp))
815 dual_timestamp_now(&s->timestamp);
816
817 if (s->seat)
818 seat_read_active_vt(s->seat);
819
820 s->started = true;
821
822 user_elect_display(s->user);
823
824 /* Save data */
825 (void) session_save(s);
826 (void) user_save(s->user);
827 if (s->seat)
828 (void) seat_save(s->seat);
829
830 /* Send signals */
831 session_send_signal(s, true);
832 user_send_changed(s->user, "Display");
833
834 if (s->seat && s->seat->active == s)
835 (void) seat_send_changed(s->seat, "ActiveSession");
836
837 return 0;
838}
839
840static int session_stop_scope(Session *s, bool force) {
841 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
842 int r;
843
844 assert(s);
845
846 if (!s->scope)
847 return 0;
848
849 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
850 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
851 * when killing any processes left after this point. */
852 r = manager_abandon_scope(s->manager, s->scope, &error);
853 if (r < 0) {
854 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
855 sd_bus_error_free(&error);
856 }
857
858 s->scope_job = mfree(s->scope_job);
859
860 /* Optionally, let's kill everything that's left now. */
861 if (force ||
862 (s->user->user_record->kill_processes != 0 &&
863 (s->user->user_record->kill_processes > 0 ||
864 manager_shall_kill(s->manager, s->user->user_record->user_name)))) {
865
866 r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job);
867 if (r < 0) {
868 if (force)
869 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
870
871 log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
872 }
873 } else {
874
875 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
876 * Therefore session stop and session removal may be two distinct events.
877 * Session stop is quite significant on its own, let's log it. */
878 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
879 LOG_ITEM("SESSION_ID=%s", s->id),
880 LOG_ITEM("USER_ID=%s", s->user->user_record->user_name),
881 LOG_ITEM("LEADER="PID_FMT, s->leader.pid),
882 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
883 }
884
885 return 0;
886}
887
888int session_stop(Session *s, bool force) {
889 int r;
890
891 assert(s);
892
893 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
894 * request via the bus (either directly for the session object or for the seat or user object this session
895 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
896 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
897
898 if (!s->user)
899 return -ESTALE;
900 if (!s->started)
901 return 0;
902 if (s->stopping)
903 return 0;
904
905 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
906
907 if (s->seat)
908 seat_evict_position(s->seat, s);
909
910 /* Kill cgroup */
911 r = session_stop_scope(s, force);
912
913 s->stopping = true;
914
915 user_elect_display(s->user);
916
917 (void) session_save(s);
918 (void) user_save(s->user);
919
920 return r;
921}
922
923int session_finalize(Session *s) {
924 SessionDevice *sd;
925
926 assert(s);
927
928 if (!s->user)
929 return -ESTALE;
930
931 if (s->started)
932 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
933 LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP_STR),
934 LOG_ITEM("SESSION_ID=%s", s->id),
935 LOG_ITEM("USER_ID=%s", s->user->user_record->user_name),
936 LOG_ITEM("LEADER="PID_FMT, s->leader.pid),
937 LOG_MESSAGE("Removed session %s.", s->id));
938
939 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
940
941 if (s->seat)
942 seat_evict_position(s->seat, s);
943
944 /* Kill session devices */
945 while ((sd = hashmap_first(s->devices)))
946 session_device_free(sd);
947
948 (void) unlink(s->state_file);
949 session_add_to_gc_queue(s);
950 user_add_to_gc_queue(s->user);
951
952 if (s->started) {
953 session_send_signal(s, false);
954 s->started = false;
955 }
956
957 if (s->seat) {
958 if (s->seat->active == s)
959 seat_set_active(s->seat, NULL);
960
961 seat_save(s->seat);
962 }
963
964 session_reset_leader(s, /* keep_fdstore = */ false);
965
966 (void) user_save(s->user);
967 (void) user_send_changed(s->user, "Display");
968
969 return 0;
970}
971
972static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
973 Session *s = ASSERT_PTR(userdata);
974
975 assert(es);
976
977 session_stop(s, /* force = */ false);
978 return 0;
979}
980
981int session_release(Session *s) {
982 assert(s);
983
984 if (!s->started || s->stopping)
985 return 0;
986
987 if (s->timer_event_source)
988 return 0;
989
990 return sd_event_add_time_relative(
991 s->manager->event,
992 &s->timer_event_source,
993 CLOCK_MONOTONIC,
994 RELEASE_USEC, 0,
995 release_timeout_callback, s);
996}
997
998bool session_is_active(Session *s) {
999 assert(s);
1000
1001 if (!s->seat)
1002 return true;
1003
1004 return s->seat->active == s;
1005}
1006
1007static int get_tty_atime(const char *tty, usec_t *atime) {
1008 _cleanup_free_ char *p = NULL;
1009 struct stat st;
1010
1011 assert(tty);
1012 assert(atime);
1013
1014 if (!path_is_absolute(tty)) {
1015 p = path_join("/dev", tty);
1016 if (!p)
1017 return -ENOMEM;
1018
1019 tty = p;
1020 } else if (!path_startswith(tty, "/dev/"))
1021 return -ENOENT;
1022
1023 if (lstat(tty, &st) < 0)
1024 return -errno;
1025
1026 *atime = timespec_load(&st.st_atim);
1027 return 0;
1028}
1029
1030static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
1031 _cleanup_free_ char *p = NULL;
1032 int r;
1033
1034 assert(pid > 0);
1035 assert(atime);
1036
1037 r = get_ctty(pid, NULL, &p);
1038 if (r < 0)
1039 return r;
1040
1041 return get_tty_atime(p, atime);
1042}
1043
1044int session_get_idle_hint(Session *s, dual_timestamp *t) {
1045 usec_t atime = 0, dtime = 0;
1046 int r;
1047
1048 assert(s);
1049
1050 if (!SESSION_CLASS_CAN_IDLE(s->class))
1051 return false;
1052
1053 /* Graphical sessions have an explicit idle hint */
1054 if (SESSION_TYPE_IS_GRAPHICAL(s->type)) {
1055 if (t)
1056 *t = s->idle_hint_timestamp;
1057
1058 return s->idle_hint;
1059 }
1060
1061 if (s->type == SESSION_TTY) {
1062 /* For sessions with an explicitly configured tty, let's check its atime */
1063 if (s->tty) {
1064 r = get_tty_atime(s->tty, &atime);
1065 if (r >= 0)
1066 goto found_atime;
1067 }
1068
1069 /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of
1070 * the leader */
1071 if (pidref_is_set(&s->leader)) {
1072 r = get_process_ctty_atime(s->leader.pid, &atime);
1073 if (r >= 0)
1074 goto found_atime;
1075 }
1076 }
1077
1078 if (t)
1079 *t = DUAL_TIMESTAMP_NULL;
1080
1081 return false;
1082
1083found_atime:
1084 if (t)
1085 dual_timestamp_from_realtime(t, atime);
1086
1087 if (s->manager->idle_action_usec > 0 && s->manager->stop_idle_session_usec != USEC_INFINITY)
1088 dtime = MIN(s->manager->idle_action_usec, s->manager->stop_idle_session_usec);
1089 else if (s->manager->idle_action_usec > 0)
1090 dtime = s->manager->idle_action_usec;
1091 else if (s->manager->stop_idle_session_usec != USEC_INFINITY)
1092 dtime = s->manager->stop_idle_session_usec;
1093 else
1094 return false;
1095
1096 return usec_add(atime, dtime) <= now(CLOCK_REALTIME);
1097}
1098
1099int session_set_idle_hint(Session *s, bool b) {
1100 assert(s);
1101
1102 if (!SESSION_CLASS_CAN_IDLE(s->class)) /* Only some session classes know the idle concept at all */
1103 return -ENOTTY;
1104 if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) /* And only graphical session types can set the field explicitly */
1105 return -ENOTTY;
1106
1107 if (s->idle_hint == b)
1108 return 0;
1109
1110 s->idle_hint = b;
1111 dual_timestamp_now(&s->idle_hint_timestamp);
1112
1113 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1114
1115 if (s->seat)
1116 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1117
1118 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1119 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1120
1121 return 1;
1122}
1123
1124int session_get_locked_hint(Session *s) {
1125 assert(s);
1126
1127 return s->locked_hint;
1128}
1129
1130int session_set_locked_hint(Session *s, bool b) {
1131 assert(s);
1132
1133 if (!SESSION_CLASS_CAN_LOCK(s->class))
1134 return -ENOTTY;
1135
1136 if (s->locked_hint == b)
1137 return 0;
1138
1139 s->locked_hint = b;
1140 (void) session_save(s);
1141 (void) session_send_changed(s, "LockedHint");
1142
1143 return 1;
1144}
1145
1146void session_set_type(Session *s, SessionType t) {
1147 assert(s);
1148
1149 if (s->type == t)
1150 return;
1151
1152 s->type = t;
1153 (void) session_save(s);
1154 (void) session_send_changed(s, "Type");
1155}
1156
1157void session_set_class(Session *s, SessionClass c) {
1158 assert(s);
1159
1160 if (s->class == c)
1161 return;
1162
1163 s->class = c;
1164 (void) session_save(s);
1165 (void) session_send_changed(s, "Class");
1166
1167 /* This class change might mean we need the per-user session manager now. Try to start it. */
1168 (void) user_start_service_manager(s->user);
1169}
1170
1171int session_set_display(Session *s, const char *display) {
1172 int r;
1173
1174 assert(s);
1175 assert(display);
1176
1177 r = free_and_strdup(&s->display, display);
1178 if (r <= 0) /* 0 means the strings were equal */
1179 return r;
1180
1181 (void) session_save(s);
1182 (void) session_send_changed(s, "Display");
1183
1184 return 1;
1185}
1186
1187int session_set_tty(Session *s, const char *tty) {
1188 int r;
1189
1190 assert(s);
1191 assert(tty);
1192
1193 r = free_and_strdup(&s->tty, tty);
1194 if (r <= 0) /* 0 means the strings were equal */
1195 return r;
1196
1197 (void) session_save(s);
1198 (void) session_send_changed(s, "TTY");
1199
1200 return 1;
1201}
1202
1203bool session_may_gc(Session *s, bool drop_not_started) {
1204 int r;
1205
1206 assert(s);
1207
1208 if (drop_not_started && !s->started)
1209 return true;
1210
1211 if (!s->user)
1212 return true;
1213
1214 r = pidref_is_alive(&s->leader);
1215 if (r == -ESRCH)
1216 /* Session has no leader. This is probably because the leader vanished before deserializing
1217 * pidfd from FD store. */
1218 return true;
1219 if (r < 0)
1220 log_debug_errno(r, "Unable to determine if leader PID " PID_FMT " is still alive, assuming not: %m", s->leader.pid);
1221 if (r > 0)
1222 return false;
1223
1224 if (s->scope_job) {
1225 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1226
1227 r = manager_job_is_active(s->manager, s->scope_job, &error);
1228 if (r < 0)
1229 log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r));
1230 if (r != 0)
1231 return false;
1232 }
1233
1234 if (s->scope) {
1235 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1236
1237 r = manager_unit_is_active(s->manager, s->scope, &error);
1238 if (r < 0)
1239 log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r));
1240 if (r != 0)
1241 return false;
1242 }
1243
1244 return true;
1245}
1246
1247void session_add_to_gc_queue(Session *s) {
1248 assert(s);
1249
1250 if (s->in_gc_queue)
1251 return;
1252
1253 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1254 s->in_gc_queue = true;
1255}
1256
1257SessionState session_get_state(Session *s) {
1258 assert(s);
1259
1260 /* always check closing first */
1261 if (s->stopping || s->timer_event_source)
1262 return SESSION_CLOSING;
1263
1264 if (s->scope_job || !pidref_is_set(&s->leader))
1265 return SESSION_OPENING;
1266
1267 if (session_is_active(s))
1268 return SESSION_ACTIVE;
1269
1270 return SESSION_ONLINE;
1271}
1272
1273int session_kill(Session *s, KillWhom whom, int signo, sd_bus_error *error) {
1274 assert(s);
1275
1276 switch (whom) {
1277
1278 case KILL_ALL:
1279 if (!SESSION_CLASS_WANTS_SCOPE(s->class))
1280 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
1281 "Session '%s' has no associated scope", s->id);
1282
1283 if (!s->scope)
1284 return sd_bus_error_set_errnof(error, ESRCH, "Scope for session '%s' not active", s->id);
1285
1286 return manager_kill_unit(s->manager, s->scope, KILL_ALL, signo, error);
1287
1288 case KILL_LEADER:
1289 return pidref_kill(&s->leader, signo);
1290
1291 default:
1292 assert_not_reached();
1293 }
1294}
1295
1296static int session_open_vt(Session *s, bool reopen) {
1297 _cleanup_close_ int fd = -EBADF;
1298 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1299
1300 assert(s);
1301
1302 if (s->vtnr < 1)
1303 return -ENODEV;
1304
1305 if (!reopen && s->vtfd >= 0)
1306 return s->vtfd;
1307
1308 sprintf(path, "/dev/tty%u", s->vtnr);
1309
1310 fd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1311 if (fd < 0)
1312 return log_error_errno(fd, "Cannot open VT %s of session %s: %m", path, s->id);
1313
1314 close_and_replace(s->vtfd, fd);
1315 return s->vtfd;
1316}
1317
1318static int session_prepare_vt(Session *s) {
1319 int vt, r;
1320 struct vt_mode mode = {};
1321
1322 assert(s);
1323
1324 if (s->vtnr < 1)
1325 return 0;
1326
1327 vt = session_open_vt(s, /* reopen = */ false);
1328 if (vt < 0)
1329 return vt;
1330
1331 r = fchown(vt, s->user->user_record->uid, -1);
1332 if (r < 0) {
1333 r = log_error_errno(errno,
1334 "Cannot change owner of /dev/tty%u: %m",
1335 s->vtnr);
1336 goto error;
1337 }
1338
1339 r = ioctl(vt, KDSKBMODE, K_OFF);
1340 if (r < 0) {
1341 r = log_error_errno(errno,
1342 "Cannot set K_OFF on /dev/tty%u: %m",
1343 s->vtnr);
1344 goto error;
1345 }
1346
1347 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1348 if (r < 0) {
1349 r = log_error_errno(errno,
1350 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1351 s->vtnr);
1352 goto error;
1353 }
1354
1355 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1356 * So we need a dummy handler here which just acknowledges *all* VT
1357 * switch requests. */
1358 mode.mode = VT_PROCESS;
1359 mode.relsig = SIGRTMIN;
1360 mode.acqsig = SIGRTMIN + 1;
1361 r = ioctl(vt, VT_SETMODE, &mode);
1362 if (r < 0) {
1363 r = log_error_errno(errno,
1364 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1365 s->vtnr);
1366 goto error;
1367 }
1368
1369 return 0;
1370
1371error:
1372 session_restore_vt(s);
1373 return r;
1374}
1375
1376static void session_restore_vt(Session *s) {
1377 int r;
1378
1379 assert(s);
1380
1381 if (s->vtfd < 0)
1382 return;
1383
1384 r = vt_restore(s->vtfd);
1385 if (r == -EIO) {
1386 /* It might happen if the controlling process exited before or while we were
1387 * restoring the VT as it would leave the old file-descriptor in a hung-up
1388 * state. In this case let's retry with a fresh handle to the virtual terminal. */
1389
1390 /* We do a little dance to avoid having the terminal be available
1391 * for reuse before we've cleaned it up. */
1392
1393 int fd = session_open_vt(s, /* reopen = */ true);
1394 if (fd >= 0)
1395 r = vt_restore(fd);
1396 }
1397 if (r < 0)
1398 log_warning_errno(r, "Failed to restore VT, ignoring: %m");
1399
1400 s->vtfd = safe_close(s->vtfd);
1401}
1402
1403void session_leave_vt(Session *s) {
1404 int r;
1405
1406 assert(s);
1407
1408 /* This is called whenever we get a VT-switch signal from the kernel.
1409 * We acknowledge all of them unconditionally. Note that session are
1410 * free to overwrite those handlers and we only register them for
1411 * sessions with controllers. Legacy sessions are not affected.
1412 * However, if we switch from a non-legacy to a legacy session, we must
1413 * make sure to pause all device before acknowledging the switch. We
1414 * process the real switch only after we are notified via sysfs, so the
1415 * legacy session might have already started using the devices. If we
1416 * don't pause the devices before the switch, we might confuse the
1417 * session we switch to. */
1418
1419 if (s->vtfd < 0)
1420 return;
1421
1422 session_device_pause_all(s);
1423 r = vt_release(s->vtfd, /* restore = */ false);
1424 if (r == -EIO) {
1425 /* Handle the same VT hung-up case as in session_restore_vt */
1426
1427 int fd = session_open_vt(s, /* reopen = */ true);
1428 if (fd >= 0)
1429 r = vt_release(fd, /* restore = */ false);
1430 }
1431 if (r < 0)
1432 log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
1433}
1434
1435bool session_is_controller(Session *s, const char *sender) {
1436 return streq_ptr(ASSERT_PTR(s)->controller, sender);
1437}
1438
1439static void session_release_controller(Session *s, bool notify) {
1440 _unused_ _cleanup_free_ char *name = NULL;
1441 SessionDevice *sd;
1442
1443 assert(s);
1444
1445 if (!s->controller)
1446 return;
1447
1448 name = s->controller;
1449
1450 /* By resetting the controller before releasing the devices, we won't send notification signals.
1451 * This avoids sending useless notifications if the controller is released on disconnects. */
1452 if (!notify)
1453 s->controller = NULL;
1454
1455 while ((sd = hashmap_first(s->devices)))
1456 session_device_free(sd);
1457
1458 s->controller = NULL;
1459 s->track = sd_bus_track_unref(s->track);
1460}
1461
1462static int on_bus_track(sd_bus_track *track, void *userdata) {
1463 Session *s = ASSERT_PTR(userdata);
1464
1465 assert(track);
1466
1467 session_drop_controller(s);
1468
1469 return 0;
1470}
1471
1472int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1473 _cleanup_free_ char *name = NULL;
1474 int r;
1475
1476 assert(s);
1477 assert(sender);
1478
1479 if (session_is_controller(s, sender))
1480 return 0;
1481 if (s->controller && !force)
1482 return -EBUSY;
1483
1484 name = strdup(sender);
1485 if (!name)
1486 return -ENOMEM;
1487
1488 s->track = sd_bus_track_unref(s->track);
1489 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1490 if (r < 0)
1491 return r;
1492
1493 r = sd_bus_track_add_name(s->track, name);
1494 if (r < 0)
1495 return r;
1496
1497 /* When setting a session controller, we forcibly mute the VT and set
1498 * it into graphics-mode. Applications can override that by changing
1499 * VT state after calling TakeControl(). However, this serves as a good
1500 * default and well-behaving controllers can now ignore VTs entirely.
1501 * Note that we reset the VT on ReleaseControl() and if the controller
1502 * exits.
1503 * If logind crashes/restarts, we restore the controller during restart
1504 * (without preparing the VT since the controller has probably overridden
1505 * VT state by now) or reset the VT in case it crashed/exited, too. */
1506 if (prepare) {
1507 r = session_prepare_vt(s);
1508 if (r < 0) {
1509 s->track = sd_bus_track_unref(s->track);
1510 return r;
1511 }
1512 }
1513
1514 session_release_controller(s, true);
1515 s->controller = TAKE_PTR(name);
1516 (void) session_save(s);
1517
1518 return 0;
1519}
1520
1521void session_drop_controller(Session *s) {
1522 assert(s);
1523
1524 if (!s->controller)
1525 return;
1526
1527 s->track = sd_bus_track_unref(s->track);
1528 session_set_type(s, s->original_type);
1529 session_release_controller(s, false);
1530 (void) session_save(s);
1531 session_restore_vt(s);
1532}
1533
1534bool session_job_pending(Session *s) {
1535 assert(s);
1536 assert(s->user);
1537
1538 /* Check if we have some jobs enqueued and not finished yet. Each time we get JobRemoved signal about
1539 * relevant units, session_send_create_reply and hence us is called (see match_job_removed).
1540 * Note that we don't care about job result here. */
1541
1542 return s->scope_job ||
1543 s->user->runtime_dir_job ||
1544 (SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) && s->user->service_manager_job);
1545}
1546
1547int session_send_create_reply(Session *s, const sd_bus_error *error) {
1548 int r;
1549
1550 assert(s);
1551
1552 /* If error occurred, return it immediately. Otherwise let's wait for all jobs to finish before
1553 * continuing. */
1554 if (!sd_bus_error_is_set(error) && session_job_pending(s))
1555 return 0;
1556
1557 r = 0;
1558 RET_GATHER(r, session_send_create_reply_bus(s, error));
1559 RET_GATHER(r, session_send_create_reply_varlink(s, error));
1560 return r;
1561}
1562
1563bool session_is_self(const char *name) {
1564 return isempty(name) || streq(name, "self");
1565}
1566
1567bool session_is_auto(const char *name) {
1568 return streq_ptr(name, "auto");
1569}
1570
1571static const char* const session_state_table[_SESSION_STATE_MAX] = {
1572 [SESSION_OPENING] = "opening",
1573 [SESSION_ONLINE] = "online",
1574 [SESSION_ACTIVE] = "active",
1575 [SESSION_CLOSING] = "closing",
1576};
1577
1578DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1579
1580static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1581 [SESSION_UNSPECIFIED] = "unspecified",
1582 [SESSION_TTY] = "tty",
1583 [SESSION_X11] = "x11",
1584 [SESSION_WAYLAND] = "wayland",
1585 [SESSION_MIR] = "mir",
1586 [SESSION_WEB] = "web",
1587};
1588
1589DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1590
1591static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1592 [SESSION_USER] = "user",
1593 [SESSION_USER_EARLY] = "user-early",
1594 [SESSION_USER_INCOMPLETE] = "user-incomplete",
1595 [SESSION_USER_LIGHT] = "user-light",
1596 [SESSION_USER_EARLY_LIGHT] = "user-early-light",
1597 [SESSION_GREETER] = "greeter",
1598 [SESSION_LOCK_SCREEN] = "lock-screen",
1599 [SESSION_BACKGROUND] = "background",
1600 [SESSION_BACKGROUND_LIGHT] = "background-light",
1601 [SESSION_MANAGER] = "manager",
1602 [SESSION_MANAGER_EARLY] = "manager-early",
1603 [SESSION_NONE] = "none",
1604};
1605
1606DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1607
1608static const char* const kill_whom_table[_KILL_WHOM_MAX] = {
1609 [KILL_LEADER] = "leader",
1610 [KILL_ALL] = "all",
1611};
1612
1613DEFINE_STRING_TABLE_LOOKUP(kill_whom, KillWhom);
1614
1615static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
1616 [TTY_FROM_PAM] = "from-pam",
1617 [TTY_FROM_UTMP] = "from-utmp",
1618 [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
1619};
1620
1621DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);