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