chiark / gitweb /
108139ce399043d6a58640303c767a880a149d31
[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-messages.h"
32 #include "util.h"
33 #include "mkdir.h"
34 #include "path-util.h"
35 #include "fileio.h"
36 #include "audit.h"
37 #include "bus-util.h"
38 #include "bus-error.h"
39 #include "logind-session.h"
40 #include "formats-util.h"
41 #include "terminal-util.h"
42
43 #define RELEASE_USEC (20*USEC_PER_SEC)
44
45 static void session_remove_fifo(Session *s);
46
47 Session* session_new(Manager *m, const char *id) {
48         Session *s;
49
50         assert(m);
51         assert(id);
52         assert(session_id_valid(id));
53
54         s = new0(Session, 1);
55         if (!s)
56                 return NULL;
57
58         s->state_file = strappend("/run/systemd/sessions/", id);
59         if (!s->state_file) {
60                 free(s);
61                 return NULL;
62         }
63
64         s->devices = hashmap_new(&devt_hash_ops);
65         if (!s->devices) {
66                 free(s->state_file);
67                 free(s);
68                 return NULL;
69         }
70
71         s->id = basename(s->state_file);
72
73         if (hashmap_put(m->sessions, s->id, s) < 0) {
74                 hashmap_free(s->devices);
75                 free(s->state_file);
76                 free(s);
77                 return NULL;
78         }
79
80         s->manager = m;
81         s->fifo_fd = -1;
82         s->vtfd = -1;
83
84         return s;
85 }
86
87 void session_free(Session *s) {
88         SessionDevice *sd;
89
90         assert(s);
91
92         if (s->in_gc_queue)
93                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
94
95         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
96
97         session_remove_fifo(s);
98
99         session_drop_controller(s);
100
101         while ((sd = hashmap_first(s->devices)))
102                 session_device_free(sd);
103
104         hashmap_free(s->devices);
105
106         if (s->user) {
107                 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
108
109                 if (s->user->display == s)
110                         s->user->display = NULL;
111         }
112
113         if (s->seat) {
114                 if (s->seat->active == s)
115                         s->seat->active = NULL;
116                 if (s->seat->pending_switch == s)
117                         s->seat->pending_switch = NULL;
118
119                 seat_evict_position(s->seat, s);
120                 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
121         }
122
123         if (s->scope) {
124                 hashmap_remove(s->manager->session_units, s->scope);
125                 free(s->scope);
126         }
127
128         free(s->scope_job);
129
130         sd_bus_message_unref(s->create_message);
131
132         free(s->tty);
133         free(s->display);
134         free(s->remote_host);
135         free(s->remote_user);
136         free(s->service);
137         free(s->desktop);
138
139         hashmap_remove(s->manager->sessions, s->id);
140
141         free(s->state_file);
142         free(s);
143 }
144
145 void session_set_user(Session *s, User *u) {
146         assert(s);
147         assert(!s->user);
148
149         s->user = u;
150         LIST_PREPEND(sessions_by_user, u->sessions, s);
151 }
152
153 int session_save(Session *s) {
154         _cleanup_free_ char *temp_path = NULL;
155         _cleanup_fclose_ FILE *f = NULL;
156         int r = 0;
157
158         assert(s);
159
160         if (!s->user)
161                 return -ESTALE;
162
163         if (!s->started)
164                 return 0;
165
166         r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
167         if (r < 0)
168                 goto finish;
169
170         r = fopen_temporary(s->state_file, &f, &temp_path);
171         if (r < 0)
172                 goto finish;
173
174         assert(s->user);
175
176         fchmod(fileno(f), 0644);
177
178         fprintf(f,
179                 "# This is private data. Do not parse.\n"
180                 "UID="UID_FMT"\n"
181                 "USER=%s\n"
182                 "ACTIVE=%i\n"
183                 "STATE=%s\n"
184                 "REMOTE=%i\n",
185                 s->user->uid,
186                 s->user->name,
187                 session_is_active(s),
188                 session_state_to_string(session_get_state(s)),
189                 s->remote);
190
191         if (s->type >= 0)
192                 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
193
194         if (s->class >= 0)
195                 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
196
197         if (s->scope)
198                 fprintf(f, "SCOPE=%s\n", s->scope);
199         if (s->scope_job)
200                 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
201
202         if (s->fifo_path)
203                 fprintf(f, "FIFO=%s\n", s->fifo_path);
204
205         if (s->seat)
206                 fprintf(f, "SEAT=%s\n", s->seat->id);
207
208         if (s->tty)
209                 fprintf(f, "TTY=%s\n", s->tty);
210
211         if (s->display)
212                 fprintf(f, "DISPLAY=%s\n", s->display);
213
214         if (s->remote_host) {
215                 _cleanup_free_ char *escaped;
216
217                 escaped = cescape(s->remote_host);
218                 if (!escaped) {
219                         r = -ENOMEM;
220                         goto finish;
221                 }
222
223                 fprintf(f, "REMOTE_HOST=%s\n", escaped);
224         }
225
226         if (s->remote_user) {
227                 _cleanup_free_ char *escaped;
228
229                 escaped = cescape(s->remote_user);
230                 if (!escaped) {
231                         r = -ENOMEM;
232                         goto finish;
233                 }
234
235                 fprintf(f, "REMOTE_USER=%s\n", escaped);
236         }
237
238         if (s->service) {
239                 _cleanup_free_ char *escaped;
240
241                 escaped = cescape(s->service);
242                 if (!escaped) {
243                         r = -ENOMEM;
244                         goto finish;
245                 }
246
247                 fprintf(f, "SERVICE=%s\n", escaped);
248         }
249
250         if (s->desktop) {
251                 _cleanup_free_ char *escaped;
252
253
254                 escaped = cescape(s->desktop);
255                 if (!escaped) {
256                         r = -ENOMEM;
257                         goto finish;
258                 }
259
260                 fprintf(f, "DESKTOP=%s\n", escaped);
261         }
262
263         if (s->seat && seat_has_vts(s->seat))
264                 fprintf(f, "VTNR=%u\n", s->vtnr);
265
266         if (!s->vtnr)
267                 fprintf(f, "POS=%u\n", s->pos);
268
269         if (s->leader > 0)
270                 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
271
272         if (s->audit_id > 0)
273                 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
274
275         if (dual_timestamp_is_set(&s->timestamp))
276                 fprintf(f,
277                         "REALTIME="USEC_FMT"\n"
278                         "MONOTONIC="USEC_FMT"\n",
279                         s->timestamp.realtime,
280                         s->timestamp.monotonic);
281
282         if (s->controller)
283                 fprintf(f, "CONTROLLER=%s\n", s->controller);
284
285         fflush(f);
286
287         if (ferror(f) || rename(temp_path, s->state_file) < 0) {
288                 r = -errno;
289                 unlink(s->state_file);
290                 unlink(temp_path);
291         }
292
293 finish:
294         if (r < 0)
295                 log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
296
297         return r;
298 }
299
300 int session_load(Session *s) {
301         _cleanup_free_ char *remote = NULL,
302                 *seat = NULL,
303                 *vtnr = NULL,
304                 *state = NULL,
305                 *pos = NULL,
306                 *leader = NULL,
307                 *type = NULL,
308                 *class = NULL,
309                 *uid = NULL,
310                 *realtime = NULL,
311                 *monotonic = NULL,
312                 *controller = NULL;
313
314         int k, r;
315
316         assert(s);
317
318         r = parse_env_file(s->state_file, NEWLINE,
319                            "REMOTE",         &remote,
320                            "SCOPE",          &s->scope,
321                            "SCOPE_JOB",      &s->scope_job,
322                            "FIFO",           &s->fifo_path,
323                            "SEAT",           &seat,
324                            "TTY",            &s->tty,
325                            "DISPLAY",        &s->display,
326                            "REMOTE_HOST",    &s->remote_host,
327                            "REMOTE_USER",    &s->remote_user,
328                            "SERVICE",        &s->service,
329                            "DESKTOP",        &s->desktop,
330                            "VTNR",           &vtnr,
331                            "STATE",          &state,
332                            "POS",            &pos,
333                            "LEADER",         &leader,
334                            "TYPE",           &type,
335                            "CLASS",          &class,
336                            "UID",            &uid,
337                            "REALTIME",       &realtime,
338                            "MONOTONIC",      &monotonic,
339                            "CONTROLLER",     &controller,
340                            NULL);
341
342         if (r < 0)
343                 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
344
345         if (!s->user) {
346                 uid_t u;
347                 User *user;
348
349                 if (!uid) {
350                         log_error("UID not specified for session %s", s->id);
351                         return -ENOENT;
352                 }
353
354                 r = parse_uid(uid, &u);
355                 if (r < 0)  {
356                         log_error("Failed to parse UID value %s for session %s.", uid, s->id);
357                         return r;
358                 }
359
360                 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
361                 if (!user) {
362                         log_error("User of session %s not known.", s->id);
363                         return -ENOENT;
364                 }
365
366                 session_set_user(s, user);
367         }
368
369         if (remote) {
370                 k = parse_boolean(remote);
371                 if (k >= 0)
372                         s->remote = k;
373         }
374
375         if (vtnr)
376                 safe_atou(vtnr, &s->vtnr);
377
378         if (seat && !s->seat) {
379                 Seat *o;
380
381                 o = hashmap_get(s->manager->seats, seat);
382                 if (o)
383                         r = seat_attach_session(o, s);
384                 if (!o || r < 0)
385                         log_error("Cannot attach session %s to seat %s", s->id, seat);
386         }
387
388         if (!s->seat || !seat_has_vts(s->seat))
389                 s->vtnr = 0;
390
391         if (pos && s->seat) {
392                 unsigned int npos;
393
394                 safe_atou(pos, &npos);
395                 seat_claim_position(s->seat, s, npos);
396         }
397
398         if (leader) {
399                 k = parse_pid(leader, &s->leader);
400                 if (k >= 0)
401                         audit_session_from_pid(s->leader, &s->audit_id);
402         }
403
404         if (type) {
405                 SessionType t;
406
407                 t = session_type_from_string(type);
408                 if (t >= 0)
409                         s->type = t;
410         }
411
412         if (class) {
413                 SessionClass c;
414
415                 c = session_class_from_string(class);
416                 if (c >= 0)
417                         s->class = c;
418         }
419
420         if (state && streq(state, "closing"))
421                 s->stopping = true;
422
423         if (s->fifo_path) {
424                 int fd;
425
426                 /* If we open an unopened pipe for reading we will not
427                    get an EOF. to trigger an EOF we hence open it for
428                    writing, but close it right away which then will
429                    trigger the EOF. This will happen immediately if no
430                    other process has the FIFO open for writing, i. e.
431                    when the session died before logind (re)started. */
432
433                 fd = session_create_fifo(s);
434                 safe_close(fd);
435         }
436
437         if (realtime) {
438                 unsigned long long l;
439                 if (sscanf(realtime, "%llu", &l) > 0)
440                         s->timestamp.realtime = l;
441         }
442
443         if (monotonic) {
444                 unsigned long long l;
445                 if (sscanf(monotonic, "%llu", &l) > 0)
446                         s->timestamp.monotonic = l;
447         }
448
449         if (controller) {
450                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
451                         session_set_controller(s, controller, false);
452                 else
453                         session_restore_vt(s);
454         }
455
456         return r;
457 }
458
459 int session_activate(Session *s) {
460         unsigned int num_pending;
461
462         assert(s);
463         assert(s->user);
464
465         if (!s->seat)
466                 return -EOPNOTSUPP;
467
468         if (s->seat->active == s)
469                 return 0;
470
471         /* on seats with VTs, we let VTs manage session-switching */
472         if (seat_has_vts(s->seat)) {
473                 if (!s->vtnr)
474                         return -EOPNOTSUPP;
475
476                 return chvt(s->vtnr);
477         }
478
479         /* On seats without VTs, we implement session-switching in logind. We
480          * try to pause all session-devices and wait until the session
481          * controller acknowledged them. Once all devices are asleep, we simply
482          * switch the active session and be done.
483          * We save the session we want to switch to in seat->pending_switch and
484          * seat_complete_switch() will perform the final switch. */
485
486         s->seat->pending_switch = s;
487
488         /* if no devices are running, immediately perform the session switch */
489         num_pending = session_device_try_pause_all(s);
490         if (!num_pending)
491                 seat_complete_switch(s->seat);
492
493         return 0;
494 }
495
496 static int session_start_scope(Session *s) {
497         int r;
498
499         assert(s);
500         assert(s->user);
501         assert(s->user->slice);
502
503         if (!s->scope) {
504                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
505                 _cleanup_free_ char *description = NULL;
506                 char *scope, *job = NULL;
507
508                 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
509                 if (!description)
510                         return log_oom();
511
512                 scope = strjoin("session-", s->id, ".scope", NULL);
513                 if (!scope)
514                         return log_oom();
515
516                 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "logind.service", "systemd-user-sessions.service", &error, &job);
517                 if (r < 0) {
518                         log_error("Failed to start session scope %s: %s %s",
519                                   scope, bus_error_message(&error, r), error.name);
520                         free(scope);
521                         return r;
522                 } else {
523                         s->scope = scope;
524
525                         free(s->scope_job);
526                         s->scope_job = job;
527                 }
528         }
529
530         if (s->scope)
531                 hashmap_put(s->manager->session_units, s->scope, s);
532
533         return 0;
534 }
535
536 int session_start(Session *s) {
537         int r;
538
539         assert(s);
540
541         if (!s->user)
542                 return -ESTALE;
543
544         if (s->started)
545                 return 0;
546
547         r = user_start(s->user);
548         if (r < 0)
549                 return r;
550
551         /* Create cgroup */
552         r = session_start_scope(s);
553         if (r < 0)
554                 return r;
555
556         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
557                    LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START),
558                    "SESSION_ID=%s", s->id,
559                    "USER_ID=%s", s->user->name,
560                    "LEADER="PID_FMT, s->leader,
561                    LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name),
562                    NULL);
563
564         if (!dual_timestamp_is_set(&s->timestamp))
565                 dual_timestamp_get(&s->timestamp);
566
567         if (s->seat)
568                 seat_read_active_vt(s->seat);
569
570         s->started = true;
571
572         user_elect_display(s->user);
573
574         /* Save data */
575         session_save(s);
576         user_save(s->user);
577         if (s->seat)
578                 seat_save(s->seat);
579
580         /* Send signals */
581         session_send_signal(s, true);
582         user_send_changed(s->user, "Sessions", "Display", NULL);
583         if (s->seat) {
584                 if (s->seat->active == s)
585                         seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
586                 else
587                         seat_send_changed(s->seat, "Sessions", NULL);
588         }
589
590         return 0;
591 }
592
593 static int session_stop_scope(Session *s, bool force) {
594         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
595         char *job = NULL;
596         int r;
597
598         assert(s);
599
600         if (!s->scope)
601                 return 0;
602
603         if (force || manager_shall_kill(s->manager, s->user->name)) {
604                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
605                 if (r < 0) {
606                         log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
607                         return r;
608                 }
609
610                 free(s->scope_job);
611                 s->scope_job = job;
612         } else {
613                 r = manager_abandon_scope(s->manager, s->scope, &error);
614                 if (r < 0) {
615                         log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
616                         return r;
617                 }
618         }
619
620         return 0;
621 }
622
623 int session_stop(Session *s, bool force) {
624         int r;
625
626         assert(s);
627
628         if (!s->user)
629                 return -ESTALE;
630
631         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
632
633         /* We are going down, don't care about FIFOs anymore */
634         session_remove_fifo(s);
635
636         /* Kill cgroup */
637         r = session_stop_scope(s, force);
638
639         s->stopping = true;
640
641         user_elect_display(s->user);
642
643         session_save(s);
644         user_save(s->user);
645
646         return r;
647 }
648
649 int session_finalize(Session *s) {
650         int r = 0;
651         SessionDevice *sd;
652
653         assert(s);
654
655         if (!s->user)
656                 return -ESTALE;
657
658         if (s->started)
659                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
660                            LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
661                            "SESSION_ID=%s", s->id,
662                            "USER_ID=%s", s->user->name,
663                            "LEADER="PID_FMT, s->leader,
664                            LOG_MESSAGE("Removed session %s.", s->id),
665                            NULL);
666
667         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
668
669         /* Kill session devices */
670         while ((sd = hashmap_first(s->devices)))
671                 session_device_free(sd);
672
673         unlink(s->state_file);
674         session_add_to_gc_queue(s);
675         user_add_to_gc_queue(s->user);
676
677         if (s->started) {
678                 session_send_signal(s, false);
679                 s->started = false;
680         }
681
682         if (s->seat) {
683                 if (s->seat->active == s)
684                         seat_set_active(s->seat, NULL);
685
686                 seat_save(s->seat);
687                 seat_send_changed(s->seat, "Sessions", NULL);
688         }
689
690         user_save(s->user);
691         user_send_changed(s->user, "Sessions", "Display", NULL);
692
693         return r;
694 }
695
696 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
697         Session *s = userdata;
698
699         assert(es);
700         assert(s);
701
702         session_stop(s, false);
703         return 0;
704 }
705
706 int session_release(Session *s) {
707         assert(s);
708
709         if (!s->started || s->stopping)
710                 return 0;
711
712         if (s->timer_event_source)
713                 return 0;
714
715         return sd_event_add_time(s->manager->event,
716                                  &s->timer_event_source,
717                                  CLOCK_MONOTONIC,
718                                  now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
719                                  release_timeout_callback, s);
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, false);
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_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
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 static void session_remove_fifo(Session *s) {
898         assert(s);
899
900         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
901         s->fifo_fd = safe_close(s->fifo_fd);
902
903         if (s->fifo_path) {
904                 unlink(s->fifo_path);
905                 free(s->fifo_path);
906                 s->fifo_path = NULL;
907         }
908 }
909
910 bool session_check_gc(Session *s, bool drop_not_started) {
911         assert(s);
912
913         if (drop_not_started && !s->started)
914                 return false;
915
916         if (!s->user)
917                 return false;
918
919         if (s->fifo_fd >= 0) {
920                 if (pipe_eof(s->fifo_fd) <= 0)
921                         return true;
922         }
923
924         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
925                 return true;
926
927         if (s->scope && manager_unit_is_active(s->manager, s->scope))
928                 return true;
929
930         return false;
931 }
932
933 void session_add_to_gc_queue(Session *s) {
934         assert(s);
935
936         if (s->in_gc_queue)
937                 return;
938
939         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
940         s->in_gc_queue = true;
941 }
942
943 SessionState session_get_state(Session *s) {
944         assert(s);
945
946         /* always check closing first */
947         if (s->stopping || s->timer_event_source)
948                 return SESSION_CLOSING;
949
950         if (s->scope_job || s->fifo_fd < 0)
951                 return SESSION_OPENING;
952
953         if (session_is_active(s))
954                 return SESSION_ACTIVE;
955
956         return SESSION_ONLINE;
957 }
958
959 int session_kill(Session *s, KillWho who, int signo) {
960         assert(s);
961
962         if (!s->scope)
963                 return -ESRCH;
964
965         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
966 }
967
968 static int session_open_vt(Session *s) {
969         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
970
971         if (s->vtnr < 1)
972                 return -ENODEV;
973
974         if (s->vtfd >= 0)
975                 return s->vtfd;
976
977         sprintf(path, "/dev/tty%u", s->vtnr);
978         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
979         if (s->vtfd < 0)
980                 return log_error_errno(errno, "cannot open VT %s of session %s: %m", path, s->id);
981
982         return s->vtfd;
983 }
984
985 int session_prepare_vt(Session *s) {
986         int vt, r;
987         struct vt_mode mode = { 0 };
988
989         if (s->vtnr < 1)
990                 return 0;
991
992         vt = session_open_vt(s);
993         if (vt < 0)
994                 return vt;
995
996         r = fchown(vt, s->user->uid, -1);
997         if (r < 0) {
998                 r = -errno;
999                 log_error_errno(errno, "Cannot change owner of /dev/tty%u: %m", s->vtnr);
1000                 goto error;
1001         }
1002
1003         r = ioctl(vt, KDSKBMODE, K_OFF);
1004         if (r < 0) {
1005                 r = -errno;
1006                 log_error_errno(errno, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr);
1007                 goto error;
1008         }
1009
1010         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1011         if (r < 0) {
1012                 r = -errno;
1013                 log_error_errno(errno, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr);
1014                 goto error;
1015         }
1016
1017         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1018          * So we need a dummy handler here which just acknowledges *all* VT
1019          * switch requests. */
1020         mode.mode = VT_PROCESS;
1021         mode.relsig = SIGRTMIN;
1022         mode.acqsig = SIGRTMIN + 1;
1023         r = ioctl(vt, VT_SETMODE, &mode);
1024         if (r < 0) {
1025                 r = -errno;
1026                 log_error_errno(errno, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr);
1027                 goto error;
1028         }
1029
1030         return 0;
1031
1032 error:
1033         session_restore_vt(s);
1034         return r;
1035 }
1036
1037 void session_restore_vt(Session *s) {
1038         _cleanup_free_ char *utf8 = NULL;
1039         int vt, kb = K_XLATE;
1040         struct vt_mode mode = { 0 };
1041
1042         vt = session_open_vt(s);
1043         if (vt < 0)
1044                 return;
1045
1046         (void) ioctl(vt, KDSETMODE, KD_TEXT);
1047
1048         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1049                 kb = K_UNICODE;
1050
1051         (void) ioctl(vt, KDSKBMODE, kb);
1052
1053         mode.mode = VT_AUTO;
1054         (void) ioctl(vt, VT_SETMODE, &mode);
1055
1056         fchown(vt, 0, -1);
1057
1058         s->vtfd = safe_close(s->vtfd);
1059 }
1060
1061 void session_leave_vt(Session *s) {
1062         int r;
1063
1064         assert(s);
1065
1066         /* This is called whenever we get a VT-switch signal from the kernel.
1067          * We acknowledge all of them unconditionally. Note that session are
1068          * free to overwrite those handlers and we only register them for
1069          * sessions with controllers. Legacy sessions are not affected.
1070          * However, if we switch from a non-legacy to a legacy session, we must
1071          * make sure to pause all device before acknowledging the switch. We
1072          * process the real switch only after we are notified via sysfs, so the
1073          * legacy session might have already started using the devices. If we
1074          * don't pause the devices before the switch, we might confuse the
1075          * session we switch to. */
1076
1077         if (s->vtfd < 0)
1078                 return;
1079
1080         session_device_pause_all(s);
1081         r = ioctl(s->vtfd, VT_RELDISP, 1);
1082         if (r < 0)
1083                 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
1084 }
1085
1086 bool session_is_controller(Session *s, const char *sender) {
1087         assert(s);
1088
1089         return streq_ptr(s->controller, sender);
1090 }
1091
1092 static void session_release_controller(Session *s, bool notify) {
1093         _cleanup_free_ char *name = NULL;
1094         SessionDevice *sd;
1095
1096         if (!s->controller)
1097                 return;
1098
1099         name = s->controller;
1100
1101         /* By resetting the controller before releasing the devices, we won't
1102          * send notification signals. This avoids sending useless notifications
1103          * if the controller is released on disconnects. */
1104         if (!notify)
1105                 s->controller = NULL;
1106
1107         while ((sd = hashmap_first(s->devices)))
1108                 session_device_free(sd);
1109
1110         s->controller = NULL;
1111         manager_drop_busname(s->manager, name);
1112 }
1113
1114 int session_set_controller(Session *s, const char *sender, bool force) {
1115         _cleanup_free_ char *name = NULL;
1116         int r;
1117
1118         assert(s);
1119         assert(sender);
1120
1121         if (session_is_controller(s, sender))
1122                 return 0;
1123         if (s->controller && !force)
1124                 return -EBUSY;
1125
1126         name = strdup(sender);
1127         if (!name)
1128                 return -ENOMEM;
1129
1130         r = manager_watch_busname(s->manager, name);
1131         if (r)
1132                 return r;
1133
1134         /* When setting a session controller, we forcibly mute the VT and set
1135          * it into graphics-mode. Applications can override that by changing
1136          * VT state after calling TakeControl(). However, this serves as a good
1137          * default and well-behaving controllers can now ignore VTs entirely.
1138          * Note that we reset the VT on ReleaseControl() and if the controller
1139          * exits.
1140          * If logind crashes/restarts, we restore the controller during restart
1141          * or reset the VT in case it crashed/exited, too. */
1142         r = session_prepare_vt(s);
1143         if (r < 0) {
1144                 manager_drop_busname(s->manager, name);
1145                 return r;
1146         }
1147
1148         session_release_controller(s, true);
1149         s->controller = name;
1150         name = NULL;
1151         session_save(s);
1152
1153         return 0;
1154 }
1155
1156 void session_drop_controller(Session *s) {
1157         assert(s);
1158
1159         if (!s->controller)
1160                 return;
1161
1162         session_release_controller(s, false);
1163         session_save(s);
1164         session_restore_vt(s);
1165 }
1166
1167 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1168         [SESSION_OPENING] = "opening",
1169         [SESSION_ONLINE] = "online",
1170         [SESSION_ACTIVE] = "active",
1171         [SESSION_CLOSING] = "closing"
1172 };
1173
1174 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1175
1176 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1177         [SESSION_UNSPECIFIED] = "unspecified",
1178         [SESSION_TTY] = "tty",
1179         [SESSION_X11] = "x11",
1180         [SESSION_WAYLAND] = "wayland",
1181         [SESSION_MIR] = "mir",
1182         [SESSION_WEB] = "web",
1183 };
1184
1185 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1186
1187 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1188         [SESSION_USER] = "user",
1189         [SESSION_GREETER] = "greeter",
1190         [SESSION_LOCK_SCREEN] = "lock-screen",
1191         [SESSION_BACKGROUND] = "background"
1192 };
1193
1194 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1195
1196 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1197         [KILL_LEADER] = "leader",
1198         [KILL_ALL] = "all"
1199 };
1200
1201 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);