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