chiark / gitweb /
logind: make VT numbers unsigned
[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 (seat && !s->seat) {
338                 Seat *o;
339
340                 o = hashmap_get(s->manager->seats, seat);
341                 if (o)
342                         seat_attach_session(o, s);
343         }
344
345         if (vtnr && s->seat && seat_has_vts(s->seat)) {
346                 unsigned int v;
347
348                 k = safe_atou(vtnr, &v);
349                 if (k >= 0 && v >= 1)
350                         s->vtnr = v;
351         }
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->closing)
958                 return SESSION_CLOSING;
959
960         if (s->scope_job)
961                 return SESSION_OPENING;
962
963         if (s->fifo_fd < 0)
964                 return SESSION_CLOSING;
965
966         if (session_is_active(s))
967                 return SESSION_ACTIVE;
968
969         return SESSION_ONLINE;
970 }
971
972 int session_kill(Session *s, KillWho who, int signo) {
973         assert(s);
974
975         if (!s->scope)
976                 return -ESRCH;
977
978         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
979 }
980
981 static int session_open_vt(Session *s) {
982         char path[128];
983
984         if (!s->vtnr)
985                 return -1;
986
987         if (s->vtfd >= 0)
988                 return s->vtfd;
989
990         sprintf(path, "/dev/tty%u", s->vtnr);
991         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
992         if (s->vtfd < 0) {
993                 log_error("cannot open VT %s of session %s: %m", path, s->id);
994                 return -1;
995         }
996
997         return s->vtfd;
998 }
999
1000 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
1001         Session *s = data;
1002
1003         if (s->vtfd >= 0)
1004                 ioctl(s->vtfd, VT_RELDISP, 1);
1005
1006         return 0;
1007 }
1008
1009 void session_mute_vt(Session *s) {
1010         int vt, r;
1011         struct vt_mode mode = { 0 };
1012         sigset_t mask;
1013
1014         vt = session_open_vt(s);
1015         if (vt < 0)
1016                 return;
1017
1018         r = ioctl(vt, KDSKBMODE, K_OFF);
1019         if (r < 0)
1020                 goto error;
1021
1022         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1023         if (r < 0)
1024                 goto error;
1025
1026         sigemptyset(&mask);
1027         sigaddset(&mask, SIGUSR1);
1028         sigprocmask(SIG_BLOCK, &mask, NULL);
1029
1030         r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
1031         if (r < 0)
1032                 goto error;
1033
1034         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1035          * So we need a dummy handler here which just acknowledges *all* VT
1036          * switch requests. */
1037         mode.mode = VT_PROCESS;
1038         mode.relsig = SIGUSR1;
1039         mode.acqsig = SIGUSR1;
1040         r = ioctl(vt, VT_SETMODE, &mode);
1041         if (r < 0)
1042                 goto error;
1043
1044         return;
1045
1046 error:
1047         log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1048         session_restore_vt(s);
1049 }
1050
1051 void session_restore_vt(Session *s) {
1052         _cleanup_free_ char *utf8;
1053         int vt, kb = K_XLATE;
1054         struct vt_mode mode = { 0 };
1055
1056         vt = session_open_vt(s);
1057         if (vt < 0)
1058                 return;
1059
1060         sd_event_source_unref(s->vt_source);
1061         s->vt_source = NULL;
1062
1063         ioctl(vt, KDSETMODE, KD_TEXT);
1064
1065         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1066                 kb = K_UNICODE;
1067         ioctl(vt, KDSKBMODE, kb);
1068
1069         mode.mode = VT_AUTO;
1070         ioctl(vt, VT_SETMODE, &mode);
1071
1072         close_nointr_nofail(vt);
1073         s->vtfd = -1;
1074 }
1075
1076 bool session_is_controller(Session *s, const char *sender) {
1077         assert(s);
1078
1079         return streq_ptr(s->controller, sender);
1080 }
1081
1082 static void session_swap_controller(Session *s, char *name) {
1083         SessionDevice *sd;
1084
1085         if (s->controller) {
1086                 manager_drop_busname(s->manager, s->controller);
1087                 free(s->controller);
1088                 s->controller = NULL;
1089
1090                 /* Drop all devices as they're now unused. Do that after the
1091                  * controller is released to avoid sending out useles
1092                  * dbus signals. */
1093                 while ((sd = hashmap_first(s->devices)))
1094                         session_device_free(sd);
1095
1096                 if (!name)
1097                         session_restore_vt(s);
1098         }
1099
1100         s->controller = name;
1101         session_save(s);
1102 }
1103
1104 int session_set_controller(Session *s, const char *sender, bool force) {
1105         char *t;
1106         int r;
1107
1108         assert(s);
1109         assert(sender);
1110
1111         if (session_is_controller(s, sender))
1112                 return 0;
1113         if (s->controller && !force)
1114                 return -EBUSY;
1115
1116         t = strdup(sender);
1117         if (!t)
1118                 return -ENOMEM;
1119
1120         r = manager_watch_busname(s->manager, sender);
1121         if (r) {
1122                 free(t);
1123                 return r;
1124         }
1125
1126         session_swap_controller(s, t);
1127
1128         /* When setting a session controller, we forcibly mute the VT and set
1129          * it into graphics-mode. Applications can override that by changing
1130          * VT state after calling TakeControl(). However, this serves as a good
1131          * default and well-behaving controllers can now ignore VTs entirely.
1132          * Note that we reset the VT on ReleaseControl() and if the controller
1133          * exits.
1134          * If logind crashes/restarts, we restore the controller during restart
1135          * or reset the VT in case it crashed/exited, too. */
1136         session_mute_vt(s);
1137
1138         return 0;
1139 }
1140
1141 void session_drop_controller(Session *s) {
1142         assert(s);
1143
1144         if (!s->controller)
1145                 return;
1146
1147         session_swap_controller(s, NULL);
1148 }
1149
1150 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1151         [SESSION_OPENING] = "opening",
1152         [SESSION_ONLINE] = "online",
1153         [SESSION_ACTIVE] = "active",
1154         [SESSION_CLOSING] = "closing"
1155 };
1156
1157 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1158
1159 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1160         [SESSION_TTY] = "tty",
1161         [SESSION_X11] = "x11",
1162         [SESSION_UNSPECIFIED] = "unspecified"
1163 };
1164
1165 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1166
1167 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1168         [SESSION_USER] = "user",
1169         [SESSION_GREETER] = "greeter",
1170         [SESSION_LOCK_SCREEN] = "lock-screen",
1171         [SESSION_BACKGROUND] = "background"
1172 };
1173
1174 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1175
1176 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1177         [KILL_LEADER] = "leader",
1178         [KILL_ALL] = "all"
1179 };
1180
1181 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);