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