chiark / gitweb /
Prep v234: Check against TRANSPORT_LOCAL in check_inhibitors()
[elogind.git] / src / login / logind-session.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2011 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <linux/kd.h>
23 #include <linux/vt.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <unistd.h>
28
29 #include "sd-messages.h"
30
31 #include "alloc-util.h"
32 #include "audit-util.h"
33 #include "bus-error.h"
34 #include "bus-util.h"
35 #include "escape.h"
36 #include "extract-word.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "format-util.h"
40 #include "io-util.h"
41 #include "logind-session.h"
42 #include "mkdir.h"
43 #include "parse-util.h"
44 #include "path-util.h"
45 #include "string-table.h"
46 #include "terminal-util.h"
47 #include "user-util.h"
48 #include "util.h"
49
50 #define RELEASE_USEC (20*USEC_PER_SEC)
51
52 static void session_remove_fifo(Session *s);
53
54 Session* session_new(Manager *m, const char *id) {
55         Session *s;
56
57         assert(m);
58         assert(id);
59         assert(session_id_valid(id));
60
61         s = new0(Session, 1);
62         if (!s)
63                 return NULL;
64
65         s->state_file = strappend("/run/systemd/sessions/", id);
66         if (!s->state_file)
67                 return mfree(s);
68
69         s->devices = hashmap_new(&devt_hash_ops);
70         if (!s->devices) {
71                 free(s->state_file);
72                 return mfree(s);
73         }
74
75         s->id = basename(s->state_file);
76
77         if (hashmap_put(m->sessions, s->id, s) < 0) {
78                 hashmap_free(s->devices);
79                 free(s->state_file);
80                 return mfree(s);
81         }
82
83         s->manager = m;
84         s->fifo_fd = -1;
85         s->vtfd = -1;
86
87         return s;
88 }
89
90 void session_free(Session *s) {
91         SessionDevice *sd;
92
93         assert(s);
94
95         if (s->in_gc_queue)
96                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
97
98         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
99
100         session_remove_fifo(s);
101
102         session_drop_controller(s);
103
104         while ((sd = hashmap_first(s->devices)))
105                 session_device_free(sd);
106
107         hashmap_free(s->devices);
108
109         if (s->user) {
110                 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
111
112                 if (s->user->display == s)
113                         s->user->display = NULL;
114         }
115
116         if (s->seat) {
117                 if (s->seat->active == s)
118                         s->seat->active = NULL;
119                 if (s->seat->pending_switch == s)
120                         s->seat->pending_switch = NULL;
121
122                 seat_evict_position(s->seat, s);
123                 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
124         }
125
126         if (s->scope) {
127                 hashmap_remove(s->manager->session_units, s->scope);
128                 free(s->scope);
129         }
130
131 #if 0 /// elogind does not support systemd scope_jobs
132         free(s->scope_job);
133 #endif // 0
134
135         sd_bus_message_unref(s->create_message);
136
137         free(s->tty);
138         free(s->display);
139         free(s->remote_host);
140         free(s->remote_user);
141         free(s->service);
142         free(s->desktop);
143
144         hashmap_remove(s->manager->sessions, s->id);
145
146         free(s->state_file);
147         free(s);
148 }
149
150 void session_set_user(Session *s, User *u) {
151         assert(s);
152         assert(!s->user);
153
154         s->user = u;
155         LIST_PREPEND(sessions_by_user, u->sessions, s);
156 }
157
158 static void session_save_devices(Session *s, FILE *f) {
159         SessionDevice *sd;
160         Iterator i;
161
162         if (!hashmap_isempty(s->devices)) {
163                 fprintf(f, "DEVICES=");
164                 HASHMAP_FOREACH(sd, s->devices, i)
165                         fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
166                 fprintf(f, "\n");
167         }
168 }
169
170 int session_save(Session *s) {
171         _cleanup_free_ char *temp_path = NULL;
172         _cleanup_fclose_ FILE *f = NULL;
173         int r = 0;
174
175         assert(s);
176
177         if (!s->user)
178                 return -ESTALE;
179
180         if (!s->started)
181                 return 0;
182
183         r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
184         if (r < 0)
185                 goto fail;
186
187         r = fopen_temporary(s->state_file, &f, &temp_path);
188         if (r < 0)
189                 goto fail;
190
191         assert(s->user);
192
193         fchmod(fileno(f), 0644);
194
195         fprintf(f,
196                 "# This is private data. Do not parse.\n"
197                 "UID="UID_FMT"\n"
198                 "USER=%s\n"
199                 "ACTIVE=%i\n"
200                 "STATE=%s\n"
201                 "REMOTE=%i\n",
202                 s->user->uid,
203                 s->user->name,
204                 session_is_active(s),
205                 session_state_to_string(session_get_state(s)),
206                 s->remote);
207
208         if (s->type >= 0)
209                 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
210
211         if (s->class >= 0)
212                 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
213
214         if (s->scope)
215                 fprintf(f, "SCOPE=%s\n", s->scope);
216 #if 0 /// elogind does not support systemd scope_jobs
217         if (s->scope_job)
218                 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
219 #endif // 0
220
221         if (s->fifo_path)
222                 fprintf(f, "FIFO=%s\n", s->fifo_path);
223
224         if (s->seat)
225                 fprintf(f, "SEAT=%s\n", s->seat->id);
226
227         if (s->tty)
228                 fprintf(f, "TTY=%s\n", s->tty);
229
230         if (s->display)
231                 fprintf(f, "DISPLAY=%s\n", s->display);
232
233         if (s->remote_host) {
234                 _cleanup_free_ char *escaped;
235
236                 escaped = cescape(s->remote_host);
237                 if (!escaped) {
238                         r = -ENOMEM;
239                         goto fail;
240                 }
241
242                 fprintf(f, "REMOTE_HOST=%s\n", escaped);
243         }
244
245         if (s->remote_user) {
246                 _cleanup_free_ char *escaped;
247
248                 escaped = cescape(s->remote_user);
249                 if (!escaped) {
250                         r = -ENOMEM;
251                         goto fail;
252                 }
253
254                 fprintf(f, "REMOTE_USER=%s\n", escaped);
255         }
256
257         if (s->service) {
258                 _cleanup_free_ char *escaped;
259
260                 escaped = cescape(s->service);
261                 if (!escaped) {
262                         r = -ENOMEM;
263                         goto fail;
264                 }
265
266                 fprintf(f, "SERVICE=%s\n", escaped);
267         }
268
269         if (s->desktop) {
270                 _cleanup_free_ char *escaped;
271
272
273                 escaped = cescape(s->desktop);
274                 if (!escaped) {
275                         r = -ENOMEM;
276                         goto fail;
277                 }
278
279                 fprintf(f, "DESKTOP=%s\n", escaped);
280         }
281
282         if (s->seat && seat_has_vts(s->seat))
283                 fprintf(f, "VTNR=%u\n", s->vtnr);
284
285         if (!s->vtnr)
286                 fprintf(f, "POSITION=%u\n", s->position);
287
288         if (s->leader > 0)
289                 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
290
291         if (s->audit_id > 0)
292                 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
293
294         if (dual_timestamp_is_set(&s->timestamp))
295                 fprintf(f,
296                         "REALTIME="USEC_FMT"\n"
297                         "MONOTONIC="USEC_FMT"\n",
298                         s->timestamp.realtime,
299                         s->timestamp.monotonic);
300
301         if (s->controller) {
302                 fprintf(f, "CONTROLLER=%s\n", s->controller);
303                 session_save_devices(s, f);
304         }
305
306         r = fflush_and_check(f);
307         if (r < 0)
308                 goto fail;
309
310         if (rename(temp_path, s->state_file) < 0) {
311                 r = -errno;
312                 goto fail;
313         }
314
315         return 0;
316
317 fail:
318         (void) unlink(s->state_file);
319
320         if (temp_path)
321                 (void) unlink(temp_path);
322
323         return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
324 }
325
326 static int session_load_devices(Session *s, const char *devices) {
327         const char *p;
328         int r = 0;
329
330         assert(s);
331
332         for (p = devices;;) {
333                 _cleanup_free_ char *word = NULL;
334                 SessionDevice *sd;
335                 dev_t dev;
336                 int k;
337
338                 k = extract_first_word(&p, &word, NULL, 0);
339                 if (k == 0)
340                         break;
341                 if (k < 0) {
342                         r = k;
343                         break;
344                 }
345
346                 k = parse_dev(word, &dev);
347                 if (k < 0) {
348                         r = k;
349                         continue;
350                 }
351
352                 /* The file descriptors for loaded devices will be reattached later. */
353                 k = session_device_new(s, dev, false, &sd);
354                 if (k < 0)
355                         r = k;
356         }
357
358         if (r < 0)
359                 log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
360
361         return r;
362 }
363
364 int session_load(Session *s) {
365         _cleanup_free_ char *remote = NULL,
366                 *seat = NULL,
367                 *vtnr = NULL,
368                 *state = NULL,
369                 *position = NULL,
370                 *leader = NULL,
371                 *type = NULL,
372                 *class = NULL,
373                 *uid = NULL,
374                 *realtime = NULL,
375                 *monotonic = NULL,
376                 *controller = NULL,
377                 *active = NULL,
378                 *devices = NULL;
379
380         int k, r;
381
382         assert(s);
383
384         r = parse_env_file(s->state_file, NEWLINE,
385                            "REMOTE",         &remote,
386                            "SCOPE",          &s->scope,
387 #if 0 /// elogind does not support systemd scope_jobs
388                            "SCOPE_JOB",      &s->scope_job,
389 #endif // 0
390                            "FIFO",           &s->fifo_path,
391                            "SEAT",           &seat,
392                            "TTY",            &s->tty,
393                            "DISPLAY",        &s->display,
394                            "REMOTE_HOST",    &s->remote_host,
395                            "REMOTE_USER",    &s->remote_user,
396                            "SERVICE",        &s->service,
397                            "DESKTOP",        &s->desktop,
398                            "VTNR",           &vtnr,
399                            "STATE",          &state,
400                            "POSITION",       &position,
401                            "LEADER",         &leader,
402                            "TYPE",           &type,
403                            "CLASS",          &class,
404                            "UID",            &uid,
405                            "REALTIME",       &realtime,
406                            "MONOTONIC",      &monotonic,
407                            "CONTROLLER",     &controller,
408                            "ACTIVE",         &active,
409                            "DEVICES",        &devices,
410                            NULL);
411
412         if (r < 0)
413                 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
414
415         if (!s->user) {
416                 uid_t u;
417                 User *user;
418
419                 if (!uid) {
420                         log_error("UID not specified for session %s", s->id);
421                         return -ENOENT;
422                 }
423
424                 r = parse_uid(uid, &u);
425                 if (r < 0)  {
426                         log_error("Failed to parse UID value %s for session %s.", uid, s->id);
427                         return r;
428                 }
429
430                 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
431                 if (!user) {
432                         log_error("User of session %s not known.", s->id);
433                         return -ENOENT;
434                 }
435
436                 session_set_user(s, user);
437         }
438
439         if (remote) {
440                 k = parse_boolean(remote);
441                 if (k >= 0)
442                         s->remote = k;
443         }
444
445         if (vtnr)
446                 safe_atou(vtnr, &s->vtnr);
447
448         if (seat && !s->seat) {
449                 Seat *o;
450
451                 o = hashmap_get(s->manager->seats, seat);
452                 if (o)
453                         r = seat_attach_session(o, s);
454                 if (!o || r < 0)
455                         log_error("Cannot attach session %s to seat %s", s->id, seat);
456         }
457
458         if (!s->seat || !seat_has_vts(s->seat))
459                 s->vtnr = 0;
460
461         if (position && s->seat) {
462                 unsigned int npos;
463
464                 safe_atou(position, &npos);
465                 seat_claim_position(s->seat, s, npos);
466         }
467
468         if (leader) {
469                 k = parse_pid(leader, &s->leader);
470                 if (k >= 0)
471                         audit_session_from_pid(s->leader, &s->audit_id);
472         }
473
474         if (type) {
475                 SessionType t;
476
477                 t = session_type_from_string(type);
478                 if (t >= 0)
479                         s->type = t;
480         }
481
482         if (class) {
483                 SessionClass c;
484
485                 c = session_class_from_string(class);
486                 if (c >= 0)
487                         s->class = c;
488         }
489
490         if (state && streq(state, "closing"))
491                 s->stopping = true;
492
493         if (s->fifo_path) {
494                 int fd;
495
496                 /* If we open an unopened pipe for reading we will not
497                    get an EOF. to trigger an EOF we hence open it for
498                    writing, but close it right away which then will
499                    trigger the EOF. This will happen immediately if no
500                    other process has the FIFO open for writing, i. e.
501                    when the session died before logind (re)started. */
502
503                 fd = session_create_fifo(s);
504                 safe_close(fd);
505         }
506
507         if (realtime)
508                 timestamp_deserialize(realtime, &s->timestamp.realtime);
509         if (monotonic)
510                 timestamp_deserialize(monotonic, &s->timestamp.monotonic);
511
512         if (active) {
513                 k = parse_boolean(active);
514                 if (k >= 0)
515                         s->was_active = k;
516         }
517
518         if (controller) {
519                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
520                         session_set_controller(s, controller, false, false);
521                         session_load_devices(s, devices);
522                 } else
523                         session_restore_vt(s);
524         }
525
526         return r;
527 }
528
529 int session_activate(Session *s) {
530         unsigned int num_pending;
531
532         assert(s);
533         assert(s->user);
534
535         if (!s->seat)
536                 return -EOPNOTSUPP;
537
538         if (s->seat->active == s)
539                 return 0;
540
541         /* on seats with VTs, we let VTs manage session-switching */
542         if (seat_has_vts(s->seat)) {
543                 if (!s->vtnr)
544                         return -EOPNOTSUPP;
545
546                 return chvt(s->vtnr);
547         }
548
549         /* On seats without VTs, we implement session-switching in logind. We
550          * try to pause all session-devices and wait until the session
551          * controller acknowledged them. Once all devices are asleep, we simply
552          * switch the active session and be done.
553          * We save the session we want to switch to in seat->pending_switch and
554          * seat_complete_switch() will perform the final switch. */
555
556         s->seat->pending_switch = s;
557
558         /* if no devices are running, immediately perform the session switch */
559         num_pending = session_device_try_pause_all(s);
560         if (!num_pending)
561                 seat_complete_switch(s->seat);
562
563         return 0;
564 }
565
566 #if 0 /// UNNEEDED by elogind
567 static int session_start_scope(Session *s) {
568         int r;
569
570         assert(s);
571         assert(s->user);
572
573         if (!s->scope) {
574                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
575                 char *scope, *job = NULL;
576                 const char *description;
577
578                 scope = strjoin("session-", s->id, ".scope");
579                 if (!scope)
580                         return log_oom();
581
582                 description = strjoina("Session ", s->id, " of user ", s->user->name);
583
584                 r = manager_start_scope(
585                                 s->manager,
586                                 scope,
587                                 s->leader,
588                                 s->user->slice,
589                                 description,
590                                 "systemd-logind.service",
591                                 "systemd-user-sessions.service",
592                                 (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
593                                 &error,
594                                 &job);
595                 if (r < 0) {
596                         log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
597                         free(scope);
598                         return r;
599                 } else {
600                         s->scope = scope;
601
602                         free(s->scope_job);
603                         s->scope_job = job;
604                 }
605         }
606
607         if (s->scope)
608                 (void) hashmap_put(s->manager->session_units, s->scope, s);
609
610         return 0;
611 }
612 #else
613 static int session_start_cgroup(Session *s) {
614         int r;
615
616         assert(s);
617         assert(s->user);
618         assert(s->leader > 0);
619
620         /* First, create our own group */
621         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, s->id);
622         if (r < 0)
623                 return log_error_errno(r, "Failed to create cgroup %s: %m", s->id);
624
625         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, s->id, s->leader);
626         if (r < 0)
627                 log_warning_errno(r, "Failed to attach PID %d to cgroup %s: %m", s->leader, s->id);
628
629         return 0;
630 }
631 #endif // 0
632
633 int session_start(Session *s) {
634         int r;
635
636         assert(s);
637
638         if (!s->user)
639                 return -ESTALE;
640
641         if (s->started)
642                 return 0;
643
644         r = user_start(s->user);
645         if (r < 0)
646                 return r;
647
648         /* Create cgroup */
649 #if 0 /// elogind does its own session management
650         r = session_start_scope(s);
651 #else
652         r = session_start_cgroup(s);
653 #endif // 0
654         if (r < 0)
655                 return r;
656
657         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
658                    "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
659                    "SESSION_ID=%s", s->id,
660                    "USER_ID=%s", s->user->name,
661                    "LEADER="PID_FMT, s->leader,
662                    LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name),
663                    NULL);
664
665         if (!dual_timestamp_is_set(&s->timestamp))
666                 dual_timestamp_get(&s->timestamp);
667
668         if (s->seat)
669                 seat_read_active_vt(s->seat);
670
671         s->started = true;
672
673         user_elect_display(s->user);
674
675         /* Save data */
676         session_save(s);
677         user_save(s->user);
678         if (s->seat)
679                 seat_save(s->seat);
680
681         /* Send signals */
682         session_send_signal(s, true);
683         user_send_changed(s->user, "Display", NULL);
684         if (s->seat) {
685                 if (s->seat->active == s)
686                         seat_send_changed(s->seat, "ActiveSession", NULL);
687         }
688
689         return 0;
690 }
691
692 #if 0 /// UNNEEDED by elogind
693 static int session_stop_scope(Session *s, bool force) {
694         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
695         int r;
696
697         assert(s);
698
699         if (!s->scope)
700                 return 0;
701
702         /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
703          * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
704          * when killing any processes left after this point. */
705         r = manager_abandon_scope(s->manager, s->scope, &error);
706         if (r < 0)
707                 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
708
709         /* Optionally, let's kill everything that's left now. */
710         if (force || manager_shall_kill(s->manager, s->user->name)) {
711                 char *job = NULL;
712
713                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
714                 if (r < 0)
715                         return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
716
717                 free(s->scope_job);
718                 s->scope_job = job;
719         } else
720                 s->scope_job = mfree(s->scope_job);
721
722         return 0;
723 }
724 #else
725 static int session_stop_cgroup(Session *s, bool force) {
726         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
727         int r;
728
729         assert(s);
730
731         if (force || manager_shall_kill(s->manager, s->user->name)) {
732                 r = session_kill(s, KILL_ALL, SIGTERM);
733                 if (r < 0)
734                         return r;
735         }
736
737         return 0;
738 }
739 #endif // 0
740
741 int session_stop(Session *s, bool force) {
742         int r;
743
744         assert(s);
745
746         if (!s->user)
747                 return -ESTALE;
748
749         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
750
751         if (s->seat)
752                 seat_evict_position(s->seat, s);
753
754         /* We are going down, don't care about FIFOs anymore */
755         session_remove_fifo(s);
756
757         /* Kill cgroup */
758 #if 0 /// elogind does not start scopes, but sessions
759         r = session_stop_scope(s, force);
760 #else
761         r = session_stop_cgroup(s, force);
762 #endif // 0
763
764         s->stopping = true;
765
766         user_elect_display(s->user);
767
768         session_save(s);
769         user_save(s->user);
770
771 #if 1 /// elogind must queue this session again
772         session_add_to_gc_queue(s);
773 #endif // 1
774
775         return r;
776 }
777
778 int session_finalize(Session *s) {
779         SessionDevice *sd;
780
781         assert(s);
782
783         if (!s->user)
784                 return -ESTALE;
785
786         if (s->started)
787                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
788                            "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
789                            "SESSION_ID=%s", s->id,
790                            "USER_ID=%s", s->user->name,
791                            "LEADER="PID_FMT, s->leader,
792                            LOG_MESSAGE("Removed session %s.", s->id),
793                            NULL);
794
795         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
796
797         if (s->seat)
798                 seat_evict_position(s->seat, s);
799
800         /* Kill session devices */
801         while ((sd = hashmap_first(s->devices)))
802                 session_device_free(sd);
803
804         (void) unlink(s->state_file);
805         session_add_to_gc_queue(s);
806         user_add_to_gc_queue(s->user);
807
808         if (s->started) {
809                 session_send_signal(s, false);
810                 s->started = false;
811         }
812
813         if (s->seat) {
814                 if (s->seat->active == s)
815                         seat_set_active(s->seat, NULL);
816
817                 seat_save(s->seat);
818         }
819
820         user_save(s->user);
821         user_send_changed(s->user, "Display", NULL);
822
823         return 0;
824 }
825
826 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
827         Session *s = userdata;
828
829         assert(es);
830         assert(s);
831
832         session_stop(s, false);
833         return 0;
834 }
835
836 int session_release(Session *s) {
837         assert(s);
838
839         if (!s->started || s->stopping)
840                 return 0;
841
842         if (s->timer_event_source)
843                 return 0;
844
845         return sd_event_add_time(s->manager->event,
846                                  &s->timer_event_source,
847                                  CLOCK_MONOTONIC,
848                                  now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
849                                  release_timeout_callback, s);
850 }
851
852 bool session_is_active(Session *s) {
853         assert(s);
854
855         if (!s->seat)
856                 return true;
857
858         return s->seat->active == s;
859 }
860
861 static int get_tty_atime(const char *tty, usec_t *atime) {
862         _cleanup_free_ char *p = NULL;
863         struct stat st;
864
865         assert(tty);
866         assert(atime);
867
868         if (!path_is_absolute(tty)) {
869                 p = strappend("/dev/", tty);
870                 if (!p)
871                         return -ENOMEM;
872
873                 tty = p;
874         } else if (!path_startswith(tty, "/dev/"))
875                 return -ENOENT;
876
877         if (lstat(tty, &st) < 0)
878                 return -errno;
879
880         *atime = timespec_load(&st.st_atim);
881         return 0;
882 }
883
884 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
885         _cleanup_free_ char *p = NULL;
886         int r;
887
888         assert(pid > 0);
889         assert(atime);
890
891         r = get_ctty(pid, NULL, &p);
892         if (r < 0)
893                 return r;
894
895         return get_tty_atime(p, atime);
896 }
897
898 int session_get_idle_hint(Session *s, dual_timestamp *t) {
899         usec_t atime = 0, n;
900         int r;
901
902         assert(s);
903
904         /* Explicit idle hint is set */
905         if (s->idle_hint) {
906                 if (t)
907                         *t = s->idle_hint_timestamp;
908
909                 return s->idle_hint;
910         }
911
912         /* Graphical sessions should really implement a real
913          * idle hint logic */
914         if (SESSION_TYPE_IS_GRAPHICAL(s->type))
915                 goto dont_know;
916
917         /* For sessions with an explicitly configured tty, let's check
918          * its atime */
919         if (s->tty) {
920                 r = get_tty_atime(s->tty, &atime);
921                 if (r >= 0)
922                         goto found_atime;
923         }
924
925         /* For sessions with a leader but no explicitly configured
926          * tty, let's check the controlling tty of the leader */
927         if (s->leader > 0) {
928                 r = get_process_ctty_atime(s->leader, &atime);
929                 if (r >= 0)
930                         goto found_atime;
931         }
932
933 dont_know:
934         if (t)
935                 *t = s->idle_hint_timestamp;
936
937         return 0;
938
939 found_atime:
940         if (t)
941                 dual_timestamp_from_realtime(t, atime);
942
943         n = now(CLOCK_REALTIME);
944
945         if (s->manager->idle_action_usec <= 0)
946                 return 0;
947
948         return atime + s->manager->idle_action_usec <= n;
949 }
950
951 void session_set_idle_hint(Session *s, bool b) {
952         assert(s);
953
954         if (s->idle_hint == b)
955                 return;
956
957         s->idle_hint = b;
958         dual_timestamp_get(&s->idle_hint_timestamp);
959
960         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
961
962         if (s->seat)
963                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
964
965         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
966         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
967 }
968
969 int session_get_locked_hint(Session *s) {
970         assert(s);
971
972         return s->locked_hint;
973 }
974
975 void session_set_locked_hint(Session *s, bool b) {
976         assert(s);
977
978         if (s->locked_hint == b)
979                 return;
980
981         s->locked_hint = b;
982
983         session_send_changed(s, "LockedHint", NULL);
984 }
985
986 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
987         Session *s = userdata;
988
989         assert(s);
990         assert(s->fifo_fd == fd);
991
992         /* EOF on the FIFO means the session died abnormally. */
993
994         session_remove_fifo(s);
995         session_stop(s, false);
996
997         return 1;
998 }
999
1000 int session_create_fifo(Session *s) {
1001         int r;
1002
1003         assert(s);
1004
1005         /* Create FIFO */
1006         if (!s->fifo_path) {
1007                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
1008                 if (r < 0)
1009                         return r;
1010
1011                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
1012                         return -ENOMEM;
1013
1014                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1015                         return -errno;
1016         }
1017
1018         /* Open reading side */
1019         if (s->fifo_fd < 0) {
1020                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
1021                 if (s->fifo_fd < 0)
1022                         return -errno;
1023
1024         }
1025
1026         if (!s->fifo_event_source) {
1027                 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
1028                 if (r < 0)
1029                         return r;
1030
1031                 /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
1032                  * sessions). */
1033                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
1034                 if (r < 0)
1035                         return r;
1036         }
1037
1038         /* Open writing side */
1039         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
1040         if (r < 0)
1041                 return -errno;
1042
1043         return r;
1044 }
1045
1046 static void session_remove_fifo(Session *s) {
1047         assert(s);
1048
1049         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1050         s->fifo_fd = safe_close(s->fifo_fd);
1051
1052         if (s->fifo_path) {
1053                 unlink(s->fifo_path);
1054                 s->fifo_path = mfree(s->fifo_path);
1055         }
1056 }
1057
1058 bool session_check_gc(Session *s, bool drop_not_started) {
1059         assert(s);
1060
1061         if (drop_not_started && !s->started)
1062                 return false;
1063
1064         if (!s->user)
1065                 return false;
1066
1067         if (s->fifo_fd >= 0) {
1068                 if (pipe_eof(s->fifo_fd) <= 0)
1069                         return true;
1070         }
1071
1072 #if 0 /// elogind supports neither scopes nor jobs
1073         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
1074                 return true;
1075
1076         if (s->scope && manager_unit_is_active(s->manager, s->scope))
1077                 return true;
1078 #endif // 0
1079
1080         return false;
1081 }
1082
1083 void session_add_to_gc_queue(Session *s) {
1084         assert(s);
1085
1086         if (s->in_gc_queue)
1087                 return;
1088
1089         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1090         s->in_gc_queue = true;
1091 }
1092
1093 SessionState session_get_state(Session *s) {
1094         assert(s);
1095
1096         /* always check closing first */
1097         if (s->stopping || s->timer_event_source)
1098                 return SESSION_CLOSING;
1099
1100 #if 0 /// elogind does not support systemd scope_jobs
1101         if (s->scope_job || s->fifo_fd < 0)
1102 #else
1103         if (s->fifo_fd < 0)
1104 #endif // 0
1105                 return SESSION_OPENING;
1106
1107         if (session_is_active(s))
1108                 return SESSION_ACTIVE;
1109
1110         return SESSION_ONLINE;
1111 }
1112
1113 int session_kill(Session *s, KillWho who, int signo) {
1114         assert(s);
1115
1116 #if 0 /// Without direct cgroup support, elogind can not kill sessions
1117         if (!s->scope)
1118                 return -ESRCH;
1119
1120         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
1121 #else
1122         if (who == KILL_LEADER) {
1123                 if (s->leader <= 0)
1124                         return -ESRCH;
1125
1126                 /* FIXME: verify that leader is in cgroup?  */
1127
1128                 if (kill(s->leader, signo) < 0) {
1129                         return log_error_errno(errno, "Failed to kill process leader %d for session %s: %m", s->leader, s->id);
1130                 }
1131                 return 0;
1132         } else
1133                 return cg_kill_recursive (SYSTEMD_CGROUP_CONTROLLER, s->id, signo,
1134                                           CGROUP_IGNORE_SELF | CGROUP_REMOVE,
1135                                           NULL, NULL, NULL);
1136 #endif // 0
1137 }
1138
1139 static int session_open_vt(Session *s) {
1140         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1141
1142         if (s->vtnr < 1)
1143                 return -ENODEV;
1144
1145         if (s->vtfd >= 0)
1146                 return s->vtfd;
1147
1148         sprintf(path, "/dev/tty%u", s->vtnr);
1149         s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1150         if (s->vtfd < 0)
1151                 return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id);
1152
1153         return s->vtfd;
1154 }
1155
1156 int session_prepare_vt(Session *s) {
1157         int vt, r;
1158         struct vt_mode mode = { 0 };
1159
1160         if (s->vtnr < 1)
1161                 return 0;
1162
1163         vt = session_open_vt(s);
1164         if (vt < 0)
1165                 return vt;
1166
1167         r = fchown(vt, s->user->uid, -1);
1168         if (r < 0) {
1169                 r = log_error_errno(errno,
1170                                     "Cannot change owner of /dev/tty%u: %m",
1171                                     s->vtnr);
1172                 goto error;
1173         }
1174
1175         r = ioctl(vt, KDSKBMODE, K_OFF);
1176         if (r < 0) {
1177                 r = log_error_errno(errno,
1178                                     "Cannot set K_OFF on /dev/tty%u: %m",
1179                                     s->vtnr);
1180                 goto error;
1181         }
1182
1183         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1184         if (r < 0) {
1185                 r = log_error_errno(errno,
1186                                     "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1187                                     s->vtnr);
1188                 goto error;
1189         }
1190
1191         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1192          * So we need a dummy handler here which just acknowledges *all* VT
1193          * switch requests. */
1194         mode.mode = VT_PROCESS;
1195         mode.relsig = SIGRTMIN;
1196         mode.acqsig = SIGRTMIN + 1;
1197         r = ioctl(vt, VT_SETMODE, &mode);
1198         if (r < 0) {
1199                 r = log_error_errno(errno,
1200                                     "Cannot set VT_PROCESS on /dev/tty%u: %m",
1201                                     s->vtnr);
1202                 goto error;
1203         }
1204
1205         return 0;
1206
1207 error:
1208         session_restore_vt(s);
1209         return r;
1210 }
1211
1212 void session_restore_vt(Session *s) {
1213
1214         static const struct vt_mode mode = {
1215                 .mode = VT_AUTO,
1216         };
1217
1218         _cleanup_free_ char *utf8 = NULL;
1219         int vt, kb, old_fd;
1220
1221         /* We need to get a fresh handle to the virtual terminal,
1222          * since the old file-descriptor is potentially in a hung-up
1223          * state after the controlling process exited; we do a
1224          * little dance to avoid having the terminal be available
1225          * for reuse before we've cleaned it up.
1226          */
1227         old_fd = s->vtfd;
1228         s->vtfd = -1;
1229
1230         vt = session_open_vt(s);
1231         safe_close(old_fd);
1232
1233         if (vt < 0)
1234                 return;
1235
1236         (void) ioctl(vt, KDSETMODE, KD_TEXT);
1237
1238         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1239                 kb = K_UNICODE;
1240         else
1241                 kb = K_XLATE;
1242
1243         (void) ioctl(vt, KDSKBMODE, kb);
1244
1245         (void) ioctl(vt, VT_SETMODE, &mode);
1246         (void) fchown(vt, 0, (gid_t) -1);
1247
1248         s->vtfd = safe_close(s->vtfd);
1249 }
1250
1251 void session_leave_vt(Session *s) {
1252         int r;
1253
1254         assert(s);
1255
1256         /* This is called whenever we get a VT-switch signal from the kernel.
1257          * We acknowledge all of them unconditionally. Note that session are
1258          * free to overwrite those handlers and we only register them for
1259          * sessions with controllers. Legacy sessions are not affected.
1260          * However, if we switch from a non-legacy to a legacy session, we must
1261          * make sure to pause all device before acknowledging the switch. We
1262          * process the real switch only after we are notified via sysfs, so the
1263          * legacy session might have already started using the devices. If we
1264          * don't pause the devices before the switch, we might confuse the
1265          * session we switch to. */
1266
1267         if (s->vtfd < 0)
1268                 return;
1269
1270         session_device_pause_all(s);
1271         r = ioctl(s->vtfd, VT_RELDISP, 1);
1272         if (r < 0)
1273                 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
1274 }
1275
1276 bool session_is_controller(Session *s, const char *sender) {
1277         assert(s);
1278
1279         return streq_ptr(s->controller, sender);
1280 }
1281
1282 static void session_release_controller(Session *s, bool notify) {
1283         _cleanup_free_ char *name = NULL;
1284         SessionDevice *sd;
1285
1286         if (!s->controller)
1287                 return;
1288
1289         name = s->controller;
1290
1291         /* By resetting the controller before releasing the devices, we won't
1292          * send notification signals. This avoids sending useless notifications
1293          * if the controller is released on disconnects. */
1294         if (!notify)
1295                 s->controller = NULL;
1296
1297         while ((sd = hashmap_first(s->devices)))
1298                 session_device_free(sd);
1299
1300         s->controller = NULL;
1301         s->track = sd_bus_track_unref(s->track);
1302 }
1303
1304 static int on_bus_track(sd_bus_track *track, void *userdata) {
1305         Session *s = userdata;
1306
1307         assert(track);
1308         assert(s);
1309
1310         session_drop_controller(s);
1311
1312         return 0;
1313 }
1314
1315 int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1316         _cleanup_free_ char *name = NULL;
1317         int r;
1318
1319         assert(s);
1320         assert(sender);
1321
1322         if (session_is_controller(s, sender))
1323                 return 0;
1324         if (s->controller && !force)
1325                 return -EBUSY;
1326
1327         name = strdup(sender);
1328         if (!name)
1329                 return -ENOMEM;
1330
1331         s->track = sd_bus_track_unref(s->track);
1332         r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1333         if (r < 0)
1334                 return r;
1335
1336         r = sd_bus_track_add_name(s->track, name);
1337         if (r < 0)
1338                 return r;
1339
1340         /* When setting a session controller, we forcibly mute the VT and set
1341          * it into graphics-mode. Applications can override that by changing
1342          * VT state after calling TakeControl(). However, this serves as a good
1343          * default and well-behaving controllers can now ignore VTs entirely.
1344          * Note that we reset the VT on ReleaseControl() and if the controller
1345          * exits.
1346          * If logind crashes/restarts, we restore the controller during restart
1347          * (without preparing the VT since the controller has probably overridden
1348          * VT state by now) or reset the VT in case it crashed/exited, too. */
1349         if (prepare) {
1350                 r = session_prepare_vt(s);
1351                 if (r < 0) {
1352                         s->track = sd_bus_track_unref(s->track);
1353                         return r;
1354                 }
1355         }
1356
1357         session_release_controller(s, true);
1358         s->controller = name;
1359         name = NULL;
1360         session_save(s);
1361
1362         return 0;
1363 }
1364
1365 void session_drop_controller(Session *s) {
1366         assert(s);
1367
1368         if (!s->controller)
1369                 return;
1370
1371         s->track = sd_bus_track_unref(s->track);
1372         session_release_controller(s, false);
1373         session_save(s);
1374         session_restore_vt(s);
1375 }
1376
1377 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1378         [SESSION_OPENING] = "opening",
1379         [SESSION_ONLINE] = "online",
1380         [SESSION_ACTIVE] = "active",
1381         [SESSION_CLOSING] = "closing"
1382 };
1383
1384 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1385
1386 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1387         [SESSION_UNSPECIFIED] = "unspecified",
1388         [SESSION_TTY] = "tty",
1389         [SESSION_X11] = "x11",
1390         [SESSION_WAYLAND] = "wayland",
1391         [SESSION_MIR] = "mir",
1392         [SESSION_WEB] = "web",
1393 };
1394
1395 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1396
1397 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1398         [SESSION_USER] = "user",
1399         [SESSION_GREETER] = "greeter",
1400         [SESSION_LOCK_SCREEN] = "lock-screen",
1401         [SESSION_BACKGROUND] = "background"
1402 };
1403
1404 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1405
1406 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1407         [KILL_LEADER] = "leader",
1408         [KILL_ALL] = "all"
1409 };
1410
1411 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);