chiark / gitweb /
logind: always kill session when termination is requested
[elogind.git] / src / login / logind-session.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <linux/vt.h>
25 #include <linux/kd.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <unistd.h>
30
31 #include "sd-id128.h"
32 #include "sd-messages.h"
33 #include "strv.h"
34 #include "util.h"
35 #include "mkdir.h"
36 #include "path-util.h"
37 #include "fileio.h"
38 #include "audit.h"
39 #include "bus-util.h"
40 #include "bus-error.h"
41 #include "logind-session.h"
42
43 #define RELEASE_USEC (20*USEC_PER_SEC)
44
45 static void session_remove_fifo(Session *s);
46
47 static unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
48         uint64_t u = *(const dev_t*)p;
49
50         return uint64_hash_func(&u, hash_key);
51 }
52
53 static int devt_compare_func(const void *_a, const void *_b) {
54         dev_t a, b;
55
56         a = *(const dev_t*) _a;
57         b = *(const dev_t*) _b;
58
59         return a < b ? -1 : (a > b ? 1 : 0);
60 }
61
62 Session* session_new(Manager *m, const char *id) {
63         Session *s;
64
65         assert(m);
66         assert(id);
67         assert(session_id_valid(id));
68
69         s = new0(Session, 1);
70         if (!s)
71                 return NULL;
72
73         s->state_file = strappend("/run/systemd/sessions/", id);
74         if (!s->state_file) {
75                 free(s);
76                 return NULL;
77         }
78
79         s->devices = hashmap_new(devt_hash_func, devt_compare_func);
80         if (!s->devices) {
81                 free(s->state_file);
82                 free(s);
83                 return NULL;
84         }
85
86         s->id = basename(s->state_file);
87
88         if (hashmap_put(m->sessions, s->id, s) < 0) {
89                 hashmap_free(s->devices);
90                 free(s->state_file);
91                 free(s);
92                 return NULL;
93         }
94
95         s->manager = m;
96         s->fifo_fd = -1;
97         s->vtfd = -1;
98
99         return s;
100 }
101
102 void session_free(Session *s) {
103         SessionDevice *sd;
104
105         assert(s);
106
107         if (s->in_gc_queue)
108                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
109
110         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
111
112         session_remove_fifo(s);
113
114         session_drop_controller(s);
115
116         while ((sd = hashmap_first(s->devices)))
117                 session_device_free(sd);
118
119         hashmap_free(s->devices);
120
121         if (s->user) {
122                 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
123
124                 if (s->user->display == s)
125                         s->user->display = NULL;
126         }
127
128         if (s->seat) {
129                 if (s->seat->active == s)
130                         s->seat->active = NULL;
131                 if (s->seat->pending_switch == s)
132                         s->seat->pending_switch = NULL;
133
134                 seat_evict_position(s->seat, s);
135                 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
136         }
137
138         if (s->scope) {
139                 hashmap_remove(s->manager->session_units, s->scope);
140                 free(s->scope);
141         }
142
143         free(s->scope_job);
144
145         sd_bus_message_unref(s->create_message);
146
147         free(s->tty);
148         free(s->display);
149         free(s->remote_host);
150         free(s->remote_user);
151         free(s->service);
152         free(s->desktop);
153
154         hashmap_remove(s->manager->sessions, s->id);
155
156         s->vt_source = sd_event_source_unref(s->vt_source);
157
158         free(s->state_file);
159         free(s);
160 }
161
162 void session_set_user(Session *s, User *u) {
163         assert(s);
164         assert(!s->user);
165
166         s->user = u;
167         LIST_PREPEND(sessions_by_user, u->sessions, s);
168 }
169
170 int session_save(Session *s) {
171         _cleanup_free_ char *temp_path = NULL;
172         _cleanup_fclose_ FILE *f = NULL;
173         int r = 0;
174
175         assert(s);
176
177         if (!s->user)
178                 return -ESTALE;
179
180         if (!s->started)
181                 return 0;
182
183         r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
184         if (r < 0)
185                 goto finish;
186
187         r = fopen_temporary(s->state_file, &f, &temp_path);
188         if (r < 0)
189                 goto finish;
190
191         assert(s->user);
192
193         fchmod(fileno(f), 0644);
194
195         fprintf(f,
196                 "# This is private data. Do not parse.\n"
197                 "UID="UID_FMT"\n"
198                 "USER=%s\n"
199                 "ACTIVE=%i\n"
200                 "STATE=%s\n"
201                 "REMOTE=%i\n",
202                 s->user->uid,
203                 s->user->name,
204                 session_is_active(s),
205                 session_state_to_string(session_get_state(s)),
206                 s->remote);
207
208         if (s->type >= 0)
209                 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
210
211         if (s->class >= 0)
212                 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
213
214         if (s->scope)
215                 fprintf(f, "SCOPE=%s\n", s->scope);
216
217         if (s->scope_job)
218                 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
219
220         if (s->fifo_path)
221                 fprintf(f, "FIFO=%s\n", s->fifo_path);
222
223         if (s->seat)
224                 fprintf(f, "SEAT=%s\n", s->seat->id);
225
226         if (s->tty)
227                 fprintf(f, "TTY=%s\n", s->tty);
228
229         if (s->display)
230                 fprintf(f, "DISPLAY=%s\n", s->display);
231
232         if (s->remote_host)
233                 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
234
235         if (s->remote_user)
236                 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
237
238         if (s->service)
239                 fprintf(f, "SERVICE=%s\n", s->service);
240
241         if (s->desktop)
242                 fprintf(f, "DESKTOP=%s\n", s->desktop);
243
244         if (s->seat && seat_has_vts(s->seat))
245                 fprintf(f, "VTNR=%u\n", s->vtnr);
246
247         if (!s->vtnr)
248                 fprintf(f, "POS=%u\n", s->pos);
249
250         if (s->leader > 0)
251                 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
252
253         if (s->audit_id > 0)
254                 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
255
256         if (dual_timestamp_is_set(&s->timestamp))
257                 fprintf(f,
258                         "REALTIME="USEC_FMT"\n"
259                         "MONOTONIC="USEC_FMT"\n",
260                         s->timestamp.realtime,
261                         s->timestamp.monotonic);
262
263         if (s->controller)
264                 fprintf(f, "CONTROLLER=%s\n", s->controller);
265
266         fflush(f);
267
268         if (ferror(f) || rename(temp_path, s->state_file) < 0) {
269                 r = -errno;
270                 unlink(s->state_file);
271                 unlink(temp_path);
272         }
273
274 finish:
275         if (r < 0)
276                 log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
277
278         return r;
279 }
280
281 int session_load(Session *s) {
282         _cleanup_free_ char *remote = NULL,
283                 *seat = NULL,
284                 *vtnr = NULL,
285                 *pos = NULL,
286                 *leader = NULL,
287                 *type = NULL,
288                 *class = NULL,
289                 *uid = NULL,
290                 *realtime = NULL,
291                 *monotonic = NULL,
292                 *controller = NULL;
293
294         int k, r;
295
296         assert(s);
297
298         r = parse_env_file(s->state_file, NEWLINE,
299                            "REMOTE",         &remote,
300                            "SCOPE",          &s->scope,
301                            "SCOPE_JOB",      &s->scope_job,
302                            "FIFO",           &s->fifo_path,
303                            "SEAT",           &seat,
304                            "TTY",            &s->tty,
305                            "DISPLAY",        &s->display,
306                            "REMOTE_HOST",    &s->remote_host,
307                            "REMOTE_USER",    &s->remote_user,
308                            "SERVICE",        &s->service,
309                            "DESKTOP",        &s->desktop,
310                            "VTNR",           &vtnr,
311                            "POS",            &pos,
312                            "LEADER",         &leader,
313                            "TYPE",           &type,
314                            "CLASS",          &class,
315                            "UID",            &uid,
316                            "REALTIME",       &realtime,
317                            "MONOTONIC",      &monotonic,
318                            "CONTROLLER",     &controller,
319                            NULL);
320
321         if (r < 0) {
322                 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
323                 return r;
324         }
325
326         if (!s->user) {
327                 uid_t u;
328                 User *user;
329
330                 if (!uid) {
331                         log_error("UID not specified for session %s", s->id);
332                         return -ENOENT;
333                 }
334
335                 r = parse_uid(uid, &u);
336                 if (r < 0)  {
337                         log_error("Failed to parse UID value %s for session %s.", uid, s->id);
338                         return r;
339                 }
340
341                 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
342                 if (!user) {
343                         log_error("User of session %s not known.", s->id);
344                         return -ENOENT;
345                 }
346
347                 session_set_user(s, user);
348         }
349
350         if (remote) {
351                 k = parse_boolean(remote);
352                 if (k >= 0)
353                         s->remote = k;
354         }
355
356         if (vtnr)
357                 safe_atou(vtnr, &s->vtnr);
358
359         if (seat && !s->seat) {
360                 Seat *o;
361
362                 o = hashmap_get(s->manager->seats, seat);
363                 if (o)
364                         r = seat_attach_session(o, s);
365                 if (!o || r < 0)
366                         log_error("Cannot attach session %s to seat %s", s->id, seat);
367         }
368
369         if (!s->seat || !seat_has_vts(s->seat))
370                 s->vtnr = 0;
371
372         if (pos && s->seat) {
373                 unsigned int npos;
374
375                 safe_atou(pos, &npos);
376                 seat_claim_position(s->seat, s, npos);
377         }
378
379         if (leader) {
380                 k = parse_pid(leader, &s->leader);
381                 if (k >= 0)
382                         audit_session_from_pid(s->leader, &s->audit_id);
383         }
384
385         if (type) {
386                 SessionType t;
387
388                 t = session_type_from_string(type);
389                 if (t >= 0)
390                         s->type = t;
391         }
392
393         if (class) {
394                 SessionClass c;
395
396                 c = session_class_from_string(class);
397                 if (c >= 0)
398                         s->class = c;
399         }
400
401         if (s->fifo_path) {
402                 int fd;
403
404                 /* If we open an unopened pipe for reading we will not
405                    get an EOF. to trigger an EOF we hence open it for
406                    reading, but close it right-away which then will
407                    trigger the EOF. */
408
409                 fd = session_create_fifo(s);
410                 if (fd >= 0)
411                         close_nointr_nofail(fd);
412         }
413
414         if (realtime) {
415                 unsigned long long l;
416                 if (sscanf(realtime, "%llu", &l) > 0)
417                         s->timestamp.realtime = l;
418         }
419
420         if (monotonic) {
421                 unsigned long long l;
422                 if (sscanf(monotonic, "%llu", &l) > 0)
423                         s->timestamp.monotonic = l;
424         }
425
426         if (controller) {
427                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
428                         session_set_controller(s, controller, false);
429                 else
430                         session_restore_vt(s);
431         }
432
433         return r;
434 }
435
436 int session_activate(Session *s) {
437         unsigned int num_pending;
438
439         assert(s);
440         assert(s->user);
441
442         if (!s->seat)
443                 return -ENOTSUP;
444
445         if (s->seat->active == s)
446                 return 0;
447
448         /* on seats with VTs, we let VTs manage session-switching */
449         if (seat_has_vts(s->seat)) {
450                 if (!s->vtnr)
451                         return -ENOTSUP;
452
453                 return chvt(s->vtnr);
454         }
455
456         /* On seats without VTs, we implement session-switching in logind. We
457          * try to pause all session-devices and wait until the session
458          * controller acknowledged them. Once all devices are asleep, we simply
459          * switch the active session and be done.
460          * We save the session we want to switch to in seat->pending_switch and
461          * seat_complete_switch() will perform the final switch. */
462
463         s->seat->pending_switch = s;
464
465         /* if no devices are running, immediately perform the session switch */
466         num_pending = session_device_try_pause_all(s);
467         if (!num_pending)
468                 seat_complete_switch(s->seat);
469
470         return 0;
471 }
472
473 static int session_start_scope(Session *s) {
474         int r;
475
476         assert(s);
477         assert(s->user);
478         assert(s->user->slice);
479
480         if (!s->scope) {
481                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
482                 _cleanup_free_ char *description = NULL;
483                 char *scope, *job;
484
485                 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
486                 if (!description)
487                         return log_oom();
488
489                 scope = strjoin("session-", s->id, ".scope", NULL);
490                 if (!scope)
491                         return log_oom();
492
493                 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-session.service", &error, &job);
494                 if (r < 0) {
495                         log_error("Failed to start session scope %s: %s %s",
496                                   scope, bus_error_message(&error, r), error.name);
497                         free(scope);
498                         return r;
499                 } else {
500                         s->scope = scope;
501
502                         free(s->scope_job);
503                         s->scope_job = job;
504                 }
505         }
506
507         if (s->scope)
508                 hashmap_put(s->manager->session_units, s->scope, s);
509
510         return 0;
511 }
512
513 int session_start(Session *s) {
514         int r;
515
516         assert(s);
517
518         if (!s->user)
519                 return -ESTALE;
520
521         if (s->started)
522                 return 0;
523
524         r = user_start(s->user);
525         if (r < 0)
526                 return r;
527
528         /* Create cgroup */
529         r = session_start_scope(s);
530         if (r < 0)
531                 return r;
532
533         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
534                    MESSAGE_ID(SD_MESSAGE_SESSION_START),
535                    "SESSION_ID=%s", s->id,
536                    "USER_ID=%s", s->user->name,
537                    "LEADER=%lu", (unsigned long) s->leader,
538                    "MESSAGE=New session %s of user %s.", s->id, s->user->name,
539                    NULL);
540
541         if (!dual_timestamp_is_set(&s->timestamp))
542                 dual_timestamp_get(&s->timestamp);
543
544         if (s->seat)
545                 seat_read_active_vt(s->seat);
546
547         s->started = true;
548
549         /* Save data */
550         session_save(s);
551         user_save(s->user);
552         if (s->seat)
553                 seat_save(s->seat);
554
555         /* Send signals */
556         session_send_signal(s, true);
557         user_send_changed(s->user, "Sessions", NULL);
558         if (s->seat) {
559                 if (s->seat->active == s)
560                         seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
561                 else
562                         seat_send_changed(s->seat, "Sessions", NULL);
563         }
564
565         return 0;
566 }
567
568 static int session_stop_scope(Session *s, bool force) {
569         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
570         char *job;
571         int r;
572
573         assert(s);
574
575         if (!s->scope)
576                 return 0;
577
578         if (force || manager_shall_kill(s->manager, s->user->name)) {
579                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
580                 if (r < 0) {
581                         log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
582                         return r;
583                 }
584
585                 free(s->scope_job);
586                 s->scope_job = job;
587         } else {
588                 r = manager_abandon_scope(s->manager, s->scope, &error);
589                 if (r < 0) {
590                         log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
591                         return r;
592                 }
593         }
594
595         return 0;
596 }
597
598 int session_stop(Session *s, bool force) {
599         int r;
600
601         assert(s);
602
603         if (!s->user)
604                 return -ESTALE;
605
606         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
607
608         /* We are going down, don't care about FIFOs anymore */
609         session_remove_fifo(s);
610
611         /* Kill cgroup */
612         r = session_stop_scope(s, force);
613
614         s->stopping = true;
615
616         session_save(s);
617         user_save(s->user);
618
619         return r;
620 }
621
622 int session_finalize(Session *s) {
623         int r = 0;
624         SessionDevice *sd;
625
626         assert(s);
627
628         if (!s->user)
629                 return -ESTALE;
630
631         if (s->started)
632                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
633                            MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
634                            "SESSION_ID=%s", s->id,
635                            "USER_ID=%s", s->user->name,
636                            "LEADER=%lu", (unsigned long) s->leader,
637                            "MESSAGE=Removed session %s.", s->id,
638                            NULL);
639
640         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
641
642         /* Kill session devices */
643         while ((sd = hashmap_first(s->devices)))
644                 session_device_free(sd);
645
646         unlink(s->state_file);
647         session_add_to_gc_queue(s);
648         user_add_to_gc_queue(s->user);
649
650         if (s->started) {
651                 session_send_signal(s, false);
652                 s->started = false;
653         }
654
655         if (s->seat) {
656                 if (s->seat->active == s)
657                         seat_set_active(s->seat, NULL);
658
659                 seat_save(s->seat);
660                 seat_send_changed(s->seat, "Sessions", NULL);
661         }
662
663         user_save(s->user);
664         user_send_changed(s->user, "Sessions", NULL);
665
666         return r;
667 }
668
669 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
670         Session *s = userdata;
671
672         assert(es);
673         assert(s);
674
675         session_stop(s, false);
676         return 0;
677 }
678
679 void session_release(Session *s) {
680         assert(s);
681
682         if (!s->started || s->stopping)
683                 return;
684
685         if (!s->timer_event_source)
686                 sd_event_add_monotonic(s->manager->event, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s, &s->timer_event_source);
687 }
688
689 bool session_is_active(Session *s) {
690         assert(s);
691
692         if (!s->seat)
693                 return true;
694
695         return s->seat->active == s;
696 }
697
698 static int get_tty_atime(const char *tty, usec_t *atime) {
699         _cleanup_free_ char *p = NULL;
700         struct stat st;
701
702         assert(tty);
703         assert(atime);
704
705         if (!path_is_absolute(tty)) {
706                 p = strappend("/dev/", tty);
707                 if (!p)
708                         return -ENOMEM;
709
710                 tty = p;
711         } else if (!path_startswith(tty, "/dev/"))
712                 return -ENOENT;
713
714         if (lstat(tty, &st) < 0)
715                 return -errno;
716
717         *atime = timespec_load(&st.st_atim);
718         return 0;
719 }
720
721 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
722         _cleanup_free_ char *p = NULL;
723         int r;
724
725         assert(pid > 0);
726         assert(atime);
727
728         r = get_ctty(pid, NULL, &p);
729         if (r < 0)
730                 return r;
731
732         return get_tty_atime(p, atime);
733 }
734
735 int session_get_idle_hint(Session *s, dual_timestamp *t) {
736         usec_t atime = 0, n;
737         int r;
738
739         assert(s);
740
741         /* Explicit idle hint is set */
742         if (s->idle_hint) {
743                 if (t)
744                         *t = s->idle_hint_timestamp;
745
746                 return s->idle_hint;
747         }
748
749         /* Graphical sessions should really implement a real
750          * idle hint logic */
751         if (s->display)
752                 goto dont_know;
753
754         /* For sessions with an explicitly configured tty, let's check
755          * its atime */
756         if (s->tty) {
757                 r = get_tty_atime(s->tty, &atime);
758                 if (r >= 0)
759                         goto found_atime;
760         }
761
762         /* For sessions with a leader but no explicitly configured
763          * tty, let's check the controlling tty of the leader */
764         if (s->leader > 0) {
765                 r = get_process_ctty_atime(s->leader, &atime);
766                 if (r >= 0)
767                         goto found_atime;
768         }
769
770 dont_know:
771         if (t)
772                 *t = s->idle_hint_timestamp;
773
774         return 0;
775
776 found_atime:
777         if (t)
778                 dual_timestamp_from_realtime(t, atime);
779
780         n = now(CLOCK_REALTIME);
781
782         if (s->manager->idle_action_usec <= 0)
783                 return 0;
784
785         return atime + s->manager->idle_action_usec <= n;
786 }
787
788 void session_set_idle_hint(Session *s, bool b) {
789         assert(s);
790
791         if (s->idle_hint == b)
792                 return;
793
794         s->idle_hint = b;
795         dual_timestamp_get(&s->idle_hint_timestamp);
796
797         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
798
799         if (s->seat)
800                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
801
802         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
803         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
804 }
805
806 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
807         Session *s = userdata;
808
809         assert(s);
810         assert(s->fifo_fd == fd);
811
812         /* EOF on the FIFO means the session died abnormally. */
813
814         session_remove_fifo(s);
815         session_stop(s, false);
816
817         return 1;
818 }
819
820 int session_create_fifo(Session *s) {
821         int r;
822
823         assert(s);
824
825         /* Create FIFO */
826         if (!s->fifo_path) {
827                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
828                 if (r < 0)
829                         return r;
830
831                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
832                         return -ENOMEM;
833
834                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
835                         return -errno;
836         }
837
838         /* Open reading side */
839         if (s->fifo_fd < 0) {
840                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
841                 if (s->fifo_fd < 0)
842                         return -errno;
843
844         }
845
846         if (!s->fifo_event_source) {
847                 r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
848                 if (r < 0)
849                         return r;
850
851                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
852                 if (r < 0)
853                         return r;
854         }
855
856         /* Open writing side */
857         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
858         if (r < 0)
859                 return -errno;
860
861         return r;
862 }
863
864 static void session_remove_fifo(Session *s) {
865         assert(s);
866
867         if (s->fifo_event_source)
868                 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
869
870         if (s->fifo_fd >= 0) {
871                 close_nointr_nofail(s->fifo_fd);
872                 s->fifo_fd = -1;
873         }
874
875         if (s->fifo_path) {
876                 unlink(s->fifo_path);
877                 free(s->fifo_path);
878                 s->fifo_path = NULL;
879         }
880 }
881
882 bool session_check_gc(Session *s, bool drop_not_started) {
883         assert(s);
884
885         if (drop_not_started && !s->started)
886                 return false;
887
888         if (!s->user)
889                 return false;
890
891         if (s->fifo_fd >= 0) {
892                 if (pipe_eof(s->fifo_fd) <= 0)
893                         return true;
894         }
895
896         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
897                 return true;
898
899         if (s->scope && manager_unit_is_active(s->manager, s->scope))
900                 return true;
901
902         return false;
903 }
904
905 void session_add_to_gc_queue(Session *s) {
906         assert(s);
907
908         if (s->in_gc_queue)
909                 return;
910
911         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
912         s->in_gc_queue = true;
913 }
914
915 SessionState session_get_state(Session *s) {
916         assert(s);
917
918         if (s->stopping || s->timer_event_source)
919                 return SESSION_CLOSING;
920
921         if (s->scope_job)
922                 return SESSION_OPENING;
923
924         if (session_is_active(s))
925                 return SESSION_ACTIVE;
926
927         return SESSION_ONLINE;
928 }
929
930 int session_kill(Session *s, KillWho who, int signo) {
931         assert(s);
932
933         if (!s->scope)
934                 return -ESRCH;
935
936         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
937 }
938
939 static int session_open_vt(Session *s) {
940         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
941
942         if (!s->vtnr)
943                 return -1;
944
945         if (s->vtfd >= 0)
946                 return s->vtfd;
947
948         sprintf(path, "/dev/tty%u", s->vtnr);
949         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
950         if (s->vtfd < 0) {
951                 log_error("cannot open VT %s of session %s: %m", path, s->id);
952                 return -1;
953         }
954
955         return s->vtfd;
956 }
957
958 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
959         Session *s = data;
960
961         if (s->vtfd >= 0)
962                 ioctl(s->vtfd, VT_RELDISP, 1);
963
964         return 0;
965 }
966
967 void session_mute_vt(Session *s) {
968         int vt, r;
969         struct vt_mode mode = { 0 };
970         sigset_t mask;
971
972         vt = session_open_vt(s);
973         if (vt < 0)
974                 return;
975
976         r = ioctl(vt, KDSKBMODE, K_OFF);
977         if (r < 0)
978                 goto error;
979
980         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
981         if (r < 0)
982                 goto error;
983
984         sigemptyset(&mask);
985         sigaddset(&mask, SIGUSR1);
986         sigprocmask(SIG_BLOCK, &mask, NULL);
987
988         r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
989         if (r < 0)
990                 goto error;
991
992         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
993          * So we need a dummy handler here which just acknowledges *all* VT
994          * switch requests. */
995         mode.mode = VT_PROCESS;
996         mode.relsig = SIGUSR1;
997         mode.acqsig = SIGUSR1;
998         r = ioctl(vt, VT_SETMODE, &mode);
999         if (r < 0)
1000                 goto error;
1001
1002         return;
1003
1004 error:
1005         log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1006         session_restore_vt(s);
1007 }
1008
1009 void session_restore_vt(Session *s) {
1010         _cleanup_free_ char *utf8;
1011         int vt, kb = K_XLATE;
1012         struct vt_mode mode = { 0 };
1013
1014         vt = session_open_vt(s);
1015         if (vt < 0)
1016                 return;
1017
1018         s->vt_source = sd_event_source_unref(s->vt_source);
1019
1020         ioctl(vt, KDSETMODE, KD_TEXT);
1021
1022         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1023                 kb = K_UNICODE;
1024         ioctl(vt, KDSKBMODE, kb);
1025
1026         mode.mode = VT_AUTO;
1027         ioctl(vt, VT_SETMODE, &mode);
1028
1029         close_nointr_nofail(vt);
1030         s->vtfd = -1;
1031 }
1032
1033 bool session_is_controller(Session *s, const char *sender) {
1034         assert(s);
1035
1036         return streq_ptr(s->controller, sender);
1037 }
1038
1039 static void session_swap_controller(Session *s, char *name) {
1040         SessionDevice *sd;
1041
1042         if (s->controller) {
1043                 manager_drop_busname(s->manager, s->controller);
1044                 free(s->controller);
1045                 s->controller = NULL;
1046
1047                 /* Drop all devices as they're now unused. Do that after the
1048                  * controller is released to avoid sending out useles
1049                  * dbus signals. */
1050                 while ((sd = hashmap_first(s->devices)))
1051                         session_device_free(sd);
1052
1053                 if (!name)
1054                         session_restore_vt(s);
1055         }
1056
1057         s->controller = name;
1058         session_save(s);
1059 }
1060
1061 int session_set_controller(Session *s, const char *sender, bool force) {
1062         char *t;
1063         int r;
1064
1065         assert(s);
1066         assert(sender);
1067
1068         if (session_is_controller(s, sender))
1069                 return 0;
1070         if (s->controller && !force)
1071                 return -EBUSY;
1072
1073         t = strdup(sender);
1074         if (!t)
1075                 return -ENOMEM;
1076
1077         r = manager_watch_busname(s->manager, sender);
1078         if (r) {
1079                 free(t);
1080                 return r;
1081         }
1082
1083         session_swap_controller(s, t);
1084
1085         /* When setting a session controller, we forcibly mute the VT and set
1086          * it into graphics-mode. Applications can override that by changing
1087          * VT state after calling TakeControl(). However, this serves as a good
1088          * default and well-behaving controllers can now ignore VTs entirely.
1089          * Note that we reset the VT on ReleaseControl() and if the controller
1090          * exits.
1091          * If logind crashes/restarts, we restore the controller during restart
1092          * or reset the VT in case it crashed/exited, too. */
1093         session_mute_vt(s);
1094
1095         return 0;
1096 }
1097
1098 void session_drop_controller(Session *s) {
1099         assert(s);
1100
1101         if (!s->controller)
1102                 return;
1103
1104         session_swap_controller(s, NULL);
1105 }
1106
1107 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1108         [SESSION_OPENING] = "opening",
1109         [SESSION_ONLINE] = "online",
1110         [SESSION_ACTIVE] = "active",
1111         [SESSION_CLOSING] = "closing"
1112 };
1113
1114 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1115
1116 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1117         [SESSION_TTY] = "tty",
1118         [SESSION_X11] = "x11",
1119         [SESSION_WAYLAND] = "wayland",
1120         [SESSION_UNSPECIFIED] = "unspecified",
1121 };
1122
1123 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1124
1125 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1126         [SESSION_USER] = "user",
1127         [SESSION_GREETER] = "greeter",
1128         [SESSION_LOCK_SCREEN] = "lock-screen",
1129         [SESSION_BACKGROUND] = "background"
1130 };
1131
1132 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1133
1134 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1135         [KILL_LEADER] = "leader",
1136         [KILL_ALL] = "all"
1137 };
1138
1139 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);