chiark / gitweb /
124fea138105c3bc20dffe02705c9a3c1ee5af1f
[elogind.git] / src / login / logind.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   Copyright 2011 Lennart Poettering
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #if 0 /// elogind needs the systems udev header
12 #include "libudev.h"
13 #else
14 #include <libudev.h>
15 #endif // 0
16 #include "sd-daemon.h"
17
18 #include "alloc-util.h"
19 #include "bus-error.h"
20 #include "bus-util.h"
21 //#include "cgroup-util.h"
22 #include "def.h"
23 #include "dirent-util.h"
24 #include "fd-util.h"
25 #include "format-util.h"
26 #include "fs-util.h"
27 #include "logind.h"
28 //#include "parse-util.h"
29 //#include "process-util.h"
30 #include "selinux-util.h"
31 #include "signal-util.h"
32 #include "strv.h"
33 #include "udev-util.h"
34 /// Additional includes needed by elogind
35 #include "cgroup.h"       // From src/core/
36 #include "elogind.h"
37 #include "label.h"
38 #include "musl_missing.h"
39 #include "process-util.h"
40 #include "cgroup-util.h"
41
42 static Manager* manager_unref(Manager *m);
43 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
44
45 #if 0 /// elogind does not support autospawning of vts
46 #endif // 0
47 static int manager_new(Manager **ret) {
48         _cleanup_(manager_unrefp) Manager *m = NULL;
49         int r;
50
51         assert(ret);
52
53         m = new0(Manager, 1);
54         if (!m)
55                 return -ENOMEM;
56
57         m->console_active_fd = -1;
58 #if 0 /// UNNEEDED by elogind
59         m->reserve_vt_fd = -1;
60 #endif // 0
61
62         m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
63
64         m->devices = hashmap_new(&string_hash_ops);
65         m->seats = hashmap_new(&string_hash_ops);
66         m->sessions = hashmap_new(&string_hash_ops);
67         m->users = hashmap_new(NULL);
68         m->inhibitors = hashmap_new(&string_hash_ops);
69         m->buttons = hashmap_new(&string_hash_ops);
70
71         m->user_units = hashmap_new(&string_hash_ops);
72         m->session_units = hashmap_new(&string_hash_ops);
73
74         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
75                 return -ENOMEM;
76
77 #if 1 /// elogind needs some more data
78         r = elogind_manager_new(m);
79         if (r < 0)
80                 goto fail;
81 #endif // 1
82         m->udev = udev_new();
83         if (!m->udev)
84                 return -errno;
85
86         r = sd_event_default(&m->event);
87         if (r < 0)
88                 return r;
89
90         r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
91         if (r < 0)
92                 return r;
93
94         r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
95         if (r < 0)
96                 return r;
97
98         (void) sd_event_set_watchdog(m->event, true);
99
100         manager_reset_config(m);
101
102         *ret = TAKE_PTR(m);
103         return 0;
104 }
105
106 static Manager* manager_unref(Manager *m) {
107         Session *session;
108         User *u;
109         Device *d;
110         Seat *s;
111         Inhibitor *i;
112         Button *b;
113
114         if (!m)
115                 return NULL;
116
117         while ((session = hashmap_first(m->sessions)))
118                 session_free(session);
119
120         while ((u = hashmap_first(m->users)))
121                 user_free(u);
122
123         while ((d = hashmap_first(m->devices)))
124                 device_free(d);
125
126         while ((s = hashmap_first(m->seats)))
127                 seat_free(s);
128
129         while ((i = hashmap_first(m->inhibitors)))
130                 inhibitor_free(i);
131
132         while ((b = hashmap_first(m->buttons)))
133                 button_free(b);
134
135         hashmap_free(m->devices);
136         hashmap_free(m->seats);
137         hashmap_free(m->sessions);
138         hashmap_free(m->users);
139         hashmap_free(m->inhibitors);
140         hashmap_free(m->buttons);
141
142         hashmap_free(m->user_units);
143         hashmap_free(m->session_units);
144
145         sd_event_source_unref(m->idle_action_event_source);
146         sd_event_source_unref(m->inhibit_timeout_source);
147         sd_event_source_unref(m->scheduled_shutdown_timeout_source);
148         sd_event_source_unref(m->nologin_timeout_source);
149         sd_event_source_unref(m->wall_message_timeout_source);
150
151         sd_event_source_unref(m->console_active_event_source);
152         sd_event_source_unref(m->udev_seat_event_source);
153         sd_event_source_unref(m->udev_device_event_source);
154         sd_event_source_unref(m->udev_vcsa_event_source);
155         sd_event_source_unref(m->udev_button_event_source);
156         sd_event_source_unref(m->lid_switch_ignore_event_source);
157
158         safe_close(m->console_active_fd);
159
160         udev_monitor_unref(m->udev_seat_monitor);
161         udev_monitor_unref(m->udev_device_monitor);
162         udev_monitor_unref(m->udev_vcsa_monitor);
163         udev_monitor_unref(m->udev_button_monitor);
164
165         udev_unref(m->udev);
166
167         if (m->unlink_nologin)
168                 (void) unlink_or_warn("/run/nologin");
169
170         bus_verify_polkit_async_registry_free(m->polkit_registry);
171
172         sd_bus_unref(m->bus);
173         sd_event_unref(m->event);
174
175 #if 0 /// elogind does not support autospawning of vts
176         safe_close(m->reserve_vt_fd);
177 #endif // 0
178 #if 1 /// elogind has to free its own data
179         elogind_manager_free(m);
180 #endif // 1
181
182         strv_free(m->kill_only_users);
183         strv_free(m->kill_exclude_users);
184
185         free(m->scheduled_shutdown_type);
186         free(m->scheduled_shutdown_tty);
187         free(m->wall_message);
188 #if 0 /// UNNEEDED by elogind
189         free(m->action_job);
190 #endif // 0
191
192         return mfree(m);
193 }
194
195 static int manager_enumerate_devices(Manager *m) {
196         struct udev_list_entry *item = NULL, *first = NULL;
197         _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
198         int r;
199
200         assert(m);
201
202         /* Loads devices from udev and creates seats for them as
203          * necessary */
204
205         e = udev_enumerate_new(m->udev);
206         if (!e)
207                 return -ENOMEM;
208
209         r = udev_enumerate_add_match_tag(e, "master-of-seat");
210         if (r < 0)
211                 return r;
212
213         r = udev_enumerate_add_match_is_initialized(e);
214         if (r < 0)
215                 return r;
216
217         r = udev_enumerate_scan_devices(e);
218         if (r < 0)
219                 return r;
220
221         first = udev_enumerate_get_list_entry(e);
222         udev_list_entry_foreach(item, first) {
223                 _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
224                 int k;
225
226                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
227                 if (!d)
228                         return -ENOMEM;
229
230                 k = manager_process_seat_device(m, d);
231                 if (k < 0)
232                         r = k;
233         }
234
235         return r;
236 }
237
238 static int manager_enumerate_buttons(Manager *m) {
239         _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
240         struct udev_list_entry *item = NULL, *first = NULL;
241         int r;
242
243         assert(m);
244
245         /* Loads buttons from udev */
246
247         if (manager_all_buttons_ignored(m))
248                 return 0;
249
250         e = udev_enumerate_new(m->udev);
251         if (!e)
252                 return -ENOMEM;
253
254         r = udev_enumerate_add_match_subsystem(e, "input");
255         if (r < 0)
256                 return r;
257
258         r = udev_enumerate_add_match_tag(e, "power-switch");
259         if (r < 0)
260                 return r;
261
262         r = udev_enumerate_add_match_is_initialized(e);
263         if (r < 0)
264                 return r;
265
266         r = udev_enumerate_scan_devices(e);
267         if (r < 0)
268                 return r;
269
270         first = udev_enumerate_get_list_entry(e);
271         udev_list_entry_foreach(item, first) {
272                 _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
273                 int k;
274
275                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
276                 if (!d)
277                         return -ENOMEM;
278
279                 k = manager_process_button_device(m, d);
280                 if (k < 0)
281                         r = k;
282         }
283
284         return r;
285 }
286
287 static int manager_enumerate_seats(Manager *m) {
288         _cleanup_closedir_ DIR *d = NULL;
289         struct dirent *de;
290         int r = 0;
291
292         assert(m);
293
294         /* This loads data about seats stored on disk, but does not
295          * actually create any seats. Removes data of seats that no
296          * longer exist. */
297
298         d = opendir("/run/systemd/seats");
299         if (!d) {
300                 if (errno == ENOENT)
301                         return 0;
302
303                 return log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
304         }
305
306         FOREACH_DIRENT(de, d, return -errno) {
307                 Seat *s;
308                 int k;
309
310                 if (!dirent_is_file(de))
311                         continue;
312
313                 s = hashmap_get(m->seats, de->d_name);
314                 if (!s) {
315                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
316                                 log_warning("Failed to remove /run/systemd/seats/%s: %m",
317                                             de->d_name);
318                         continue;
319                 }
320
321                 k = seat_load(s);
322                 if (k < 0)
323                         r = k;
324         }
325
326         return r;
327 }
328
329 static int manager_enumerate_linger_users(Manager *m) {
330         _cleanup_closedir_ DIR *d = NULL;
331         struct dirent *de;
332         int r = 0;
333
334         assert(m);
335
336         d = opendir("/var/lib/elogind/linger");
337         if (!d) {
338                 if (errno == ENOENT)
339                         return 0;
340
341                 return log_error_errno(errno, "Failed to open /var/lib/elogind/linger/: %m");
342         }
343
344         FOREACH_DIRENT(de, d, return -errno) {
345                 int k;
346
347                 if (!dirent_is_file(de))
348                         continue;
349
350                 k = manager_add_user_by_name(m, de->d_name, NULL);
351                 if (k < 0) {
352                         log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
353                         r = k;
354                 }
355         }
356
357         return r;
358 }
359
360 static int manager_enumerate_users(Manager *m) {
361         _cleanup_closedir_ DIR *d = NULL;
362         struct dirent *de;
363         int r, k;
364
365         assert(m);
366
367         /* Add lingering users */
368         r = manager_enumerate_linger_users(m);
369
370         /* Read in user data stored on disk */
371         d = opendir("/run/systemd/users");
372         if (!d) {
373                 if (errno == ENOENT)
374                         return 0;
375
376                 return log_error_errno(errno, "Failed to open /run/systemd/users: %m");
377         }
378
379         FOREACH_DIRENT(de, d, return -errno) {
380                 User *u;
381
382                 if (!dirent_is_file(de))
383                         continue;
384
385                 k = manager_add_user_by_name(m, de->d_name, &u);
386                 if (k < 0) {
387                         log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
388
389                         r = k;
390                         continue;
391                 }
392
393                 user_add_to_gc_queue(u);
394
395                 k = user_load(u);
396                 if (k < 0)
397                         r = k;
398         }
399
400         return r;
401 }
402
403 static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
404         _cleanup_strv_free_ char **parts = NULL;
405         _cleanup_free_ char *id = NULL;
406         unsigned int major, minor;
407         int r;
408
409         parts = strv_split(fdname, "-");
410         if (!parts)
411                 return -ENOMEM;
412         if (strv_length(parts) != 5)
413                 return -EINVAL;
414
415         if (!streq(parts[0], "session"))
416                 return -EINVAL;
417
418         id = strdup(parts[1]);
419         if (!id)
420                 return -ENOMEM;
421
422         if (!streq(parts[2], "device"))
423                 return -EINVAL;
424
425         r = safe_atou(parts[3], &major);
426         if (r < 0)
427                 return r;
428         r = safe_atou(parts[4], &minor);
429         if (r < 0)
430                 return r;
431
432         *dev = makedev(major, minor);
433         *session_id = TAKE_PTR(id);
434
435         return 0;
436 }
437
438 static int manager_attach_fds(Manager *m) {
439         _cleanup_strv_free_ char **fdnames = NULL;
440         int n, i, fd;
441
442         /* Upon restart, PID1 will send us back all fds of session devices
443          * that we previously opened. Each file descriptor is associated
444          * with a given session. The session ids are passed through FDNAMES. */
445
446         n = sd_listen_fds_with_names(true, &fdnames);
447         if (n <= 0)
448                 return n;
449
450         for (i = 0; i < n; i++) {
451                 _cleanup_free_ char *id = NULL;
452                 dev_t dev;
453                 struct stat st;
454                 SessionDevice *sd;
455                 Session *s;
456                 int r;
457
458                 fd = SD_LISTEN_FDS_START + i;
459
460                 r = parse_fdname(fdnames[i], &id, &dev);
461                 if (r < 0) {
462                         log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
463                         close_nointr(fd);
464                         continue;
465                 }
466
467                 s = hashmap_get(m->sessions, id);
468                 if (!s) {
469                         /* If the session doesn't exist anymore, the associated session
470                          * device attached to this fd doesn't either. Let's simply close
471                          * this fd. */
472                         log_debug("Failed to attach fd for unknown session: %s", id);
473                         close_nointr(fd);
474                         continue;
475                 }
476
477                 if (fstat(fd, &st) < 0) {
478                         /* The device is allowed to go away at a random point, in which
479                          * case fstat failing is expected. */
480                         log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
481                         close_nointr(fd);
482                         continue;
483                 }
484
485                 if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
486                         log_debug("Device fd doesn't point to the expected character device node");
487                         close_nointr(fd);
488                         continue;
489                 }
490
491                 sd = hashmap_get(s->devices, &dev);
492                 if (!sd) {
493                         /* Weird, we got an fd for a session device which wasn't
494                          * recorded in the session state file... */
495                         log_warning("Got fd for missing session device [%u:%u] in session %s",
496                                     major(dev), minor(dev), s->id);
497                         close_nointr(fd);
498                         continue;
499                 }
500
501                 log_debug("Attaching fd to session device [%u:%u] for session %s",
502                           major(dev), minor(dev), s->id);
503
504                 session_device_attach_fd(sd, fd, s->was_active);
505         }
506
507         return 0;
508 }
509
510 static int manager_enumerate_sessions(Manager *m) {
511         _cleanup_closedir_ DIR *d = NULL;
512         struct dirent *de;
513         int r = 0, k;
514
515         assert(m);
516
517         /* Read in session data stored on disk */
518         d = opendir("/run/systemd/sessions");
519         if (!d) {
520                 if (errno == ENOENT)
521                         return 0;
522
523                 return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
524         }
525
526         FOREACH_DIRENT(de, d, return -errno) {
527                 struct Session *s;
528
529                 if (!dirent_is_file(de))
530                         continue;
531
532                 if (!session_id_valid(de->d_name)) {
533                         log_warning("Invalid session file name '%s', ignoring.", de->d_name);
534                         r = -EINVAL;
535                         continue;
536                 }
537
538                 k = manager_add_session(m, de->d_name, &s);
539                 if (k < 0) {
540                         log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
541                         r = k;
542                         continue;
543                 }
544
545                 session_add_to_gc_queue(s);
546
547                 k = session_load(s);
548                 if (k < 0)
549                         r = k;
550         }
551
552         /* We might be restarted and PID1 could have sent us back the
553          * session device fds we previously saved. */
554         k = manager_attach_fds(m);
555         if (k < 0)
556                 log_warning_errno(k, "Failed to reattach session device fds: %m");
557
558         return r;
559 }
560
561 static int manager_enumerate_inhibitors(Manager *m) {
562         _cleanup_closedir_ DIR *d = NULL;
563         struct dirent *de;
564         int r = 0;
565
566         assert(m);
567
568         d = opendir("/run/systemd/inhibit");
569         if (!d) {
570                 if (errno == ENOENT)
571                         return 0;
572
573                 return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
574         }
575
576         FOREACH_DIRENT(de, d, return -errno) {
577                 int k;
578                 Inhibitor *i;
579
580                 if (!dirent_is_file(de))
581                         continue;
582
583                 k = manager_add_inhibitor(m, de->d_name, &i);
584                 if (k < 0) {
585                         log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
586                         r = k;
587                         continue;
588                 }
589
590                 k = inhibitor_load(i);
591                 if (k < 0)
592                         r = k;
593         }
594
595         return r;
596 }
597
598 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
599         _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
600         Manager *m = userdata;
601
602         assert(m);
603
604         d = udev_monitor_receive_device(m->udev_seat_monitor);
605         if (!d)
606                 return -ENOMEM;
607
608         manager_process_seat_device(m, d);
609         return 0;
610 }
611
612 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
613         _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
614         Manager *m = userdata;
615
616         assert(m);
617
618         d = udev_monitor_receive_device(m->udev_device_monitor);
619         if (!d)
620                 return -ENOMEM;
621
622         manager_process_seat_device(m, d);
623         return 0;
624 }
625
626 #if 0 /// UNNEEDED by elogind
627 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
628         _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
629         Manager *m = userdata;
630         const char *name;
631
632         assert(m);
633
634         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
635         if (!d)
636                 return -ENOMEM;
637
638         name = udev_device_get_sysname(d);
639
640         /* Whenever a VCSA device is removed try to reallocate our
641          * VTs, to make sure our auto VTs never go away. */
642
643         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
644                 seat_preallocate_vts(m->seat0);
645
646         return 0;
647 }
648 #endif // 0
649
650 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
651         _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
652         Manager *m = userdata;
653
654         assert(m);
655
656         d = udev_monitor_receive_device(m->udev_button_monitor);
657         if (!d)
658                 return -ENOMEM;
659
660         manager_process_button_device(m, d);
661         return 0;
662 }
663
664 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
665         Manager *m = userdata;
666
667         assert(m);
668         assert(m->seat0);
669         assert(m->console_active_fd == fd);
670
671         seat_read_active_vt(m->seat0);
672         return 0;
673 }
674
675 #if 0 /// UNNEEDED by elogind
676 static int manager_reserve_vt(Manager *m) {
677         _cleanup_free_ char *p = NULL;
678
679         assert(m);
680
681         if (m->reserve_vt <= 0)
682                 return 0;
683
684         if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
685                 return log_oom();
686
687         m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
688         if (m->reserve_vt_fd < 0) {
689
690                 /* Don't complain on VT-less systems */
691                 if (errno != ENOENT)
692                         log_warning_errno(errno, "Failed to pin reserved VT: %m");
693                 return -errno;
694         }
695
696         return 0;
697 }
698 #endif // 0
699
700 static int manager_connect_bus(Manager *m) {
701         int r;
702
703         assert(m);
704         assert(!m->bus);
705
706         r = sd_bus_default_system(&m->bus);
707         if (r < 0)
708                 return log_error_errno(r, "Failed to connect to system bus: %m");
709
710         r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
711         if (r < 0)
712                 return log_error_errno(r, "Failed to add manager object vtable: %m");
713
714         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
715         if (r < 0)
716                 return log_error_errno(r, "Failed to add seat object vtable: %m");
717
718         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
719         if (r < 0)
720                 return log_error_errno(r, "Failed to add seat enumerator: %m");
721
722         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
723         if (r < 0)
724                 return log_error_errno(r, "Failed to add session object vtable: %m");
725
726         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
727         if (r < 0)
728                 return log_error_errno(r, "Failed to add session enumerator: %m");
729
730         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
731         if (r < 0)
732                 return log_error_errno(r, "Failed to add user object vtable: %m");
733
734         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
735         if (r < 0)
736                 return log_error_errno(r, "Failed to add user enumerator: %m");
737
738 #if 0 /// elogind does not support systemd as PID 1
739         r = sd_bus_match_signal_async(
740                         m->bus,
741                         NULL,
742                         "org.freedesktop.systemd1",
743                         "/org/freedesktop/systemd1",
744                         "org.freedesktop.systemd1.Manager",
745                         "JobRemoved",
746                         match_job_removed, NULL, m);
747         if (r < 0)
748                 return log_error_errno(r, "Failed to request match for JobRemoved: %m");
749
750         r = sd_bus_match_signal_async(
751                         m->bus,
752                         NULL,
753                         "org.freedesktop.systemd1",
754                         "/org/freedesktop/systemd1",
755                         "org.freedesktop.systemd1.Manager",
756                         "UnitRemoved",
757                         match_unit_removed, NULL, m);
758         if (r < 0)
759                 return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
760
761         r = sd_bus_match_signal_async(
762                         m->bus,
763                         NULL,
764                         "org.freedesktop.systemd1",
765                         NULL,
766                         "org.freedesktop.DBus.Properties",
767                         "PropertiesChanged",
768                         match_properties_changed, NULL, m);
769         if (r < 0)
770                 return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
771
772         r = sd_bus_match_signal_async(
773                         m->bus,
774                         NULL,
775                         "org.freedesktop.systemd1",
776                         "/org/freedesktop/systemd1",
777                         "org.freedesktop.systemd1.Manager",
778                         "Reloading",
779                         match_reloading, NULL, m);
780         if (r < 0)
781                 return log_error_errno(r, "Failed to request match for Reloading: %m");
782
783         r = sd_bus_call_method_async(
784                         m->bus,
785                         NULL,
786                         "org.freedesktop.systemd1",
787                         "/org/freedesktop/systemd1",
788                         "org.freedesktop.systemd1.Manager",
789                         "Subscribe",
790                         NULL, NULL,
791                         NULL);
792 #endif // 0
793         if (r < 0)
794                 return log_error_errno(r, "Failed to enable subscription: %m");
795
796         r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
797         if (r < 0)
798                 return log_error_errno(r, "Failed to request name: %m");
799
800         r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
801         if (r < 0)
802                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
803
804 #if 0 /// elogind has to setup its release agent
805         return 0;
806 #else
807         r = elogind_setup_cgroups_agent(m);
808
809         return r;
810 #endif // 0
811 }
812
813 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
814         Manager *m = data;
815         Session *active, *iter;
816
817         /*
818          * We got a VT-switch signal and we have to acknowledge it immediately.
819          * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
820          * old user-space might run multiple sessions on a single VT, *sigh*.
821          * Therefore, we have to iterate all sessions and find one with a vtfd
822          * on the requested VT.
823          * As only VTs with active controllers have VT_PROCESS set, our current
824          * notion of the active VT might be wrong (for instance if the switch
825          * happens while we setup VT_PROCESS). Therefore, read the current VT
826          * first and then use s->active->vtnr as reference. Note that this is
827          * not racy, as no further VT-switch can happen as long as we're in
828          * synchronous VT_PROCESS mode.
829          */
830
831         assert(m->seat0);
832         seat_read_active_vt(m->seat0);
833
834         active = m->seat0->active;
835         if (!active || active->vtnr < 1) {
836                 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
837                 return 0;
838         }
839
840         if (active->vtfd >= 0) {
841                 session_leave_vt(active);
842         } else {
843                 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
844                         if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
845                                 session_leave_vt(iter);
846                                 break;
847                         }
848                 }
849         }
850
851         return 0;
852 }
853
854 static int manager_connect_console(Manager *m) {
855         int r;
856
857         assert(m);
858         assert(m->console_active_fd < 0);
859
860         /* On certain architectures (S390 and Xen, and containers),
861            /dev/tty0 does not exist, so don't fail if we can't open
862            it. */
863         if (access("/dev/tty0", F_OK) < 0)
864                 return 0;
865
866         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
867         if (m->console_active_fd < 0) {
868
869                 /* On some systems the device node /dev/tty0 may exist
870                  * even though /sys/class/tty/tty0 does not. */
871                 if (errno == ENOENT)
872                         return 0;
873
874                 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
875         }
876
877         r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
878         if (r < 0) {
879                 log_error("Failed to watch foreground console");
880                 return r;
881         }
882
883         /*
884          * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
885          * as VT-acquire signal. We ignore any acquire-events (yes, we still
886          * have to provide a valid signal-number for it!) and acknowledge all
887          * release events immediately.
888          */
889
890         if (SIGRTMIN + 1 > SIGRTMAX) {
891                 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
892                 return -EINVAL;
893         }
894
895         assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0);
896         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
897
898         r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
899         if (r < 0)
900                 return r;
901
902         return 0;
903 }
904
905 static int manager_connect_udev(Manager *m) {
906         int r;
907
908         assert(m);
909         assert(!m->udev_seat_monitor);
910         assert(!m->udev_device_monitor);
911         assert(!m->udev_vcsa_monitor);
912         assert(!m->udev_button_monitor);
913
914         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
915         if (!m->udev_seat_monitor)
916                 return -ENOMEM;
917
918         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
919         if (r < 0)
920                 return r;
921
922         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
923         if (r < 0)
924                 return r;
925
926         r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m);
927         if (r < 0)
928                 return r;
929
930         m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
931         if (!m->udev_device_monitor)
932                 return -ENOMEM;
933
934         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
935         if (r < 0)
936                 return r;
937
938         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
939         if (r < 0)
940                 return r;
941
942         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
943         if (r < 0)
944                 return r;
945
946         r = udev_monitor_enable_receiving(m->udev_device_monitor);
947         if (r < 0)
948                 return r;
949
950         r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m);
951         if (r < 0)
952                 return r;
953
954         /* Don't watch keys if nobody cares */
955         if (!manager_all_buttons_ignored(m)) {
956                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
957                 if (!m->udev_button_monitor)
958                         return -ENOMEM;
959
960                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
961                 if (r < 0)
962                         return r;
963
964                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
965                 if (r < 0)
966                         return r;
967
968                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
969                 if (r < 0)
970                         return r;
971
972                 r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m);
973                 if (r < 0)
974                         return r;
975         }
976
977         /* Don't bother watching VCSA devices, if nobody cares */
978 #if 0 /// elogind does not support autospawning of vts
979         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
980
981                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
982                 if (!m->udev_vcsa_monitor)
983                         return -ENOMEM;
984
985                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
986                 if (r < 0)
987                         return r;
988
989                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
990                 if (r < 0)
991                         return r;
992
993                 r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m);
994                 if (r < 0)
995                         return r;
996         }
997 #endif // 0
998
999         return 0;
1000 }
1001
1002 static void manager_gc(Manager *m, bool drop_not_started) {
1003         Seat *seat;
1004         Session *session;
1005         User *user;
1006
1007         assert(m);
1008
1009         while ((seat = m->seat_gc_queue)) {
1010                 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1011                 seat->in_gc_queue = false;
1012
1013                 if (seat_may_gc(seat, drop_not_started)) {
1014                         seat_stop(seat, false);
1015                         seat_free(seat);
1016                 }
1017         }
1018
1019         while ((session = m->session_gc_queue)) {
1020                 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1021                 session->in_gc_queue = false;
1022
1023                 /* First, if we are not closing yet, initiate stopping */
1024                 if (session_may_gc(session, drop_not_started) &&
1025                     session_get_state(session) != SESSION_CLOSING)
1026                         session_stop(session, false);
1027
1028                 /* Normally, this should make the session referenced
1029                  * again, if it doesn't then let's get rid of it
1030                  * immediately */
1031                 if (session_may_gc(session, drop_not_started)) {
1032                         session_finalize(session);
1033                         session_free(session);
1034                 }
1035         }
1036
1037         while ((user = m->user_gc_queue)) {
1038                 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1039                 user->in_gc_queue = false;
1040
1041                 /* First step: queue stop jobs */
1042                 if (user_may_gc(user, drop_not_started))
1043                         user_stop(user, false);
1044
1045                 /* Second step: finalize user */
1046                 if (user_may_gc(user, drop_not_started)) {
1047                         user_finalize(user);
1048                         user_free(user);
1049                 }
1050         }
1051 }
1052
1053 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1054         Manager *m = userdata;
1055         struct dual_timestamp since;
1056         usec_t n, elapse;
1057         int r;
1058
1059         assert(m);
1060
1061         if (m->idle_action == HANDLE_IGNORE ||
1062             m->idle_action_usec <= 0)
1063                 return 0;
1064
1065         n = now(CLOCK_MONOTONIC);
1066
1067         r = manager_get_idle_hint(m, &since);
1068         if (r <= 0)
1069                 /* Not idle. Let's check if after a timeout it might be idle then. */
1070                 elapse = n + m->idle_action_usec;
1071         else {
1072                 /* Idle! Let's see if it's time to do something, or if
1073                  * we shall sleep for longer. */
1074
1075                 if (n >= since.monotonic + m->idle_action_usec &&
1076                     (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1077                         log_info("System idle. Taking action.");
1078
1079                         manager_handle_action(m, 0, m->idle_action, false, false);
1080                         m->idle_action_not_before_usec = n;
1081                 }
1082
1083                 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1084         }
1085
1086         if (!m->idle_action_event_source) {
1087
1088                 r = sd_event_add_time(
1089                                 m->event,
1090                                 &m->idle_action_event_source,
1091                                 CLOCK_MONOTONIC,
1092                                 elapse, USEC_PER_SEC*30,
1093                                 manager_dispatch_idle_action, m);
1094                 if (r < 0)
1095                         return log_error_errno(r, "Failed to add idle event source: %m");
1096
1097                 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1098                 if (r < 0)
1099                         return log_error_errno(r, "Failed to set idle event source priority: %m");
1100         } else {
1101                 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1102                 if (r < 0)
1103                         return log_error_errno(r, "Failed to set idle event timer: %m");
1104
1105                 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1106                 if (r < 0)
1107                         return log_error_errno(r, "Failed to enable idle event timer: %m");
1108         }
1109
1110         return 0;
1111 }
1112
1113 #if 0 /// elogind parses its own config file
1114 #else
1115          const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1116
1117          assert(m);
1118
1119          if (!logind_conf)
1120                  logind_conf = PKGSYSCONFDIR "/logind.conf";
1121
1122          return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1123                              config_item_perf_lookup, logind_gperf_lookup,
1124 #endif // 0
1125 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1126         Manager *m = userdata;
1127         int r;
1128
1129         manager_reset_config(m);
1130         r = manager_parse_config_file(m);
1131         if (r < 0)
1132                 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1133         else
1134                 log_info("Config file reloaded.");
1135
1136 #if 1 /// elogind needs an Add-On for sleep configuration
1137         elogind_manager_reset_config(m);
1138 #endif // 1
1139         return 0;
1140 }
1141
1142 static int manager_startup(Manager *m) {
1143         int r;
1144         Seat *seat;
1145         Session *session;
1146         User *user;
1147         Button *button;
1148         Inhibitor *inhibitor;
1149         Iterator i;
1150
1151         assert(m);
1152
1153         r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1154         if (r < 0)
1155                 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1156
1157 #if 1 /// elogind needs some extra preparations before connecting...
1158         elogind_manager_startup(m);
1159 #endif // 1
1160         /* Connect to console */
1161         r = manager_connect_console(m);
1162         if (r < 0)
1163                 return r;
1164
1165         /* Connect to udev */
1166         r = manager_connect_udev(m);
1167         if (r < 0)
1168                 return log_error_errno(r, "Failed to create udev watchers: %m");
1169
1170         /* Connect to the bus */
1171         r = manager_connect_bus(m);
1172         if (r < 0)
1173                 return r;
1174
1175         /* Instantiate magic seat 0 */
1176         r = manager_add_seat(m, "seat0", &m->seat0);
1177         if (r < 0)
1178                 return log_error_errno(r, "Failed to add seat0: %m");
1179
1180         r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1181         if (r < 0)
1182                 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1183
1184         /* Deserialize state */
1185         r = manager_enumerate_devices(m);
1186         if (r < 0)
1187                 log_warning_errno(r, "Device enumeration failed: %m");
1188
1189         r = manager_enumerate_seats(m);
1190         if (r < 0)
1191                 log_warning_errno(r, "Seat enumeration failed: %m");
1192
1193         r = manager_enumerate_users(m);
1194         if (r < 0)
1195                 log_warning_errno(r, "User enumeration failed: %m");
1196
1197         r = manager_enumerate_sessions(m);
1198         if (r < 0)
1199                 log_warning_errno(r, "Session enumeration failed: %m");
1200
1201         r = manager_enumerate_inhibitors(m);
1202         if (r < 0)
1203                 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1204
1205         r = manager_enumerate_buttons(m);
1206         if (r < 0)
1207                 log_warning_errno(r, "Button enumeration failed: %m");
1208
1209         /* Remove stale objects before we start them */
1210         manager_gc(m, false);
1211
1212         /* Reserve the special reserved VT */
1213 #if 0 /// elogind does not support autospawning of vts
1214         manager_reserve_vt(m);
1215 #endif // 0
1216
1217         /* And start everything */
1218         HASHMAP_FOREACH(seat, m->seats, i)
1219                 seat_start(seat);
1220
1221         HASHMAP_FOREACH(user, m->users, i)
1222                 user_start(user);
1223
1224         HASHMAP_FOREACH(session, m->sessions, i)
1225                 session_start(session, NULL);
1226
1227         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1228                 inhibitor_start(inhibitor);
1229
1230         HASHMAP_FOREACH(button, m->buttons, i)
1231                 button_check_switches(button);
1232
1233         manager_dispatch_idle_action(NULL, 0, m);
1234
1235         return 0;
1236 }
1237
1238 static int manager_run(Manager *m) {
1239         int r;
1240
1241         assert(m);
1242
1243         for (;;) {
1244                 r = sd_event_get_state(m->event);
1245                 if (r < 0)
1246                         return r;
1247                 if (r == SD_EVENT_FINISHED)
1248                         return 0;
1249
1250                 manager_gc(m, true);
1251
1252                 r = manager_dispatch_delayed(m, false);
1253                 if (r < 0)
1254                         return r;
1255                 if (r > 0)
1256                         continue;
1257
1258                 r = sd_event_run(m->event, (uint64_t) -1);
1259                 if (r < 0)
1260                         return r;
1261         }
1262 }
1263
1264 int main(int argc, char *argv[]) {
1265         _cleanup_(manager_unrefp) Manager *m = NULL;
1266         int r;
1267
1268 #if 1 /// perform extra checks for elogind startup
1269         r = elogind_startup(argc, argv);
1270         if (r)
1271                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1272 #endif // 1
1273         elogind_set_program_name(argv[0]);
1274         log_set_target(LOG_TARGET_AUTO);
1275         log_set_facility(LOG_AUTH);
1276         log_parse_environment();
1277 #if ENABLE_DEBUG_ELOGIND
1278         log_set_max_level(LOG_DEBUG);
1279         log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1280 #endif // ENABLE_DEBUG_ELOGIND
1281         log_open();
1282
1283         umask(0022);
1284
1285 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1286         if (argc != 1) {
1287                 log_error("This program takes no arguments.");
1288                 r = -EINVAL;
1289                 goto finish;
1290         }
1291 #endif // 0
1292
1293         r = mac_selinux_init();
1294         if (r < 0) {
1295                 log_error_errno(r, "Could not initialize labelling: %m");
1296                 goto finish;
1297         }
1298
1299 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1300         mkdir_label("/run/systemd/seats", 0755);
1301         mkdir_label("/run/systemd/users", 0755);
1302         mkdir_label("/run/systemd/sessions", 0755);
1303         /* Always create the directories people can create inotify watches in. Note that some applications might check
1304          * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make
1305          * sure these directories are created early on and unconditionally. */
1306         (void) mkdir_label("/run/systemd/seats", 0755);
1307         (void) mkdir_label("/run/systemd/users", 0755);
1308         (void) mkdir_label("/run/systemd/sessions", 0755);
1309
1310         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, -1) >= 0);
1311
1312         r = manager_new(&m);
1313         if (r < 0) {
1314                 log_error_errno(r, "Failed to allocate manager object: %m");
1315 #else
1316         r = mkdir_label("/run/systemd", 0755);
1317         if ( (r < 0) && (-EEXIST != r) )
1318                 return log_error_errno(r, "Failed to create /run/systemd : %m");
1319         r = mkdir_label("/run/systemd/seats", 0755);
1320         if ( r < 0 && (-EEXIST != r) )
1321                 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1322         r = mkdir_label("/run/systemd/users", 0755);
1323         if ( r < 0 && (-EEXIST != r) )
1324                 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1325         r = mkdir_label("/run/systemd/sessions", 0755);
1326         if ( r < 0 && (-EEXIST != r) )
1327                 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1328         r = mkdir_label("/run/systemd/machines", 0755);
1329         if ( r < 0 && (-EEXIST != r) )
1330                 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1331 #endif // 0
1332                 goto finish;
1333         }
1334
1335         (void) manager_parse_config_file(m);
1336
1337 #if 1 /// elogind needs an Add-On for sleep configuration
1338         elogind_manager_reset_config(m);
1339 #endif // 1
1340         r = manager_startup(m);
1341         if (r < 0) {
1342                 log_error_errno(r, "Failed to fully start up daemon: %m");
1343                 goto finish;
1344         }
1345
1346         log_debug("elogind running as pid "PID_FMT, getpid_cached());
1347
1348         (void) sd_notify(false,
1349                          "READY=1\n"
1350                          "STATUS=Processing requests...");
1351
1352         r = manager_run(m);
1353
1354         log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1355
1356         (void) sd_notify(false,
1357                          "STOPPING=1\n"
1358                          "STATUS=Shutting down...");
1359
1360 finish:
1361         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1362 }