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