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