chiark / gitweb /
Document CONFIG_NET_NS as a required kernel option
[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                 safe_close(fd);
411         }
412
413         if (realtime) {
414                 unsigned long long l;
415                 if (sscanf(realtime, "%llu", &l) > 0)
416                         s->timestamp.realtime = l;
417         }
418
419         if (monotonic) {
420                 unsigned long long l;
421                 if (sscanf(monotonic, "%llu", &l) > 0)
422                         s->timestamp.monotonic = l;
423         }
424
425         if (controller) {
426                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
427                         session_set_controller(s, controller, false);
428                 else
429                         session_restore_vt(s);
430         }
431
432         return r;
433 }
434
435 int session_activate(Session *s) {
436         unsigned int num_pending;
437
438         assert(s);
439         assert(s->user);
440
441         if (!s->seat)
442                 return -ENOTSUP;
443
444         if (s->seat->active == s)
445                 return 0;
446
447         /* on seats with VTs, we let VTs manage session-switching */
448         if (seat_has_vts(s->seat)) {
449                 if (!s->vtnr)
450                         return -ENOTSUP;
451
452                 return chvt(s->vtnr);
453         }
454
455         /* On seats without VTs, we implement session-switching in logind. We
456          * try to pause all session-devices and wait until the session
457          * controller acknowledged them. Once all devices are asleep, we simply
458          * switch the active session and be done.
459          * We save the session we want to switch to in seat->pending_switch and
460          * seat_complete_switch() will perform the final switch. */
461
462         s->seat->pending_switch = s;
463
464         /* if no devices are running, immediately perform the session switch */
465         num_pending = session_device_try_pause_all(s);
466         if (!num_pending)
467                 seat_complete_switch(s->seat);
468
469         return 0;
470 }
471
472 static int session_start_scope(Session *s) {
473         int r;
474
475         assert(s);
476         assert(s->user);
477         assert(s->user->slice);
478
479         if (!s->scope) {
480                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
481                 _cleanup_free_ char *description = NULL;
482                 char *scope, *job = NULL;
483
484                 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
485                 if (!description)
486                         return log_oom();
487
488                 scope = strjoin("session-", s->id, ".scope", NULL);
489                 if (!scope)
490                         return log_oom();
491
492                 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
493                 if (r < 0) {
494                         log_error("Failed to start session scope %s: %s %s",
495                                   scope, bus_error_message(&error, r), error.name);
496                         free(scope);
497                         return r;
498                 } else {
499                         s->scope = scope;
500
501                         free(s->scope_job);
502                         s->scope_job = job;
503                 }
504         }
505
506         if (s->scope)
507                 hashmap_put(s->manager->session_units, s->scope, s);
508
509         return 0;
510 }
511
512 int session_start(Session *s) {
513         int r;
514
515         assert(s);
516
517         if (!s->user)
518                 return -ESTALE;
519
520         if (s->started)
521                 return 0;
522
523         r = user_start(s->user);
524         if (r < 0)
525                 return r;
526
527         /* Create cgroup */
528         r = session_start_scope(s);
529         if (r < 0)
530                 return r;
531
532         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
533                    MESSAGE_ID(SD_MESSAGE_SESSION_START),
534                    "SESSION_ID=%s", s->id,
535                    "USER_ID=%s", s->user->name,
536                    "LEADER=%lu", (unsigned long) s->leader,
537                    "MESSAGE=New session %s of user %s.", s->id, s->user->name,
538                    NULL);
539
540         if (!dual_timestamp_is_set(&s->timestamp))
541                 dual_timestamp_get(&s->timestamp);
542
543         if (s->seat)
544                 seat_read_active_vt(s->seat);
545
546         s->started = true;
547
548         /* Save data */
549         session_save(s);
550         user_save(s->user);
551         if (s->seat)
552                 seat_save(s->seat);
553
554         /* Send signals */
555         session_send_signal(s, true);
556         user_send_changed(s->user, "Sessions", NULL);
557         if (s->seat) {
558                 if (s->seat->active == s)
559                         seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
560                 else
561                         seat_send_changed(s->seat, "Sessions", NULL);
562         }
563
564         return 0;
565 }
566
567 static int session_stop_scope(Session *s, bool force) {
568         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
569         char *job = NULL;
570         int r;
571
572         assert(s);
573
574         if (!s->scope)
575                 return 0;
576
577         if (force || manager_shall_kill(s->manager, s->user->name)) {
578                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
579                 if (r < 0) {
580                         log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
581                         return r;
582                 }
583
584                 free(s->scope_job);
585                 s->scope_job = job;
586         } else {
587                 r = manager_abandon_scope(s->manager, s->scope, &error);
588                 if (r < 0) {
589                         log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
590                         return r;
591                 }
592         }
593
594         return 0;
595 }
596
597 int session_stop(Session *s, bool force) {
598         int r;
599
600         assert(s);
601
602         if (!s->user)
603                 return -ESTALE;
604
605         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
606
607         /* We are going down, don't care about FIFOs anymore */
608         session_remove_fifo(s);
609
610         /* Kill cgroup */
611         r = session_stop_scope(s, force);
612
613         s->stopping = true;
614
615         session_save(s);
616         user_save(s->user);
617
618         return r;
619 }
620
621 int session_finalize(Session *s) {
622         int r = 0;
623         SessionDevice *sd;
624
625         assert(s);
626
627         if (!s->user)
628                 return -ESTALE;
629
630         if (s->started)
631                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
632                            MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
633                            "SESSION_ID=%s", s->id,
634                            "USER_ID=%s", s->user->name,
635                            "LEADER=%lu", (unsigned long) s->leader,
636                            "MESSAGE=Removed session %s.", s->id,
637                            NULL);
638
639         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
640
641         /* Kill session devices */
642         while ((sd = hashmap_first(s->devices)))
643                 session_device_free(sd);
644
645         unlink(s->state_file);
646         session_add_to_gc_queue(s);
647         user_add_to_gc_queue(s->user);
648
649         if (s->started) {
650                 session_send_signal(s, false);
651                 s->started = false;
652         }
653
654         if (s->seat) {
655                 if (s->seat->active == s)
656                         seat_set_active(s->seat, NULL);
657
658                 seat_save(s->seat);
659                 seat_send_changed(s->seat, "Sessions", NULL);
660         }
661
662         user_save(s->user);
663         user_send_changed(s->user, "Sessions", NULL);
664
665         return r;
666 }
667
668 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
669         Session *s = userdata;
670
671         assert(es);
672         assert(s);
673
674         session_stop(s, false);
675         return 0;
676 }
677
678 void session_release(Session *s) {
679         assert(s);
680
681         if (!s->started || s->stopping)
682                 return;
683
684         if (!s->timer_event_source)
685                 sd_event_add_time(s->manager->event,
686                                   &s->timer_event_source,
687                                   CLOCK_MONOTONIC,
688                                   now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
689                                   release_timeout_callback, s);
690 }
691
692 bool session_is_active(Session *s) {
693         assert(s);
694
695         if (!s->seat)
696                 return true;
697
698         return s->seat->active == s;
699 }
700
701 static int get_tty_atime(const char *tty, usec_t *atime) {
702         _cleanup_free_ char *p = NULL;
703         struct stat st;
704
705         assert(tty);
706         assert(atime);
707
708         if (!path_is_absolute(tty)) {
709                 p = strappend("/dev/", tty);
710                 if (!p)
711                         return -ENOMEM;
712
713                 tty = p;
714         } else if (!path_startswith(tty, "/dev/"))
715                 return -ENOENT;
716
717         if (lstat(tty, &st) < 0)
718                 return -errno;
719
720         *atime = timespec_load(&st.st_atim);
721         return 0;
722 }
723
724 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
725         _cleanup_free_ char *p = NULL;
726         int r;
727
728         assert(pid > 0);
729         assert(atime);
730
731         r = get_ctty(pid, NULL, &p);
732         if (r < 0)
733                 return r;
734
735         return get_tty_atime(p, atime);
736 }
737
738 int session_get_idle_hint(Session *s, dual_timestamp *t) {
739         usec_t atime = 0, n;
740         int r;
741
742         assert(s);
743
744         /* Explicit idle hint is set */
745         if (s->idle_hint) {
746                 if (t)
747                         *t = s->idle_hint_timestamp;
748
749                 return s->idle_hint;
750         }
751
752         /* Graphical sessions should really implement a real
753          * idle hint logic */
754         if (s->display)
755                 goto dont_know;
756
757         /* For sessions with an explicitly configured tty, let's check
758          * its atime */
759         if (s->tty) {
760                 r = get_tty_atime(s->tty, &atime);
761                 if (r >= 0)
762                         goto found_atime;
763         }
764
765         /* For sessions with a leader but no explicitly configured
766          * tty, let's check the controlling tty of the leader */
767         if (s->leader > 0) {
768                 r = get_process_ctty_atime(s->leader, &atime);
769                 if (r >= 0)
770                         goto found_atime;
771         }
772
773 dont_know:
774         if (t)
775                 *t = s->idle_hint_timestamp;
776
777         return 0;
778
779 found_atime:
780         if (t)
781                 dual_timestamp_from_realtime(t, atime);
782
783         n = now(CLOCK_REALTIME);
784
785         if (s->manager->idle_action_usec <= 0)
786                 return 0;
787
788         return atime + s->manager->idle_action_usec <= n;
789 }
790
791 void session_set_idle_hint(Session *s, bool b) {
792         assert(s);
793
794         if (s->idle_hint == b)
795                 return;
796
797         s->idle_hint = b;
798         dual_timestamp_get(&s->idle_hint_timestamp);
799
800         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
801
802         if (s->seat)
803                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
804
805         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
806         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
807 }
808
809 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
810         Session *s = userdata;
811
812         assert(s);
813         assert(s->fifo_fd == fd);
814
815         /* EOF on the FIFO means the session died abnormally. */
816
817         session_remove_fifo(s);
818         session_stop(s, false);
819
820         return 1;
821 }
822
823 int session_create_fifo(Session *s) {
824         int r;
825
826         assert(s);
827
828         /* Create FIFO */
829         if (!s->fifo_path) {
830                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
831                 if (r < 0)
832                         return r;
833
834                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
835                         return -ENOMEM;
836
837                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
838                         return -errno;
839         }
840
841         /* Open reading side */
842         if (s->fifo_fd < 0) {
843                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
844                 if (s->fifo_fd < 0)
845                         return -errno;
846
847         }
848
849         if (!s->fifo_event_source) {
850                 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
851                 if (r < 0)
852                         return r;
853
854                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
855                 if (r < 0)
856                         return r;
857         }
858
859         /* Open writing side */
860         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
861         if (r < 0)
862                 return -errno;
863
864         return r;
865 }
866
867 static void session_remove_fifo(Session *s) {
868         assert(s);
869
870         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
871         s->fifo_fd = safe_close(s->fifo_fd);
872
873         if (s->fifo_path) {
874                 unlink(s->fifo_path);
875                 free(s->fifo_path);
876                 s->fifo_path = NULL;
877         }
878 }
879
880 bool session_check_gc(Session *s, bool drop_not_started) {
881         assert(s);
882
883         if (drop_not_started && !s->started)
884                 return false;
885
886         if (!s->user)
887                 return false;
888
889         if (s->fifo_fd >= 0) {
890                 if (pipe_eof(s->fifo_fd) <= 0)
891                         return true;
892         }
893
894         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
895                 return true;
896
897         if (s->scope && manager_unit_is_active(s->manager, s->scope))
898                 return true;
899
900         return false;
901 }
902
903 void session_add_to_gc_queue(Session *s) {
904         assert(s);
905
906         if (s->in_gc_queue)
907                 return;
908
909         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
910         s->in_gc_queue = true;
911 }
912
913 SessionState session_get_state(Session *s) {
914         assert(s);
915
916         /* always check closing first */
917         if (s->stopping || s->timer_event_source)
918                 return SESSION_CLOSING;
919
920         if (s->scope_job || s->fifo_fd < 0)
921                 return SESSION_OPENING;
922
923         if (session_is_active(s))
924                 return SESSION_ACTIVE;
925
926         return SESSION_ONLINE;
927 }
928
929 int session_kill(Session *s, KillWho who, int signo) {
930         assert(s);
931
932         if (!s->scope)
933                 return -ESRCH;
934
935         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
936 }
937
938 static int session_open_vt(Session *s) {
939         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
940
941         if (!s->vtnr)
942                 return -1;
943
944         if (s->vtfd >= 0)
945                 return s->vtfd;
946
947         sprintf(path, "/dev/tty%u", s->vtnr);
948         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
949         if (s->vtfd < 0) {
950                 log_error("cannot open VT %s of session %s: %m", path, s->id);
951                 return -errno;
952         }
953
954         return s->vtfd;
955 }
956
957 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
958         Session *s = data;
959
960         if (s->vtfd >= 0)
961                 ioctl(s->vtfd, VT_RELDISP, 1);
962
963         return 0;
964 }
965
966 void session_mute_vt(Session *s) {
967         int vt, r;
968         struct vt_mode mode = { 0 };
969         sigset_t mask;
970
971         vt = session_open_vt(s);
972         if (vt < 0)
973                 return;
974
975         r = ioctl(vt, KDSKBMODE, K_OFF);
976         if (r < 0)
977                 goto error;
978
979         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
980         if (r < 0)
981                 goto error;
982
983         sigemptyset(&mask);
984         sigaddset(&mask, SIGUSR1);
985         sigprocmask(SIG_BLOCK, &mask, NULL);
986
987         r = sd_event_add_signal(s->manager->event, &s->vt_source, SIGUSR1, session_vt_fn, s);
988         if (r < 0)
989                 goto error;
990
991         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
992          * So we need a dummy handler here which just acknowledges *all* VT
993          * switch requests. */
994         mode.mode = VT_PROCESS;
995         mode.relsig = SIGUSR1;
996         mode.acqsig = SIGUSR1;
997         r = ioctl(vt, VT_SETMODE, &mode);
998         if (r < 0)
999                 goto error;
1000
1001         return;
1002
1003 error:
1004         log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1005         session_restore_vt(s);
1006 }
1007
1008 void session_restore_vt(Session *s) {
1009         _cleanup_free_ char *utf8 = NULL;
1010         int vt, kb = K_XLATE;
1011         struct vt_mode mode = { 0 };
1012
1013         vt = session_open_vt(s);
1014         if (vt < 0)
1015                 return;
1016
1017         s->vt_source = sd_event_source_unref(s->vt_source);
1018
1019         ioctl(vt, KDSETMODE, KD_TEXT);
1020
1021         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1022                 kb = K_UNICODE;
1023
1024         ioctl(vt, KDSKBMODE, kb);
1025
1026         mode.mode = VT_AUTO;
1027         ioctl(vt, VT_SETMODE, &mode);
1028
1029         s->vtfd = safe_close(s->vtfd);
1030 }
1031
1032 bool session_is_controller(Session *s, const char *sender) {
1033         assert(s);
1034
1035         return streq_ptr(s->controller, sender);
1036 }
1037
1038 static void session_swap_controller(Session *s, char *name) {
1039         SessionDevice *sd;
1040
1041         if (s->controller) {
1042                 manager_drop_busname(s->manager, s->controller);
1043                 free(s->controller);
1044                 s->controller = NULL;
1045
1046                 /* Drop all devices as they're now unused. Do that after the
1047                  * controller is released to avoid sending out useles
1048                  * dbus signals. */
1049                 while ((sd = hashmap_first(s->devices)))
1050                         session_device_free(sd);
1051
1052                 if (!name)
1053                         session_restore_vt(s);
1054         }
1055
1056         s->controller = name;
1057         session_save(s);
1058 }
1059
1060 int session_set_controller(Session *s, const char *sender, bool force) {
1061         char *t;
1062         int r;
1063
1064         assert(s);
1065         assert(sender);
1066
1067         if (session_is_controller(s, sender))
1068                 return 0;
1069         if (s->controller && !force)
1070                 return -EBUSY;
1071
1072         t = strdup(sender);
1073         if (!t)
1074                 return -ENOMEM;
1075
1076         r = manager_watch_busname(s->manager, sender);
1077         if (r) {
1078                 free(t);
1079                 return r;
1080         }
1081
1082         session_swap_controller(s, t);
1083
1084         /* When setting a session controller, we forcibly mute the VT and set
1085          * it into graphics-mode. Applications can override that by changing
1086          * VT state after calling TakeControl(). However, this serves as a good
1087          * default and well-behaving controllers can now ignore VTs entirely.
1088          * Note that we reset the VT on ReleaseControl() and if the controller
1089          * exits.
1090          * If logind crashes/restarts, we restore the controller during restart
1091          * or reset the VT in case it crashed/exited, too. */
1092         session_mute_vt(s);
1093
1094         return 0;
1095 }
1096
1097 void session_drop_controller(Session *s) {
1098         assert(s);
1099
1100         if (!s->controller)
1101                 return;
1102
1103         session_swap_controller(s, NULL);
1104 }
1105
1106 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1107         [SESSION_OPENING] = "opening",
1108         [SESSION_ONLINE] = "online",
1109         [SESSION_ACTIVE] = "active",
1110         [SESSION_CLOSING] = "closing"
1111 };
1112
1113 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1114
1115 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1116         [SESSION_UNSPECIFIED] = "unspecified",
1117         [SESSION_TTY] = "tty",
1118         [SESSION_X11] = "x11",
1119         [SESSION_WAYLAND] = "wayland",
1120 };
1121
1122 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1123
1124 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1125         [SESSION_USER] = "user",
1126         [SESSION_GREETER] = "greeter",
1127         [SESSION_LOCK_SCREEN] = "lock-screen",
1128         [SESSION_BACKGROUND] = "background"
1129 };
1130
1131 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1132
1133 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1134         [KILL_LEADER] = "leader",
1135         [KILL_ALL] = "all"
1136 };
1137
1138 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);