]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-session.c
generators: drop umask calls
[thirdparty/systemd.git] / src / login / logind-session.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
20263082
LP
2
3#include <errno.h>
90a18413 4#include <fcntl.h>
90a18413 5#include <linux/kd.h>
4f5dd394 6#include <linux/vt.h>
90a18413 7#include <signal.h>
44176400 8#include <stdio_ext.h>
20263082 9#include <string.h>
90a18413 10#include <sys/ioctl.h>
20263082
LP
11#include <unistd.h>
12
cc377381 13#include "sd-messages.h"
4f5dd394 14
b5efdb8a 15#include "alloc-util.h"
430f0182 16#include "audit-util.h"
cc377381 17#include "bus-error.h"
4f5dd394
LP
18#include "bus-util.h"
19#include "escape.h"
3ffd4af2 20#include "fd-util.h"
4f5dd394 21#include "fileio.h"
f97b34a6 22#include "format-util.h"
c004493c 23#include "io-util.h"
3ffd4af2 24#include "logind-session.h"
4f5dd394 25#include "mkdir.h"
6bedfcbb 26#include "parse-util.h"
4f5dd394 27#include "path-util.h"
8c29a457 28#include "process-util.h"
d68c645b 29#include "serialize.h"
8b43440b 30#include "string-table.h"
25a1ab4e 31#include "strv.h"
288a74cc 32#include "terminal-util.h"
b1d4f8e1 33#include "user-util.h"
4f5dd394 34#include "util.h"
20263082 35
5f41d1f1
LP
36#define RELEASE_USEC (20*USEC_PER_SEC)
37
38static void session_remove_fifo(Session *s);
39
8c29a457
LP
40int session_new(Session **ret, Manager *m, const char *id) {
41 _cleanup_(session_freep) Session *s = NULL;
42 int r;
20263082 43
8c29a457 44 assert(ret);
20263082
LP
45 assert(m);
46 assert(id);
47
8c29a457
LP
48 if (!session_id_valid(id))
49 return -EINVAL;
50
51 s = new(Session, 1);
20263082 52 if (!s)
8c29a457
LP
53 return -ENOMEM;
54
55 *s = (Session) {
56 .manager = m,
57 .fifo_fd = -1,
58 .vtfd = -1,
59 .audit_id = AUDIT_SESSION_INVALID,
3d0ef5c7 60 .tty_validity = _TTY_VALIDITY_INVALID,
8c29a457 61 };
20263082 62
98a28fef 63 s->state_file = strappend("/run/systemd/sessions/", id);
6b430fdb 64 if (!s->state_file)
8c29a457 65 return -ENOMEM;
118ecf32 66
2b6bf07d 67 s->id = basename(s->state_file);
20263082 68
8c29a457
LP
69 s->devices = hashmap_new(&devt_hash_ops);
70 if (!s->devices)
71 return -ENOMEM;
20263082 72
8c29a457
LP
73 r = hashmap_put(m->sessions, s->id, s);
74 if (r < 0)
75 return r;
20263082 76
8c29a457
LP
77 *ret = TAKE_PTR(s);
78 return 0;
20263082
LP
79}
80
8c29a457 81Session* session_free(Session *s) {
118ecf32
DH
82 SessionDevice *sd;
83
8c29a457
LP
84 if (!s)
85 return NULL;
20263082 86
14c3baca 87 if (s->in_gc_queue)
71fda00f 88 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
14c3baca 89
5f41d1f1
LP
90 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
91
cc377381
LP
92 session_remove_fifo(s);
93
ae5e06bd
DH
94 session_drop_controller(s);
95
118ecf32
DH
96 while ((sd = hashmap_first(s->devices)))
97 session_device_free(sd);
98
99 hashmap_free(s->devices);
100
20263082 101 if (s->user) {
71fda00f 102 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
20263082
LP
103
104 if (s->user->display == s)
105 s->user->display = NULL;
9afe9efb
LP
106
107 user_update_last_session_timer(s->user);
20263082
LP
108 }
109
9418f147
LP
110 if (s->seat) {
111 if (s->seat->active == s)
112 s->seat->active = NULL;
d7bd01b5
DH
113 if (s->seat->pending_switch == s)
114 s->seat->pending_switch = NULL;
9418f147 115
49e6fdbf 116 seat_evict_position(s->seat, s);
71fda00f 117 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
9418f147 118 }
20263082 119
fb6becb4
LP
120 if (s->scope) {
121 hashmap_remove(s->manager->session_units, s->scope);
122 free(s->scope);
123 }
124
238794b1
LP
125 if (pid_is_valid(s->leader))
126 (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
127
fb6becb4 128 free(s->scope_job);
1713813d 129
cc377381 130 sd_bus_message_unref(s->create_message);
20263082
LP
131
132 free(s->tty);
133 free(s->display);
134 free(s->remote_host);
3f49d45a 135 free(s->remote_user);
98a28fef 136 free(s->service);
a4cd87e9 137 free(s->desktop);
20263082
LP
138
139 hashmap_remove(s->manager->sessions, s->id);
98a28fef 140
d2f92cdf 141 free(s->state_file);
8c29a457
LP
142
143 return mfree(s);
20263082
LP
144}
145
9444b1f2
LP
146void session_set_user(Session *s, User *u) {
147 assert(s);
148 assert(!s->user);
149
150 s->user = u;
71fda00f 151 LIST_PREPEND(sessions_by_user, u->sessions, s);
9afe9efb
LP
152
153 user_update_last_session_timer(u);
9444b1f2
LP
154}
155
238794b1
LP
156int session_set_leader(Session *s, pid_t pid) {
157 int r;
158
159 assert(s);
160
161 if (!pid_is_valid(pid))
162 return -EINVAL;
163
164 if (s->leader == pid)
165 return 0;
166
167 r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pid), s);
168 if (r < 0)
169 return r;
170
171 if (pid_is_valid(s->leader))
172 (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
173
174 s->leader = pid;
175 (void) audit_session_from_pid(pid, &s->audit_id);
176
177 return 1;
178}
179
aed24c4c
FB
180static void session_save_devices(Session *s, FILE *f) {
181 SessionDevice *sd;
182 Iterator i;
183
184 if (!hashmap_isempty(s->devices)) {
185 fprintf(f, "DEVICES=");
186 HASHMAP_FOREACH(sd, s->devices, i)
187 fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
188 fprintf(f, "\n");
189 }
190}
191
20263082 192int session_save(Session *s) {
507f22bd 193 _cleanup_free_ char *temp_path = NULL;
cc377381 194 _cleanup_fclose_ FILE *f = NULL;
20263082
LP
195 int r = 0;
196
197 assert(s);
198
9444b1f2
LP
199 if (!s->user)
200 return -ESTALE;
201
accaeded
LP
202 if (!s->started)
203 return 0;
204
37c1d5e9 205 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
20263082 206 if (r < 0)
dacd6cee 207 goto fail;
20263082 208
14c3baca
LP
209 r = fopen_temporary(s->state_file, &f, &temp_path);
210 if (r < 0)
dacd6cee 211 goto fail;
20263082 212
44176400
LP
213 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
214 (void) fchmod(fileno(f), 0644);
14c3baca 215
20263082
LP
216 fprintf(f,
217 "# This is private data. Do not parse.\n"
90b2de37 218 "UID="UID_FMT"\n"
20263082
LP
219 "USER=%s\n"
220 "ACTIVE=%i\n"
1c8280fd 221 "IS_DISPLAY=%i\n"
0604381b 222 "STATE=%s\n"
fb6becb4 223 "REMOTE=%i\n",
90b2de37 224 s->user->uid,
20263082
LP
225 s->user->name,
226 session_is_active(s),
1c8280fd 227 s->user->display == s,
0604381b 228 session_state_to_string(session_get_state(s)),
fb6becb4 229 s->remote);
20263082 230
a91e4e53 231 if (s->type >= 0)
507f22bd 232 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
a91e4e53 233
55efac6c 234 if (s->class >= 0)
507f22bd 235 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
55efac6c 236
fb6becb4
LP
237 if (s->scope)
238 fprintf(f, "SCOPE=%s\n", s->scope);
fb6becb4
LP
239 if (s->scope_job)
240 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
20263082 241
932e3ee7 242 if (s->fifo_path)
507f22bd 243 fprintf(f, "FIFO=%s\n", s->fifo_path);
932e3ee7 244
20263082 245 if (s->seat)
507f22bd 246 fprintf(f, "SEAT=%s\n", s->seat->id);
20263082
LP
247
248 if (s->tty)
507f22bd 249 fprintf(f, "TTY=%s\n", s->tty);
20263082 250
3d0ef5c7
LP
251 if (s->tty_validity >= 0)
252 fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
253
20263082 254 if (s->display)
507f22bd 255 fprintf(f, "DISPLAY=%s\n", s->display);
20263082 256
558c6490
LP
257 if (s->remote_host) {
258 _cleanup_free_ char *escaped;
259
260 escaped = cescape(s->remote_host);
261 if (!escaped) {
262 r = -ENOMEM;
dacd6cee 263 goto fail;
558c6490
LP
264 }
265
266 fprintf(f, "REMOTE_HOST=%s\n", escaped);
267 }
268
269 if (s->remote_user) {
270 _cleanup_free_ char *escaped;
271
272 escaped = cescape(s->remote_user);
273 if (!escaped) {
274 r = -ENOMEM;
dacd6cee 275 goto fail;
558c6490
LP
276 }
277
278 fprintf(f, "REMOTE_USER=%s\n", escaped);
279 }
280
281 if (s->service) {
282 _cleanup_free_ char *escaped;
20263082 283
558c6490
LP
284 escaped = cescape(s->service);
285 if (!escaped) {
286 r = -ENOMEM;
dacd6cee 287 goto fail;
558c6490
LP
288 }
289
290 fprintf(f, "SERVICE=%s\n", escaped);
291 }
3f49d45a 292
558c6490
LP
293 if (s->desktop) {
294 _cleanup_free_ char *escaped;
98a28fef 295
558c6490
LP
296 escaped = cescape(s->desktop);
297 if (!escaped) {
298 r = -ENOMEM;
dacd6cee 299 goto fail;
558c6490
LP
300 }
301
302 fprintf(f, "DESKTOP=%s\n", escaped);
303 }
a4cd87e9 304
bf7825ae 305 if (s->seat && seat_has_vts(s->seat))
92bd5ff3 306 fprintf(f, "VTNR=%u\n", s->vtnr);
20263082 307
49e6fdbf 308 if (!s->vtnr)
e6494a07 309 fprintf(f, "POSITION=%u\n", s->position);
49e6fdbf 310
54191eb3 311 if (pid_is_valid(s->leader))
90b2de37 312 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
20263082 313
3a87a86e 314 if (audit_session_is_valid(s->audit_id))
507f22bd 315 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
20263082 316
9444b1f2
LP
317 if (dual_timestamp_is_set(&s->timestamp))
318 fprintf(f,
90b2de37
ZJS
319 "REALTIME="USEC_FMT"\n"
320 "MONOTONIC="USEC_FMT"\n",
321 s->timestamp.realtime,
322 s->timestamp.monotonic);
9444b1f2 323
aed24c4c 324 if (s->controller) {
6d33772f 325 fprintf(f, "CONTROLLER=%s\n", s->controller);
aed24c4c
FB
326 session_save_devices(s, f);
327 }
6d33772f 328
dacd6cee
LP
329 r = fflush_and_check(f);
330 if (r < 0)
331 goto fail;
14c3baca 332
dacd6cee 333 if (rename(temp_path, s->state_file) < 0) {
20263082 334 r = -errno;
dacd6cee 335 goto fail;
20263082
LP
336 }
337
dacd6cee
LP
338 return 0;
339
340fail:
341 (void) unlink(s->state_file);
14c3baca 342
dacd6cee
LP
343 if (temp_path)
344 (void) unlink(temp_path);
345
346 return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
20263082
LP
347}
348
aed24c4c
FB
349static int session_load_devices(Session *s, const char *devices) {
350 const char *p;
351 int r = 0;
352
353 assert(s);
354
355 for (p = devices;;) {
356 _cleanup_free_ char *word = NULL;
357 SessionDevice *sd;
358 dev_t dev;
359 int k;
360
361 k = extract_first_word(&p, &word, NULL, 0);
362 if (k == 0)
363 break;
364 if (k < 0) {
365 r = k;
366 break;
367 }
368
369 k = parse_dev(word, &dev);
370 if (k < 0) {
371 r = k;
372 continue;
373 }
374
375 /* The file descriptors for loaded devices will be reattached later. */
376 k = session_device_new(s, dev, false, &sd);
377 if (k < 0)
378 r = k;
379 }
380
381 if (r < 0)
382 log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
383
384 return r;
385}
dacd6cee 386
20263082 387int session_load(Session *s) {
9444b1f2 388 _cleanup_free_ char *remote = NULL,
a185c5aa 389 *seat = NULL,
3d0ef5c7 390 *tty_validity = NULL,
a185c5aa 391 *vtnr = NULL,
be94d954 392 *state = NULL,
e6494a07 393 *position = NULL,
a185c5aa 394 *leader = NULL,
55efac6c 395 *type = NULL,
9444b1f2
LP
396 *class = NULL,
397 *uid = NULL,
398 *realtime = NULL,
6d33772f 399 *monotonic = NULL,
aed24c4c
FB
400 *controller = NULL,
401 *active = NULL,
1c8280fd
LP
402 *devices = NULL,
403 *is_display = NULL;
a185c5aa
LP
404
405 int k, r;
406
20263082
LP
407 assert(s);
408
aa8fbc74 409 r = parse_env_file(NULL, s->state_file,
a185c5aa 410 "REMOTE", &remote,
fb6becb4
LP
411 "SCOPE", &s->scope,
412 "SCOPE_JOB", &s->scope_job,
932e3ee7 413 "FIFO", &s->fifo_path,
a185c5aa
LP
414 "SEAT", &seat,
415 "TTY", &s->tty,
3d0ef5c7 416 "TTY_VALIDITY", &tty_validity,
a185c5aa
LP
417 "DISPLAY", &s->display,
418 "REMOTE_HOST", &s->remote_host,
419 "REMOTE_USER", &s->remote_user,
98a28fef 420 "SERVICE", &s->service,
a4cd87e9 421 "DESKTOP", &s->desktop,
a185c5aa 422 "VTNR", &vtnr,
be94d954 423 "STATE", &state,
e6494a07 424 "POSITION", &position,
a185c5aa 425 "LEADER", &leader,
a91e4e53 426 "TYPE", &type,
55efac6c 427 "CLASS", &class,
9444b1f2
LP
428 "UID", &uid,
429 "REALTIME", &realtime,
430 "MONOTONIC", &monotonic,
6d33772f 431 "CONTROLLER", &controller,
aed24c4c
FB
432 "ACTIVE", &active,
433 "DEVICES", &devices,
13df9c39 434 "IS_DISPLAY", &is_display);
a185c5aa 435
f647962d
MS
436 if (r < 0)
437 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
9444b1f2
LP
438
439 if (!s->user) {
440 uid_t u;
441 User *user;
442
443 if (!uid) {
444 log_error("UID not specified for session %s", s->id);
445 return -ENOENT;
446 }
447
448 r = parse_uid(uid, &u);
449 if (r < 0) {
450 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
451 return r;
452 }
453
8cb4ab00 454 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
9444b1f2
LP
455 if (!user) {
456 log_error("User of session %s not known.", s->id);
457 return -ENOENT;
458 }
459
460 session_set_user(s, user);
461 }
a185c5aa
LP
462
463 if (remote) {
464 k = parse_boolean(remote);
465 if (k >= 0)
466 s->remote = k;
467 }
468
c506027a
DH
469 if (vtnr)
470 safe_atou(vtnr, &s->vtnr);
471
9418f147 472 if (seat && !s->seat) {
a185c5aa
LP
473 Seat *o;
474
475 o = hashmap_get(s->manager->seats, seat);
476 if (o)
c506027a
DH
477 r = seat_attach_session(o, s);
478 if (!o || r < 0)
479 log_error("Cannot attach session %s to seat %s", s->id, seat);
a185c5aa
LP
480 }
481
c506027a
DH
482 if (!s->seat || !seat_has_vts(s->seat))
483 s->vtnr = 0;
a185c5aa 484
e6494a07 485 if (position && s->seat) {
14cb109d 486 unsigned npos;
49e6fdbf 487
e6494a07 488 safe_atou(position, &npos);
49e6fdbf
DH
489 seat_claim_position(s->seat, s, npos);
490 }
491
3d0ef5c7
LP
492 if (tty_validity) {
493 TTYValidity v;
494
495 v = tty_validity_from_string(tty_validity);
496 if (v < 0)
497 log_debug("Failed to parse TTY validity: %s", tty_validity);
498 else
499 s->tty_validity = v;
500 }
501
a185c5aa 502 if (leader) {
238794b1
LP
503 pid_t pid;
504
505 r = parse_pid(leader, &pid);
506 if (r < 0)
507 log_debug_errno(r, "Failed to parse leader PID of session: %s", leader);
508 else {
509 r = session_set_leader(s, pid);
510 if (r < 0)
511 log_warning_errno(r, "Failed to set session leader PID, ignoring: %m");
512 }
a185c5aa
LP
513 }
514
a91e4e53
LP
515 if (type) {
516 SessionType t;
517
518 t = session_type_from_string(type);
519 if (t >= 0)
520 s->type = t;
521 }
522
55efac6c
LP
523 if (class) {
524 SessionClass c;
525
526 c = session_class_from_string(class);
527 if (c >= 0)
528 s->class = c;
529 }
530
be94d954
MP
531 if (state && streq(state, "closing"))
532 s->stopping = true;
533
b4f78aea
LP
534 if (s->fifo_path) {
535 int fd;
536
537 /* If we open an unopened pipe for reading we will not
538 get an EOF. to trigger an EOF we hence open it for
be94d954
MP
539 writing, but close it right away which then will
540 trigger the EOF. This will happen immediately if no
541 other process has the FIFO open for writing, i. e.
542 when the session died before logind (re)started. */
b4f78aea
LP
543
544 fd = session_create_fifo(s);
03e334a1 545 safe_close(fd);
b4f78aea
LP
546 }
547
b895a735 548 if (realtime)
d68c645b 549 (void) deserialize_usec(realtime, &s->timestamp.realtime);
b895a735 550 if (monotonic)
d68c645b 551 (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
a185c5aa 552
aed24c4c
FB
553 if (active) {
554 k = parse_boolean(active);
555 if (k >= 0)
556 s->was_active = k;
557 }
558
1c8280fd
LP
559 if (is_display) {
560 /* Note that when enumerating users are loaded before sessions, hence the display session to use is
561 * something we have to store along with the session and not the user, as in that case we couldn't
562 * apply it at the time we load the user. */
563
564 k = parse_boolean(is_display);
565 if (k < 0)
566 log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
567 else if (k > 0)
568 s->user->display = s;
569 }
570
6d33772f 571 if (controller) {
aed24c4c 572 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
dc6284e9 573 session_set_controller(s, controller, false, false);
aed24c4c
FB
574 session_load_devices(s, devices);
575 } else
90a18413 576 session_restore_vt(s);
6d33772f
DH
577 }
578
a185c5aa 579 return r;
20263082
LP
580}
581
582int session_activate(Session *s) {
14cb109d 583 unsigned num_pending;
d7bd01b5 584
20263082 585 assert(s);
9444b1f2 586 assert(s->user);
20263082 587
20263082 588 if (!s->seat)
15411c0c 589 return -EOPNOTSUPP;
20263082
LP
590
591 if (s->seat->active == s)
592 return 0;
593
d7bd01b5
DH
594 /* on seats with VTs, we let VTs manage session-switching */
595 if (seat_has_vts(s->seat)) {
709d0587 596 if (s->vtnr == 0)
15411c0c 597 return -EOPNOTSUPP;
d7bd01b5
DH
598
599 return chvt(s->vtnr);
600 }
601
602 /* On seats without VTs, we implement session-switching in logind. We
603 * try to pause all session-devices and wait until the session
604 * controller acknowledged them. Once all devices are asleep, we simply
605 * switch the active session and be done.
606 * We save the session we want to switch to in seat->pending_switch and
607 * seat_complete_switch() will perform the final switch. */
608
609 s->seat->pending_switch = s;
610
611 /* if no devices are running, immediately perform the session switch */
612 num_pending = session_device_try_pause_all(s);
613 if (!num_pending)
614 seat_complete_switch(s->seat);
20263082 615
d7bd01b5 616 return 0;
20263082
LP
617}
618
25a1ab4e 619static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
98a28fef
LP
620 int r;
621
622 assert(s);
9444b1f2 623 assert(s->user);
98a28fef 624
fb6becb4 625 if (!s->scope) {
fb2367ed 626 _cleanup_free_ char *scope = NULL;
90558f31 627 const char *description;
405e0255 628
25a1ab4e
LP
629 s->scope_job = mfree(s->scope_job);
630
605405c6 631 scope = strjoin("session-", s->id, ".scope");
d0af76e6 632 if (!scope)
ae018d9b
LP
633 return log_oom();
634
81d62103 635 description = strjoina("Session ", s->id, " of user ", s->user->name);
90558f31
LP
636
637 r = manager_start_scope(
638 s->manager,
639 scope,
640 s->leader,
641 s->user->slice,
642 description,
25a1ab4e
LP
643 STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
644 STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
d5ac9d06 645 s->user->home,
22f93314 646 properties,
25a1ab4e
LP
647 error,
648 &s->scope_job);
fb2367ed 649 if (r < 0)
25a1ab4e 650 return log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(error, r));
fb2367ed
YW
651
652 s->scope = TAKE_PTR(scope);
20263082
LP
653 }
654
d0af76e6 655 if (s->scope)
90558f31 656 (void) hashmap_put(s->manager->session_units, s->scope, s);
d0af76e6 657
20263082
LP
658 return 0;
659}
660
25a1ab4e 661int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
20263082
LP
662 int r;
663
664 assert(s);
9444b1f2
LP
665
666 if (!s->user)
667 return -ESTALE;
20263082 668
25a1ab4e
LP
669 if (s->stopping)
670 return -EINVAL;
671
9418f147
LP
672 if (s->started)
673 return 0;
674
ed18b08b
LP
675 r = user_start(s->user);
676 if (r < 0)
677 return r;
678
25a1ab4e 679 r = session_start_scope(s, properties, error);
fb6becb4
LP
680 if (r < 0)
681 return r;
682
d9eb81f9 683 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
2b044526 684 "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
877d54e9
LP
685 "SESSION_ID=%s", s->id,
686 "USER_ID=%s", s->user->name,
de0671ee 687 "LEADER="PID_FMT, s->leader,
a1230ff9 688 LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name));
98a28fef 689
9444b1f2
LP
690 if (!dual_timestamp_is_set(&s->timestamp))
691 dual_timestamp_get(&s->timestamp);
14c3baca 692
e9816c48
LP
693 if (s->seat)
694 seat_read_active_vt(s->seat);
695
9418f147
LP
696 s->started = true;
697
952d3260
LP
698 user_elect_display(s->user);
699
5f41d1f1 700 /* Save data */
e9816c48 701 session_save(s);
7f7bb946 702 user_save(s->user);
5f41d1f1
LP
703 if (s->seat)
704 seat_save(s->seat);
e9816c48 705
5f41d1f1 706 /* Send signals */
da119395 707 session_send_signal(s, true);
7d049e30 708 user_send_changed(s->user, "Display", NULL);
9418f147
LP
709 if (s->seat) {
710 if (s->seat->active == s)
7d049e30 711 seat_send_changed(s->seat, "ActiveSession", NULL);
9418f147
LP
712 }
713
20263082
LP
714 return 0;
715}
716
9bb69af4 717static int session_stop_scope(Session *s, bool force) {
4afd3348 718 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
20263082 719 int r;
20263082
LP
720
721 assert(s);
722
fb6becb4
LP
723 if (!s->scope)
724 return 0;
9b221b63 725
756ed0e2 726 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
629ff674 727 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
756ed0e2
LP
728 * when killing any processes left after this point. */
729 r = manager_abandon_scope(s->manager, s->scope, &error);
25a1ab4e 730 if (r < 0) {
756ed0e2 731 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
25a1ab4e
LP
732 sd_bus_error_free(&error);
733 }
734
735 s->scope_job = mfree(s->scope_job);
756ed0e2
LP
736
737 /* Optionally, let's kill everything that's left now. */
9bb69af4 738 if (force || manager_shall_kill(s->manager, s->user->name)) {
801a884d 739
25a1ab4e
LP
740 r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job);
741 if (r < 0) {
742 if (force)
743 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
20263082 744
25a1ab4e
LP
745 log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
746 }
8150acb1 747 } else {
20263082 748
8150acb1
AJ
749 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
750 * Therefore session stop and session removal may be two distinct events.
751 * Session stop is quite significant on its own, let's log it. */
752 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
753 "SESSION_ID=%s", s->id,
754 "USER_ID=%s", s->user->name,
755 "LEADER="PID_FMT, s->leader,
f4cf1d66 756 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
8150acb1
AJ
757 }
758
9b221b63 759 return 0;
20263082
LP
760}
761
9bb69af4 762int session_stop(Session *s, bool force) {
405e0255
LP
763 int r;
764
765 assert(s);
766
25a1ab4e
LP
767 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
768 * request via the bus (either directly for the session object or for the seat or user object this session
769 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
770 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
771
405e0255
LP
772 if (!s->user)
773 return -ESTALE;
25a1ab4e
LP
774 if (!s->started)
775 return 0;
776 if (s->stopping)
777 return 0;
405e0255 778
5f41d1f1
LP
779 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
780
10189fd6
DH
781 if (s->seat)
782 seat_evict_position(s->seat, s);
783
5f41d1f1
LP
784 /* We are going down, don't care about FIFOs anymore */
785 session_remove_fifo(s);
786
405e0255 787 /* Kill cgroup */
9bb69af4 788 r = session_stop_scope(s, force);
405e0255 789
5f41d1f1
LP
790 s->stopping = true;
791
952d3260
LP
792 user_elect_display(s->user);
793
405e0255 794 session_save(s);
cc377381 795 user_save(s->user);
405e0255
LP
796
797 return r;
798}
799
800int session_finalize(Session *s) {
118ecf32 801 SessionDevice *sd;
20263082
LP
802
803 assert(s);
804
9444b1f2
LP
805 if (!s->user)
806 return -ESTALE;
807
ed18b08b 808 if (s->started)
d9eb81f9 809 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
2b044526 810 "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
877d54e9
LP
811 "SESSION_ID=%s", s->id,
812 "USER_ID=%s", s->user->name,
de0671ee 813 "LEADER="PID_FMT, s->leader,
a1230ff9 814 LOG_MESSAGE("Removed session %s.", s->id));
98a28fef 815
5f41d1f1
LP
816 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
817
10189fd6
DH
818 if (s->seat)
819 seat_evict_position(s->seat, s);
820
118ecf32
DH
821 /* Kill session devices */
822 while ((sd = hashmap_first(s->devices)))
823 session_device_free(sd);
824
491ac9f2 825 (void) unlink(s->state_file);
d2f92cdf 826 session_add_to_gc_queue(s);
ed18b08b 827 user_add_to_gc_queue(s->user);
14c3baca 828
405e0255 829 if (s->started) {
ed18b08b 830 session_send_signal(s, false);
405e0255
LP
831 s->started = false;
832 }
50fb9793 833
9418f147
LP
834 if (s->seat) {
835 if (s->seat->active == s)
836 seat_set_active(s->seat, NULL);
837
23bd3b62 838 seat_save(s->seat);
9418f147
LP
839 }
840
23bd3b62 841 user_save(s->user);
7d049e30 842 user_send_changed(s->user, "Display", NULL);
9418f147 843
491ac9f2 844 return 0;
20263082
LP
845}
846
5f41d1f1
LP
847static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
848 Session *s = userdata;
849
850 assert(es);
851 assert(s);
852
9bb69af4 853 session_stop(s, false);
5f41d1f1
LP
854 return 0;
855}
856
ad8780c9 857int session_release(Session *s) {
5f41d1f1
LP
858 assert(s);
859
860 if (!s->started || s->stopping)
ad8780c9
ZJS
861 return 0;
862
863 if (s->timer_event_source)
864 return 0;
865
866 return sd_event_add_time(s->manager->event,
867 &s->timer_event_source,
868 CLOCK_MONOTONIC,
061c6607 869 usec_add(now(CLOCK_MONOTONIC), RELEASE_USEC), 0,
ad8780c9 870 release_timeout_callback, s);
5f41d1f1
LP
871}
872
20263082
LP
873bool session_is_active(Session *s) {
874 assert(s);
875
876 if (!s->seat)
877 return true;
878
879 return s->seat->active == s;
880}
881
23406ce5
LP
882static int get_tty_atime(const char *tty, usec_t *atime) {
883 _cleanup_free_ char *p = NULL;
a185c5aa 884 struct stat st;
23406ce5
LP
885
886 assert(tty);
887 assert(atime);
888
889 if (!path_is_absolute(tty)) {
890 p = strappend("/dev/", tty);
891 if (!p)
892 return -ENOMEM;
893
894 tty = p;
895 } else if (!path_startswith(tty, "/dev/"))
896 return -ENOENT;
897
898 if (lstat(tty, &st) < 0)
899 return -errno;
900
901 *atime = timespec_load(&st.st_atim);
902 return 0;
903}
904
905static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
906 _cleanup_free_ char *p = NULL;
907 int r;
908
909 assert(pid > 0);
910 assert(atime);
911
912 r = get_ctty(pid, NULL, &p);
913 if (r < 0)
914 return r;
915
916 return get_tty_atime(p, atime);
917}
918
919int session_get_idle_hint(Session *s, dual_timestamp *t) {
23406ce5
LP
920 usec_t atime = 0, n;
921 int r;
a185c5aa
LP
922
923 assert(s);
924
23406ce5 925 /* Explicit idle hint is set */
a185c5aa
LP
926 if (s->idle_hint) {
927 if (t)
928 *t = s->idle_hint_timestamp;
929
930 return s->idle_hint;
931 }
932
0762eaa3 933 /* Graphical sessions should really implement a real
23406ce5 934 * idle hint logic */
129baf1b 935 if (SESSION_TYPE_IS_GRAPHICAL(s->type))
a185c5aa
LP
936 goto dont_know;
937
23406ce5
LP
938 /* For sessions with an explicitly configured tty, let's check
939 * its atime */
940 if (s->tty) {
941 r = get_tty_atime(s->tty, &atime);
942 if (r >= 0)
943 goto found_atime;
944 }
a185c5aa 945
23406ce5
LP
946 /* For sessions with a leader but no explicitly configured
947 * tty, let's check the controlling tty of the leader */
238794b1 948 if (pid_is_valid(s->leader)) {
23406ce5
LP
949 r = get_process_ctty_atime(s->leader, &atime);
950 if (r >= 0)
951 goto found_atime;
a185c5aa
LP
952 }
953
a185c5aa
LP
954dont_know:
955 if (t)
956 *t = s->idle_hint_timestamp;
957
958 return 0;
23406ce5
LP
959
960found_atime:
961 if (t)
962 dual_timestamp_from_realtime(t, atime);
963
964 n = now(CLOCK_REALTIME);
965
966 if (s->manager->idle_action_usec <= 0)
967 return 0;
968
969 return atime + s->manager->idle_action_usec <= n;
a185c5aa
LP
970}
971
bef422ae
LP
972void session_set_idle_hint(Session *s, bool b) {
973 assert(s);
974
975 if (s->idle_hint == b)
976 return;
977
978 s->idle_hint = b;
979 dual_timestamp_get(&s->idle_hint_timestamp);
9418f147 980
cc377381 981 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
9418f147
LP
982
983 if (s->seat)
cc377381
LP
984 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
985
986 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
987 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
988}
989
42d35e13
VT
990int session_get_locked_hint(Session *s) {
991 assert(s);
992
993 return s->locked_hint;
994}
995
996void session_set_locked_hint(Session *s, bool b) {
997 assert(s);
998
999 if (s->locked_hint == b)
1000 return;
1001
1002 s->locked_hint = b;
1003
1004 session_send_changed(s, "LockedHint", NULL);
1005}
1006
cc377381
LP
1007static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
1008 Session *s = userdata;
1009
1010 assert(s);
1011 assert(s->fifo_fd == fd);
1012
1013 /* EOF on the FIFO means the session died abnormally. */
1014
1015 session_remove_fifo(s);
9bb69af4 1016 session_stop(s, false);
cc377381
LP
1017
1018 return 1;
bef422ae
LP
1019}
1020
932e3ee7
LP
1021int session_create_fifo(Session *s) {
1022 int r;
1023
31b79c2b
LP
1024 assert(s);
1025
b4f78aea 1026 /* Create FIFO */
932e3ee7 1027 if (!s->fifo_path) {
37c1d5e9 1028 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
e6061ab2
LP
1029 if (r < 0)
1030 return r;
1031
d5ddc930
LP
1032 s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref");
1033 if (!s->fifo_path)
932e3ee7 1034 return -ENOMEM;
31b79c2b 1035
932e3ee7
LP
1036 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1037 return -errno;
1038 }
31b79c2b 1039
932e3ee7 1040 /* Open reading side */
b4f78aea 1041 if (s->fifo_fd < 0) {
db4a47e9 1042 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
b4f78aea
LP
1043 if (s->fifo_fd < 0)
1044 return -errno;
cc377381
LP
1045 }
1046
1047 if (!s->fifo_event_source) {
151b9b96 1048 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
b4f78aea
LP
1049 if (r < 0)
1050 return r;
1051
e11544a8
LP
1052 /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
1053 * sessions). */
1054 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
cc377381
LP
1055 if (r < 0)
1056 return r;
b4f78aea 1057 }
932e3ee7
LP
1058
1059 /* Open writing side */
db4a47e9 1060 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
932e3ee7
LP
1061 if (r < 0)
1062 return -errno;
31b79c2b 1063
932e3ee7
LP
1064 return r;
1065}
1066
5f41d1f1 1067static void session_remove_fifo(Session *s) {
932e3ee7
LP
1068 assert(s);
1069
03e334a1
LP
1070 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1071 s->fifo_fd = safe_close(s->fifo_fd);
932e3ee7
LP
1072
1073 if (s->fifo_path) {
75bbdf47 1074 (void) unlink(s->fifo_path);
a1e58e8e 1075 s->fifo_path = mfree(s->fifo_path);
932e3ee7 1076 }
31b79c2b
LP
1077}
1078
5c093a23 1079bool session_may_gc(Session *s, bool drop_not_started) {
bd26aee1
LP
1080 int r;
1081
20263082
LP
1082 assert(s);
1083
4a4b033f 1084 if (drop_not_started && !s->started)
5c093a23 1085 return true;
932e3ee7 1086
9444b1f2 1087 if (!s->user)
5c093a23 1088 return true;
9444b1f2 1089
932e3ee7 1090 if (s->fifo_fd >= 0) {
5f41d1f1 1091 if (pipe_eof(s->fifo_fd) <= 0)
5c093a23 1092 return false;
20263082
LP
1093 }
1094
bd26aee1
LP
1095 if (s->scope_job) {
1096 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1097
1098 r = manager_job_is_active(s->manager, s->scope_job, &error);
1099 if (r < 0)
1100 log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r));
1101 if (r != 0)
1102 return false;
1103 }
20263082 1104
bd26aee1
LP
1105 if (s->scope) {
1106 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1107
1108 r = manager_unit_is_active(s->manager, s->scope, &error);
1109 if (r < 0)
1110 log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r));
1111 if (r != 0)
1112 return false;
1113 }
20263082 1114
5c093a23 1115 return true;
20263082
LP
1116}
1117
14c3baca
LP
1118void session_add_to_gc_queue(Session *s) {
1119 assert(s);
1120
1121 if (s->in_gc_queue)
1122 return;
1123
71fda00f 1124 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
14c3baca
LP
1125 s->in_gc_queue = true;
1126}
1127
0604381b
LP
1128SessionState session_get_state(Session *s) {
1129 assert(s);
1130
8fe63cd4 1131 /* always check closing first */
5f41d1f1
LP
1132 if (s->stopping || s->timer_event_source)
1133 return SESSION_CLOSING;
1134
8fe63cd4 1135 if (s->scope_job || s->fifo_fd < 0)
405e0255 1136 return SESSION_OPENING;
fb6becb4 1137
0604381b
LP
1138 if (session_is_active(s))
1139 return SESSION_ACTIVE;
1140
1141 return SESSION_ONLINE;
1142}
1143
de07ab16 1144int session_kill(Session *s, KillWho who, int signo) {
de07ab16
LP
1145 assert(s);
1146
fb6becb4 1147 if (!s->scope)
de07ab16
LP
1148 return -ESRCH;
1149
fb6becb4 1150 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
de07ab16
LP
1151}
1152
90a18413 1153static int session_open_vt(Session *s) {
5f41d1f1 1154 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
90a18413 1155
baccf3e4
OB
1156 if (s->vtnr < 1)
1157 return -ENODEV;
90a18413
DH
1158
1159 if (s->vtfd >= 0)
1160 return s->vtfd;
1161
92bd5ff3 1162 sprintf(path, "/dev/tty%u", s->vtnr);
22356953 1163 s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
4a62c710 1164 if (s->vtfd < 0)
709f6e46 1165 return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id);
90a18413
DH
1166
1167 return s->vtfd;
1168}
1169
baccf3e4 1170int session_prepare_vt(Session *s) {
90a18413
DH
1171 int vt, r;
1172 struct vt_mode mode = { 0 };
90a18413 1173
baccf3e4
OB
1174 if (s->vtnr < 1)
1175 return 0;
1176
90a18413
DH
1177 vt = session_open_vt(s);
1178 if (vt < 0)
baccf3e4 1179 return vt;
90a18413 1180
d6176c6c 1181 r = fchown(vt, s->user->uid, -1);
baccf3e4 1182 if (r < 0) {
94c156cd
LP
1183 r = log_error_errno(errno,
1184 "Cannot change owner of /dev/tty%u: %m",
1185 s->vtnr);
d6176c6c 1186 goto error;
baccf3e4 1187 }
d6176c6c 1188
90a18413 1189 r = ioctl(vt, KDSKBMODE, K_OFF);
baccf3e4 1190 if (r < 0) {
94c156cd
LP
1191 r = log_error_errno(errno,
1192 "Cannot set K_OFF on /dev/tty%u: %m",
1193 s->vtnr);
90a18413 1194 goto error;
baccf3e4 1195 }
90a18413
DH
1196
1197 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
baccf3e4 1198 if (r < 0) {
94c156cd
LP
1199 r = log_error_errno(errno,
1200 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1201 s->vtnr);
90a18413 1202 goto error;
baccf3e4 1203 }
90a18413 1204
90a18413
DH
1205 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1206 * So we need a dummy handler here which just acknowledges *all* VT
1207 * switch requests. */
1208 mode.mode = VT_PROCESS;
92683ad2
DH
1209 mode.relsig = SIGRTMIN;
1210 mode.acqsig = SIGRTMIN + 1;
90a18413 1211 r = ioctl(vt, VT_SETMODE, &mode);
baccf3e4 1212 if (r < 0) {
94c156cd
LP
1213 r = log_error_errno(errno,
1214 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1215 s->vtnr);
90a18413 1216 goto error;
baccf3e4 1217 }
90a18413 1218
baccf3e4 1219 return 0;
90a18413
DH
1220
1221error:
90a18413 1222 session_restore_vt(s);
baccf3e4 1223 return r;
90a18413
DH
1224}
1225
1226void session_restore_vt(Session *s) {
16597ac3
LP
1227
1228 static const struct vt_mode mode = {
1229 .mode = VT_AUTO,
1230 };
1231
c83f349c 1232 int vt, old_fd;
90a18413 1233
128df4cf
OT
1234 /* We need to get a fresh handle to the virtual terminal,
1235 * since the old file-descriptor is potentially in a hung-up
1236 * state after the controlling process exited; we do a
1237 * little dance to avoid having the terminal be available
1238 * for reuse before we've cleaned it up.
1239 */
c10d6bdb 1240 old_fd = TAKE_FD(s->vtfd);
128df4cf 1241
90a18413 1242 vt = session_open_vt(s);
128df4cf
OT
1243 safe_close(old_fd);
1244
90a18413
DH
1245 if (vt < 0)
1246 return;
1247
2bf10523 1248 (void) ioctl(vt, KDSETMODE, KD_TEXT);
90a18413 1249
c83f349c 1250 (void) vt_reset_keyboard(vt);
90a18413 1251
2bf10523 1252 (void) ioctl(vt, VT_SETMODE, &mode);
16597ac3 1253 (void) fchown(vt, 0, (gid_t) -1);
d6176c6c 1254
03e334a1 1255 s->vtfd = safe_close(s->vtfd);
90a18413
DH
1256}
1257
2ec3ff66 1258void session_leave_vt(Session *s) {
ce540a24
DH
1259 int r;
1260
2ec3ff66
DH
1261 assert(s);
1262
1263 /* This is called whenever we get a VT-switch signal from the kernel.
1264 * We acknowledge all of them unconditionally. Note that session are
1265 * free to overwrite those handlers and we only register them for
1266 * sessions with controllers. Legacy sessions are not affected.
1267 * However, if we switch from a non-legacy to a legacy session, we must
1268 * make sure to pause all device before acknowledging the switch. We
1269 * process the real switch only after we are notified via sysfs, so the
1270 * legacy session might have already started using the devices. If we
1271 * don't pause the devices before the switch, we might confuse the
1272 * session we switch to. */
1273
1274 if (s->vtfd < 0)
1275 return;
1276
1277 session_device_pause_all(s);
ce540a24
DH
1278 r = ioctl(s->vtfd, VT_RELDISP, 1);
1279 if (r < 0)
56f64d95 1280 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
2ec3ff66
DH
1281}
1282
cc377381 1283bool session_is_controller(Session *s, const char *sender) {
ae5e06bd
DH
1284 assert(s);
1285
1286 return streq_ptr(s->controller, sender);
1287}
1288
b12e5615
DH
1289static void session_release_controller(Session *s, bool notify) {
1290 _cleanup_free_ char *name = NULL;
6d33772f
DH
1291 SessionDevice *sd;
1292
b12e5615
DH
1293 if (!s->controller)
1294 return;
6d33772f 1295
b12e5615 1296 name = s->controller;
90a18413 1297
b12e5615
DH
1298 /* By resetting the controller before releasing the devices, we won't
1299 * send notification signals. This avoids sending useless notifications
1300 * if the controller is released on disconnects. */
1301 if (!notify)
1302 s->controller = NULL;
6d33772f 1303
b12e5615
DH
1304 while ((sd = hashmap_first(s->devices)))
1305 session_device_free(sd);
1306
1307 s->controller = NULL;
3cde9e8f
DM
1308 s->track = sd_bus_track_unref(s->track);
1309}
1310
1311static int on_bus_track(sd_bus_track *track, void *userdata) {
1312 Session *s = userdata;
1313
1314 assert(track);
1315 assert(s);
1316
1317 session_drop_controller(s);
1318
1319 return 0;
6d33772f
DH
1320}
1321
dc6284e9 1322int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
b12e5615 1323 _cleanup_free_ char *name = NULL;
ae5e06bd
DH
1324 int r;
1325
1326 assert(s);
1327 assert(sender);
1328
1329 if (session_is_controller(s, sender))
1330 return 0;
1331 if (s->controller && !force)
1332 return -EBUSY;
1333
b12e5615
DH
1334 name = strdup(sender);
1335 if (!name)
ae5e06bd
DH
1336 return -ENOMEM;
1337
3cde9e8f
DM
1338 s->track = sd_bus_track_unref(s->track);
1339 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1340 if (r < 0)
1341 return r;
1342
1343 r = sd_bus_track_add_name(s->track, name);
1344 if (r < 0)
ae5e06bd 1345 return r;
ae5e06bd 1346
90a18413
DH
1347 /* When setting a session controller, we forcibly mute the VT and set
1348 * it into graphics-mode. Applications can override that by changing
1349 * VT state after calling TakeControl(). However, this serves as a good
1350 * default and well-behaving controllers can now ignore VTs entirely.
1351 * Note that we reset the VT on ReleaseControl() and if the controller
1352 * exits.
1353 * If logind crashes/restarts, we restore the controller during restart
dc6284e9
FB
1354 * (without preparing the VT since the controller has probably overridden
1355 * VT state by now) or reset the VT in case it crashed/exited, too. */
1356 if (prepare) {
1357 r = session_prepare_vt(s);
1358 if (r < 0) {
1359 s->track = sd_bus_track_unref(s->track);
1360 return r;
1361 }
13f493dc 1362 }
baccf3e4 1363
b12e5615 1364 session_release_controller(s, true);
ae2a15bc 1365 s->controller = TAKE_PTR(name);
b12e5615 1366 session_save(s);
90a18413 1367
ae5e06bd
DH
1368 return 0;
1369}
1370
1371void session_drop_controller(Session *s) {
1372 assert(s);
1373
1374 if (!s->controller)
1375 return;
1376
3cde9e8f 1377 s->track = sd_bus_track_unref(s->track);
b12e5615
DH
1378 session_release_controller(s, false);
1379 session_save(s);
1380 session_restore_vt(s);
ae5e06bd
DH
1381}
1382
fb6becb4
LP
1383static const char* const session_state_table[_SESSION_STATE_MAX] = {
1384 [SESSION_OPENING] = "opening",
0604381b
LP
1385 [SESSION_ONLINE] = "online",
1386 [SESSION_ACTIVE] = "active",
1387 [SESSION_CLOSING] = "closing"
1388};
1389
1390DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1391
20263082 1392static const char* const session_type_table[_SESSION_TYPE_MAX] = {
2c5859af 1393 [SESSION_UNSPECIFIED] = "unspecified",
3f49d45a 1394 [SESSION_TTY] = "tty",
98a28fef 1395 [SESSION_X11] = "x11",
d9eb81f9 1396 [SESSION_WAYLAND] = "wayland",
9541666b 1397 [SESSION_MIR] = "mir",
e9e74f28 1398 [SESSION_WEB] = "web",
20263082
LP
1399};
1400
1401DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
de07ab16 1402
55efac6c
LP
1403static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1404 [SESSION_USER] = "user",
1405 [SESSION_GREETER] = "greeter",
e2acb67b
LP
1406 [SESSION_LOCK_SCREEN] = "lock-screen",
1407 [SESSION_BACKGROUND] = "background"
55efac6c
LP
1408};
1409
1410DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1411
de07ab16
LP
1412static const char* const kill_who_table[_KILL_WHO_MAX] = {
1413 [KILL_LEADER] = "leader",
1414 [KILL_ALL] = "all"
1415};
1416
1417DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
3d0ef5c7
LP
1418
1419static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
1420 [TTY_FROM_PAM] = "from-pam",
1421 [TTY_FROM_UTMP] = "from-utmp",
1422 [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
1423};
1424
1425DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);