1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #if 0 /// elogind needs the systems udev header
31 #include "sd-daemon.h"
33 #include "alloc-util.h"
34 #include "bus-error.h"
36 #include "conf-parser.h"
38 #include "dirent-util.h"
40 #include "format-util.h"
42 #include "selinux-util.h"
43 #include "signal-util.h"
45 #include "udev-util.h"
46 /// Additional includes needed by elogind
47 #include "cgroup.h" // From src/core/
50 #include "musl_missing.h"
51 #include "process-util.h"
52 #include "cgroup-util.h"
54 static void manager_free(Manager *m);
56 static void manager_reset_config(Manager *m) {
57 #if 0 /// elogind does not support autospawning of vts
62 m->inhibit_delay_max = 5 * USEC_PER_SEC;
63 m->handle_power_key = HANDLE_POWEROFF;
64 m->handle_suspend_key = HANDLE_SUSPEND;
65 m->handle_hibernate_key = HANDLE_HIBERNATE;
66 m->handle_lid_switch = HANDLE_SUSPEND;
67 m->handle_lid_switch_docked = HANDLE_IGNORE;
68 m->power_key_ignore_inhibited = false;
69 m->suspend_key_ignore_inhibited = false;
70 m->hibernate_key_ignore_inhibited = false;
71 m->lid_switch_ignore_inhibited = true;
73 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
75 m->idle_action_usec = 30 * USEC_PER_MINUTE;
76 m->idle_action = HANDLE_IGNORE;
78 m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
79 m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
80 m->sessions_max = 8192;
81 m->inhibitors_max = 8192;
83 m->kill_user_processes = KILL_USER_PROCESSES;
85 m->kill_only_users = strv_free(m->kill_only_users);
86 m->kill_exclude_users = strv_free(m->kill_exclude_users);
89 static Manager *manager_new(void) {
97 m->console_active_fd = -1;
98 #if 0 /// UNNEEDED by elogind
99 m->reserve_vt_fd = -1;
102 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
104 m->devices = hashmap_new(&string_hash_ops);
105 m->seats = hashmap_new(&string_hash_ops);
106 m->sessions = hashmap_new(&string_hash_ops);
107 m->users = hashmap_new(NULL);
108 m->inhibitors = hashmap_new(&string_hash_ops);
109 m->buttons = hashmap_new(&string_hash_ops);
111 m->user_units = hashmap_new(&string_hash_ops);
112 m->session_units = hashmap_new(&string_hash_ops);
114 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
117 #if 1 /// elogind needs some more data
118 r = elogind_manager_new(m);
122 m->udev = udev_new();
126 r = sd_event_default(&m->event);
130 sd_event_set_watchdog(m->event, true);
132 manager_reset_config(m);
141 static void manager_free(Manager *m) {
152 while ((session = hashmap_first(m->sessions)))
153 session_free(session);
155 while ((u = hashmap_first(m->users)))
158 while ((d = hashmap_first(m->devices)))
161 while ((s = hashmap_first(m->seats)))
164 while ((i = hashmap_first(m->inhibitors)))
167 while ((b = hashmap_first(m->buttons)))
170 hashmap_free(m->devices);
171 hashmap_free(m->seats);
172 hashmap_free(m->sessions);
173 hashmap_free(m->users);
174 hashmap_free(m->inhibitors);
175 hashmap_free(m->buttons);
177 hashmap_free(m->user_units);
178 hashmap_free(m->session_units);
180 sd_event_source_unref(m->idle_action_event_source);
181 sd_event_source_unref(m->inhibit_timeout_source);
182 sd_event_source_unref(m->scheduled_shutdown_timeout_source);
183 sd_event_source_unref(m->nologin_timeout_source);
184 sd_event_source_unref(m->wall_message_timeout_source);
186 sd_event_source_unref(m->console_active_event_source);
187 sd_event_source_unref(m->udev_seat_event_source);
188 sd_event_source_unref(m->udev_device_event_source);
189 sd_event_source_unref(m->udev_vcsa_event_source);
190 sd_event_source_unref(m->udev_button_event_source);
191 sd_event_source_unref(m->lid_switch_ignore_event_source);
193 safe_close(m->console_active_fd);
195 udev_monitor_unref(m->udev_seat_monitor);
196 udev_monitor_unref(m->udev_device_monitor);
197 udev_monitor_unref(m->udev_vcsa_monitor);
198 udev_monitor_unref(m->udev_button_monitor);
202 if (m->unlink_nologin)
203 (void) unlink("/run/nologin");
205 bus_verify_polkit_async_registry_free(m->polkit_registry);
207 sd_bus_unref(m->bus);
208 sd_event_unref(m->event);
210 #if 0 /// elogind does not support autospawning of vts
211 safe_close(m->reserve_vt_fd);
213 #if 1 /// elogind has to free its own data
214 elogind_manager_free(m);
217 strv_free(m->kill_only_users);
218 strv_free(m->kill_exclude_users);
220 free(m->scheduled_shutdown_type);
221 free(m->scheduled_shutdown_tty);
222 free(m->wall_message);
223 #if 0 /// UNNEEDED by elogind
229 static int manager_enumerate_devices(Manager *m) {
230 struct udev_list_entry *item = NULL, *first = NULL;
231 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
236 /* Loads devices from udev and creates seats for them as
239 e = udev_enumerate_new(m->udev);
243 r = udev_enumerate_add_match_tag(e, "master-of-seat");
247 r = udev_enumerate_add_match_is_initialized(e);
251 r = udev_enumerate_scan_devices(e);
255 first = udev_enumerate_get_list_entry(e);
256 udev_list_entry_foreach(item, first) {
257 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
260 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
264 k = manager_process_seat_device(m, d);
272 static int manager_enumerate_buttons(Manager *m) {
273 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
274 struct udev_list_entry *item = NULL, *first = NULL;
279 /* Loads buttons from udev */
281 if (m->handle_power_key == HANDLE_IGNORE &&
282 m->handle_suspend_key == HANDLE_IGNORE &&
283 m->handle_hibernate_key == HANDLE_IGNORE &&
284 m->handle_lid_switch == HANDLE_IGNORE &&
285 m->handle_lid_switch_docked == HANDLE_IGNORE)
288 e = udev_enumerate_new(m->udev);
292 r = udev_enumerate_add_match_subsystem(e, "input");
296 r = udev_enumerate_add_match_tag(e, "power-switch");
300 r = udev_enumerate_add_match_is_initialized(e);
304 r = udev_enumerate_scan_devices(e);
308 first = udev_enumerate_get_list_entry(e);
309 udev_list_entry_foreach(item, first) {
310 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
313 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
317 k = manager_process_button_device(m, d);
325 static int manager_enumerate_seats(Manager *m) {
326 _cleanup_closedir_ DIR *d = NULL;
332 /* This loads data about seats stored on disk, but does not
333 * actually create any seats. Removes data of seats that no
336 d = opendir("/run/systemd/seats");
341 return log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
344 FOREACH_DIRENT(de, d, return -errno) {
348 if (!dirent_is_file(de))
351 s = hashmap_get(m->seats, de->d_name);
353 unlinkat(dirfd(d), de->d_name, 0);
365 static int manager_enumerate_linger_users(Manager *m) {
366 _cleanup_closedir_ DIR *d = NULL;
372 d = opendir("/var/lib/systemd/linger");
377 return log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
380 FOREACH_DIRENT(de, d, return -errno) {
383 if (!dirent_is_file(de))
386 k = manager_add_user_by_name(m, de->d_name, NULL);
388 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
396 static int manager_enumerate_users(Manager *m) {
397 _cleanup_closedir_ DIR *d = NULL;
403 /* Add lingering users */
404 r = manager_enumerate_linger_users(m);
406 /* Read in user data stored on disk */
407 d = opendir("/run/systemd/users");
412 return log_error_errno(errno, "Failed to open /run/systemd/users: %m");
415 FOREACH_DIRENT(de, d, return -errno) {
418 if (!dirent_is_file(de))
421 k = manager_add_user_by_name(m, de->d_name, &u);
423 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
429 user_add_to_gc_queue(u);
439 static int manager_attach_fds(Manager *m) {
440 _cleanup_strv_free_ char **fdnames = NULL;
443 /* Upon restart, PID1 will send us back all fds of session devices
444 * that we previously opened. Each file descriptor is associated
445 * with a given session. The session ids are passed through FDNAMES. */
447 n = sd_listen_fds_with_names(true, &fdnames);
451 for (i = 0; i < n; i++) {
457 fd = SD_LISTEN_FDS_START + i;
459 id = startswith(fdnames[i], "session-");
463 s = hashmap_get(m->sessions, id);
465 /* If the session doesn't exist anymore, the associated session
466 * device attached to this fd doesn't either. Let's simply close
468 log_debug("Failed to attach fd for unknown session: %s", id);
473 if (fstat(fd, &st) < 0) {
474 /* The device is allowed to go away at a random point, in which
475 * case fstat failing is expected. */
476 log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
481 sd = hashmap_get(s->devices, &st.st_rdev);
483 /* Weird we got an fd for a session device which wasn't
484 * recorded in the session state file... */
485 log_warning("Got fd for missing session device [%u:%u] in session %s",
486 major(st.st_rdev), minor(st.st_rdev), s->id);
491 log_debug("Attaching fd to session device [%u:%u] for session %s",
492 major(st.st_rdev), minor(st.st_rdev), s->id);
494 session_device_attach_fd(sd, fd, s->was_active);
500 static int manager_enumerate_sessions(Manager *m) {
501 _cleanup_closedir_ DIR *d = NULL;
507 /* Read in session data stored on disk */
508 d = opendir("/run/systemd/sessions");
513 return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
516 FOREACH_DIRENT(de, d, return -errno) {
519 if (!dirent_is_file(de))
522 if (!session_id_valid(de->d_name)) {
523 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
528 k = manager_add_session(m, de->d_name, &s);
530 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
535 session_add_to_gc_queue(s);
542 /* We might be restarted and PID1 could have sent us back the
543 * session device fds we previously saved. */
544 k = manager_attach_fds(m);
546 log_warning_errno(k, "Failed to reattach session device fds: %m");
551 static int manager_enumerate_inhibitors(Manager *m) {
552 _cleanup_closedir_ DIR *d = NULL;
558 d = opendir("/run/systemd/inhibit");
563 return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
566 FOREACH_DIRENT(de, d, return -errno) {
570 if (!dirent_is_file(de))
573 k = manager_add_inhibitor(m, de->d_name, &i);
575 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
580 k = inhibitor_load(i);
588 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
589 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
590 Manager *m = userdata;
594 d = udev_monitor_receive_device(m->udev_seat_monitor);
598 manager_process_seat_device(m, d);
602 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
603 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
604 Manager *m = userdata;
608 d = udev_monitor_receive_device(m->udev_device_monitor);
612 manager_process_seat_device(m, d);
616 #if 0 /// UNNEEDED by elogind
617 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
618 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
619 Manager *m = userdata;
624 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
628 name = udev_device_get_sysname(d);
630 /* Whenever a VCSA device is removed try to reallocate our
631 * VTs, to make sure our auto VTs never go away. */
633 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
634 seat_preallocate_vts(m->seat0);
640 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
641 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
642 Manager *m = userdata;
646 d = udev_monitor_receive_device(m->udev_button_monitor);
650 manager_process_button_device(m, d);
654 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
655 Manager *m = userdata;
659 assert(m->console_active_fd == fd);
661 seat_read_active_vt(m->seat0);
665 #if 0 /// UNNEEDED by elogind
666 static int manager_reserve_vt(Manager *m) {
667 _cleanup_free_ char *p = NULL;
671 if (m->reserve_vt <= 0)
674 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
677 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
678 if (m->reserve_vt_fd < 0) {
680 /* Don't complain on VT-less systems */
682 log_warning_errno(errno, "Failed to pin reserved VT: %m");
690 static int manager_connect_bus(Manager *m) {
691 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
697 r = sd_bus_default_system(&m->bus);
699 return log_error_errno(r, "Failed to connect to system bus: %m");
701 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
703 return log_error_errno(r, "Failed to add manager object vtable: %m");
705 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
707 return log_error_errno(r, "Failed to add seat object vtable: %m");
709 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
711 return log_error_errno(r, "Failed to add seat enumerator: %m");
713 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
715 return log_error_errno(r, "Failed to add session object vtable: %m");
717 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
719 return log_error_errno(r, "Failed to add session enumerator: %m");
721 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
723 return log_error_errno(r, "Failed to add user object vtable: %m");
725 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
727 return log_error_errno(r, "Failed to add user enumerator: %m");
729 #if 0 /// elogind does not support systemd as PID 1
730 r = sd_bus_add_match(m->bus,
733 "sender='org.freedesktop.systemd1',"
734 "interface='org.freedesktop.systemd1.Manager',"
735 "member='JobRemoved',"
736 "path='/org/freedesktop/systemd1'",
737 match_job_removed, m);
739 return log_error_errno(r, "Failed to add match for JobRemoved: %m");
741 r = sd_bus_add_match(m->bus,
744 "sender='org.freedesktop.systemd1',"
745 "interface='org.freedesktop.systemd1.Manager',"
746 "member='UnitRemoved',"
747 "path='/org/freedesktop/systemd1'",
748 match_unit_removed, m);
750 return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
752 r = sd_bus_add_match(m->bus,
755 "sender='org.freedesktop.systemd1',"
756 "interface='org.freedesktop.DBus.Properties',"
757 "member='PropertiesChanged'",
758 match_properties_changed, m);
760 return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
762 r = sd_bus_add_match(m->bus,
765 "sender='org.freedesktop.systemd1',"
766 "interface='org.freedesktop.systemd1.Manager',"
767 "member='Reloading',"
768 "path='/org/freedesktop/systemd1'",
771 return log_error_errno(r, "Failed to add match for Reloading: %m");
773 r = sd_bus_call_method(
775 "org.freedesktop.systemd1",
776 "/org/freedesktop/systemd1",
777 "org.freedesktop.systemd1.Manager",
782 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
787 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
789 return log_error_errno(r, "Failed to register name: %m");
791 r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
793 return log_error_errno(r, "Failed to attach bus to event loop: %m");
795 #if 0 /// elogind has to setup its release agent
798 r = elogind_setup_cgroups_agent(m);
804 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
806 Session *active, *iter;
809 * We got a VT-switch signal and we have to acknowledge it immediately.
810 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
811 * old user-space might run multiple sessions on a single VT, *sigh*.
812 * Therefore, we have to iterate all sessions and find one with a vtfd
813 * on the requested VT.
814 * As only VTs with active controllers have VT_PROCESS set, our current
815 * notion of the active VT might be wrong (for instance if the switch
816 * happens while we setup VT_PROCESS). Therefore, read the current VT
817 * first and then use s->active->vtnr as reference. Note that this is
818 * not racy, as no further VT-switch can happen as long as we're in
819 * synchronous VT_PROCESS mode.
823 seat_read_active_vt(m->seat0);
825 active = m->seat0->active;
826 if (!active || active->vtnr < 1) {
827 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
831 if (active->vtfd >= 0) {
832 session_leave_vt(active);
834 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
835 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
836 session_leave_vt(iter);
845 static int manager_connect_console(Manager *m) {
849 assert(m->console_active_fd < 0);
851 /* On certain architectures (S390 and Xen, and containers),
852 /dev/tty0 does not exist, so don't fail if we can't open
854 if (access("/dev/tty0", F_OK) < 0)
857 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
858 if (m->console_active_fd < 0) {
860 /* On some systems the device node /dev/tty0 may exist
861 * even though /sys/class/tty/tty0 does not. */
865 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
868 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
870 log_error("Failed to watch foreground console");
875 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
876 * as VT-acquire signal. We ignore any acquire-events (yes, we still
877 * have to provide a valid signal-number for it!) and acknowledge all
878 * release events immediately.
881 if (SIGRTMIN + 1 > SIGRTMAX) {
882 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
886 assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0);
887 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
889 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
896 static int manager_connect_udev(Manager *m) {
900 assert(!m->udev_seat_monitor);
901 assert(!m->udev_device_monitor);
902 assert(!m->udev_vcsa_monitor);
903 assert(!m->udev_button_monitor);
905 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
906 if (!m->udev_seat_monitor)
909 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
913 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
917 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);
921 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
922 if (!m->udev_device_monitor)
925 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
929 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
933 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
937 r = udev_monitor_enable_receiving(m->udev_device_monitor);
941 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);
945 /* Don't watch keys if nobody cares */
946 if (m->handle_power_key != HANDLE_IGNORE ||
947 m->handle_suspend_key != HANDLE_IGNORE ||
948 m->handle_hibernate_key != HANDLE_IGNORE ||
949 m->handle_lid_switch != HANDLE_IGNORE ||
950 m->handle_lid_switch_docked != HANDLE_IGNORE) {
952 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
953 if (!m->udev_button_monitor)
956 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
960 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
964 r = udev_monitor_enable_receiving(m->udev_button_monitor);
968 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 /* Don't bother watching VCSA devices, if nobody cares */
974 #if 0 /// elogind does not support autospawning of vts
975 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
977 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
978 if (!m->udev_vcsa_monitor)
981 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
985 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
989 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);
998 static void manager_gc(Manager *m, bool drop_not_started) {
1005 while ((seat = m->seat_gc_queue)) {
1006 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1007 seat->in_gc_queue = false;
1009 if (!seat_check_gc(seat, drop_not_started)) {
1010 seat_stop(seat, false);
1015 while ((session = m->session_gc_queue)) {
1016 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1017 session->in_gc_queue = false;
1019 /* First, if we are not closing yet, initiate stopping */
1020 if (!session_check_gc(session, drop_not_started) &&
1021 session_get_state(session) != SESSION_CLOSING)
1022 session_stop(session, false);
1024 /* Normally, this should make the session referenced
1025 * again, if it doesn't then let's get rid of it
1027 if (!session_check_gc(session, drop_not_started)) {
1028 session_finalize(session);
1029 session_free(session);
1033 while ((user = m->user_gc_queue)) {
1034 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1035 user->in_gc_queue = false;
1037 /* First step: queue stop jobs */
1038 if (!user_check_gc(user, drop_not_started))
1039 user_stop(user, false);
1041 /* Second step: finalize user */
1042 if (!user_check_gc(user, drop_not_started)) {
1043 user_finalize(user);
1049 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1050 Manager *m = userdata;
1051 struct dual_timestamp since;
1057 if (m->idle_action == HANDLE_IGNORE ||
1058 m->idle_action_usec <= 0)
1061 n = now(CLOCK_MONOTONIC);
1063 r = manager_get_idle_hint(m, &since);
1065 /* Not idle. Let's check if after a timeout it might be idle then. */
1066 elapse = n + m->idle_action_usec;
1068 /* Idle! Let's see if it's time to do something, or if
1069 * we shall sleep for longer. */
1071 if (n >= since.monotonic + m->idle_action_usec &&
1072 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1073 log_info("System idle. Taking action.");
1075 manager_handle_action(m, 0, m->idle_action, false, false);
1076 m->idle_action_not_before_usec = n;
1079 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1082 if (!m->idle_action_event_source) {
1084 r = sd_event_add_time(
1086 &m->idle_action_event_source,
1088 elapse, USEC_PER_SEC*30,
1089 manager_dispatch_idle_action, m);
1091 return log_error_errno(r, "Failed to add idle event source: %m");
1093 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1095 return log_error_errno(r, "Failed to set idle event source priority: %m");
1097 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1099 return log_error_errno(r, "Failed to set idle event timer: %m");
1101 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1103 return log_error_errno(r, "Failed to enable idle event timer: %m");
1109 static int manager_parse_config_file(Manager *m) {
1110 #if 0 /// elogind parses its own config file
1113 return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
1114 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
1116 config_item_perf_lookup, logind_gperf_lookup,
1118 const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1123 logind_conf = PKGSYSCONFDIR "/logind.conf";
1125 return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1126 config_item_perf_lookup, logind_gperf_lookup,
1128 CONFIG_PARSE_WARN, m);
1131 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1132 Manager *m = userdata;
1135 manager_reset_config(m);
1136 r = manager_parse_config_file(m);
1138 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1140 log_info("Config file reloaded.");
1142 #if 1 /// elogind needs an Add-On for sleep configuration
1143 elogind_manager_reset_config(m);
1148 static int manager_startup(Manager *m) {
1154 Inhibitor *inhibitor;
1159 assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
1161 r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1163 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1165 #if 1 /// elogind needs some extra preparations before connecting...
1166 elogind_manager_startup(m);
1168 /* Connect to console */
1169 r = manager_connect_console(m);
1173 /* Connect to udev */
1174 r = manager_connect_udev(m);
1176 return log_error_errno(r, "Failed to create udev watchers: %m");
1178 /* Connect to the bus */
1179 r = manager_connect_bus(m);
1183 /* Instantiate magic seat 0 */
1184 r = manager_add_seat(m, "seat0", &m->seat0);
1186 return log_error_errno(r, "Failed to add seat0: %m");
1188 r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1190 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1192 /* Deserialize state */
1193 r = manager_enumerate_devices(m);
1195 log_warning_errno(r, "Device enumeration failed: %m");
1197 r = manager_enumerate_seats(m);
1199 log_warning_errno(r, "Seat enumeration failed: %m");
1201 r = manager_enumerate_users(m);
1203 log_warning_errno(r, "User enumeration failed: %m");
1205 r = manager_enumerate_sessions(m);
1207 log_warning_errno(r, "Session enumeration failed: %m");
1209 r = manager_enumerate_inhibitors(m);
1211 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1213 r = manager_enumerate_buttons(m);
1215 log_warning_errno(r, "Button enumeration failed: %m");
1217 /* Remove stale objects before we start them */
1218 manager_gc(m, false);
1220 /* Reserve the special reserved VT */
1221 #if 0 /// elogind does not support autospawning of vts
1222 manager_reserve_vt(m);
1225 /* And start everything */
1226 HASHMAP_FOREACH(seat, m->seats, i)
1229 HASHMAP_FOREACH(user, m->users, i)
1232 HASHMAP_FOREACH(session, m->sessions, i)
1233 session_start(session);
1235 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1236 inhibitor_start(inhibitor);
1238 HASHMAP_FOREACH(button, m->buttons, i)
1239 button_check_switches(button);
1241 manager_dispatch_idle_action(NULL, 0, m);
1246 static int manager_run(Manager *m) {
1252 r = sd_event_get_state(m->event);
1255 if (r == SD_EVENT_FINISHED)
1258 manager_gc(m, true);
1260 r = manager_dispatch_delayed(m, false);
1266 r = sd_event_run(m->event, (uint64_t) -1);
1272 int main(int argc, char *argv[]) {
1276 #if 1 /// perform extra checks for elogind startup
1277 r = elogind_startup(argc, argv);
1279 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1281 elogind_set_program_name(argv[0]);
1282 log_set_target(LOG_TARGET_AUTO);
1283 log_set_facility(LOG_AUTH);
1284 log_parse_environment();
1285 #ifdef ENABLE_DEBUG_ELOGIND
1286 log_set_max_level(LOG_DEBUG);
1287 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1288 #endif // ENABLE_DEBUG_ELOGIND
1293 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1295 log_error("This program takes no arguments.");
1301 r = mac_selinux_init();
1303 log_error_errno(r, "Could not initialize labelling: %m");
1307 /* Always create the directories people can create inotify
1308 * watches in. Note that some applications might check for the
1309 * existence of /run/systemd/seats/ to determine whether
1310 * logind is available, so please always make sure this check
1312 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1313 mkdir_label("/run/systemd/seats", 0755);
1314 mkdir_label("/run/systemd/users", 0755);
1315 mkdir_label("/run/systemd/sessions", 0755);
1317 r = mkdir_label("/run/systemd", 0755);
1318 if ( (r < 0) && (-EEXIST != r) )
1319 return log_error_errno(r, "Failed to create /run/systemd : %m");
1320 r = mkdir_label("/run/systemd/seats", 0755);
1321 if ( r < 0 && (-EEXIST != r) )
1322 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1323 r = mkdir_label("/run/systemd/users", 0755);
1324 if ( r < 0 && (-EEXIST != r) )
1325 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1326 r = mkdir_label("/run/systemd/sessions", 0755);
1327 if ( r < 0 && (-EEXIST != r) )
1328 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1329 r = mkdir_label("/run/systemd/machines", 0755);
1330 if ( r < 0 && (-EEXIST != r) )
1331 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1340 manager_parse_config_file(m);
1342 #if 1 /// elogind needs an Add-On for sleep configuration
1343 elogind_manager_reset_config(m);
1345 r = manager_startup(m);
1347 log_error_errno(r, "Failed to fully start up daemon: %m");
1351 log_debug("elogind running as pid "PID_FMT, getpid_cached());
1355 "STATUS=Processing requests...");
1359 log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1364 "STATUS=Shutting down...");
1368 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;