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 "cgroup-util.h"
37 #include "conf-parser.h"
39 #include "dirent-util.h"
41 #include "format-util.h"
44 //#include "parse-util.h"
45 //#include "process-util.h"
46 #include "selinux-util.h"
47 #include "signal-util.h"
49 #include "udev-util.h"
50 /// Additional includes needed by elogind
51 #include "cgroup.h" // From src/core/
54 #include "musl_missing.h"
55 #include "process-util.h"
56 #include "cgroup-util.h"
58 static void manager_free(Manager *m);
60 static void manager_reset_config(Manager *m) {
61 #if 0 /// elogind does not support autospawning of vts
66 m->inhibit_delay_max = 5 * USEC_PER_SEC;
67 m->handle_power_key = HANDLE_POWEROFF;
68 m->handle_suspend_key = HANDLE_SUSPEND;
69 m->handle_hibernate_key = HANDLE_HIBERNATE;
70 m->handle_lid_switch = HANDLE_SUSPEND;
71 m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
72 m->handle_lid_switch_docked = HANDLE_IGNORE;
73 m->power_key_ignore_inhibited = false;
74 m->suspend_key_ignore_inhibited = false;
75 m->hibernate_key_ignore_inhibited = false;
76 m->lid_switch_ignore_inhibited = true;
78 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
80 m->idle_action_usec = 30 * USEC_PER_MINUTE;
81 m->idle_action = HANDLE_IGNORE;
83 m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
84 m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
85 m->sessions_max = 8192;
86 m->inhibitors_max = 8192;
88 m->kill_user_processes = KILL_USER_PROCESSES;
90 m->kill_only_users = strv_free(m->kill_only_users);
91 m->kill_exclude_users = strv_free(m->kill_exclude_users);
94 static Manager *manager_new(void) {
102 m->console_active_fd = -1;
103 #if 0 /// UNNEEDED by elogind
104 m->reserve_vt_fd = -1;
107 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
109 m->devices = hashmap_new(&string_hash_ops);
110 m->seats = hashmap_new(&string_hash_ops);
111 m->sessions = hashmap_new(&string_hash_ops);
112 m->users = hashmap_new(NULL);
113 m->inhibitors = hashmap_new(&string_hash_ops);
114 m->buttons = hashmap_new(&string_hash_ops);
116 m->user_units = hashmap_new(&string_hash_ops);
117 m->session_units = hashmap_new(&string_hash_ops);
119 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
122 #if 1 /// elogind needs some more data
123 r = elogind_manager_new(m);
127 m->udev = udev_new();
131 r = sd_event_default(&m->event);
135 sd_event_set_watchdog(m->event, true);
137 manager_reset_config(m);
146 static void manager_free(Manager *m) {
157 while ((session = hashmap_first(m->sessions)))
158 session_free(session);
160 while ((u = hashmap_first(m->users)))
163 while ((d = hashmap_first(m->devices)))
166 while ((s = hashmap_first(m->seats)))
169 while ((i = hashmap_first(m->inhibitors)))
172 while ((b = hashmap_first(m->buttons)))
175 hashmap_free(m->devices);
176 hashmap_free(m->seats);
177 hashmap_free(m->sessions);
178 hashmap_free(m->users);
179 hashmap_free(m->inhibitors);
180 hashmap_free(m->buttons);
182 hashmap_free(m->user_units);
183 hashmap_free(m->session_units);
185 sd_event_source_unref(m->idle_action_event_source);
186 sd_event_source_unref(m->inhibit_timeout_source);
187 sd_event_source_unref(m->scheduled_shutdown_timeout_source);
188 sd_event_source_unref(m->nologin_timeout_source);
189 sd_event_source_unref(m->wall_message_timeout_source);
191 sd_event_source_unref(m->console_active_event_source);
192 sd_event_source_unref(m->udev_seat_event_source);
193 sd_event_source_unref(m->udev_device_event_source);
194 sd_event_source_unref(m->udev_vcsa_event_source);
195 sd_event_source_unref(m->udev_button_event_source);
196 sd_event_source_unref(m->lid_switch_ignore_event_source);
198 safe_close(m->console_active_fd);
200 udev_monitor_unref(m->udev_seat_monitor);
201 udev_monitor_unref(m->udev_device_monitor);
202 udev_monitor_unref(m->udev_vcsa_monitor);
203 udev_monitor_unref(m->udev_button_monitor);
207 if (m->unlink_nologin)
208 (void) unlink_or_warn("/run/nologin");
210 bus_verify_polkit_async_registry_free(m->polkit_registry);
212 sd_bus_unref(m->bus);
213 sd_event_unref(m->event);
215 #if 0 /// elogind does not support autospawning of vts
216 safe_close(m->reserve_vt_fd);
218 #if 1 /// elogind has to free its own data
219 elogind_manager_free(m);
222 strv_free(m->kill_only_users);
223 strv_free(m->kill_exclude_users);
225 free(m->scheduled_shutdown_type);
226 free(m->scheduled_shutdown_tty);
227 free(m->wall_message);
228 #if 0 /// UNNEEDED by elogind
234 static int manager_enumerate_devices(Manager *m) {
235 struct udev_list_entry *item = NULL, *first = NULL;
236 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
241 /* Loads devices from udev and creates seats for them as
244 e = udev_enumerate_new(m->udev);
248 r = udev_enumerate_add_match_tag(e, "master-of-seat");
252 r = udev_enumerate_add_match_is_initialized(e);
256 r = udev_enumerate_scan_devices(e);
260 first = udev_enumerate_get_list_entry(e);
261 udev_list_entry_foreach(item, first) {
262 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
265 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
269 k = manager_process_seat_device(m, d);
277 static int manager_enumerate_buttons(Manager *m) {
278 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
279 struct udev_list_entry *item = NULL, *first = NULL;
284 /* Loads buttons from udev */
286 if (manager_all_buttons_ignored(m))
289 e = udev_enumerate_new(m->udev);
293 r = udev_enumerate_add_match_subsystem(e, "input");
297 r = udev_enumerate_add_match_tag(e, "power-switch");
301 r = udev_enumerate_add_match_is_initialized(e);
305 r = udev_enumerate_scan_devices(e);
309 first = udev_enumerate_get_list_entry(e);
310 udev_list_entry_foreach(item, first) {
311 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
314 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
318 k = manager_process_button_device(m, d);
326 static int manager_enumerate_seats(Manager *m) {
327 _cleanup_closedir_ DIR *d = NULL;
333 /* This loads data about seats stored on disk, but does not
334 * actually create any seats. Removes data of seats that no
337 d = opendir("/run/systemd/seats");
342 return log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
345 FOREACH_DIRENT(de, d, return -errno) {
349 if (!dirent_is_file(de))
352 s = hashmap_get(m->seats, de->d_name);
354 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
355 log_warning("Failed to remove /run/systemd/seats/%s: %m",
368 static int manager_enumerate_linger_users(Manager *m) {
369 _cleanup_closedir_ DIR *d = NULL;
375 d = opendir("/var/lib/elogind/linger");
380 return log_error_errno(errno, "Failed to open /var/lib/elogind/linger/: %m");
383 FOREACH_DIRENT(de, d, return -errno) {
386 if (!dirent_is_file(de))
389 k = manager_add_user_by_name(m, de->d_name, NULL);
391 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
399 static int manager_enumerate_users(Manager *m) {
400 _cleanup_closedir_ DIR *d = NULL;
406 /* Add lingering users */
407 r = manager_enumerate_linger_users(m);
409 /* Read in user data stored on disk */
410 d = opendir("/run/systemd/users");
415 return log_error_errno(errno, "Failed to open /run/systemd/users: %m");
418 FOREACH_DIRENT(de, d, return -errno) {
421 if (!dirent_is_file(de))
424 k = manager_add_user_by_name(m, de->d_name, &u);
426 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
432 user_add_to_gc_queue(u);
442 static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
443 _cleanup_strv_free_ char **parts = NULL;
444 _cleanup_free_ char *id = NULL;
445 unsigned int major, minor;
448 parts = strv_split(fdname, "-");
451 if (strv_length(parts) != 5)
454 if (!streq(parts[0], "session"))
456 id = strdup(parts[1]);
460 if (!streq(parts[2], "device"))
462 r = safe_atou(parts[3], &major) ||
463 safe_atou(parts[4], &minor);
467 *dev = makedev(major, minor);
468 *session_id = TAKE_PTR(id);
473 static int manager_attach_fds(Manager *m) {
474 _cleanup_strv_free_ char **fdnames = NULL;
477 /* Upon restart, PID1 will send us back all fds of session devices
478 * that we previously opened. Each file descriptor is associated
479 * with a given session. The session ids are passed through FDNAMES. */
481 n = sd_listen_fds_with_names(true, &fdnames);
485 for (i = 0; i < n; i++) {
486 _cleanup_free_ char *id = NULL;
493 fd = SD_LISTEN_FDS_START + i;
495 r = parse_fdname(fdnames[i], &id, &dev);
497 log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
502 s = hashmap_get(m->sessions, id);
504 /* If the session doesn't exist anymore, the associated session
505 * device attached to this fd doesn't either. Let's simply close
507 log_debug("Failed to attach fd for unknown session: %s", id);
512 if (fstat(fd, &st) < 0) {
513 /* The device is allowed to go away at a random point, in which
514 * case fstat failing is expected. */
515 log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
520 if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
521 log_debug("Device fd doesn't point to the expected character device node");
526 sd = hashmap_get(s->devices, &dev);
528 /* Weird, we got an fd for a session device which wasn't
529 * recorded in the session state file... */
530 log_warning("Got fd for missing session device [%u:%u] in session %s",
531 major(dev), minor(dev), s->id);
536 log_debug("Attaching fd to session device [%u:%u] for session %s",
537 major(dev), minor(dev), s->id);
539 session_device_attach_fd(sd, fd, s->was_active);
545 static int manager_enumerate_sessions(Manager *m) {
546 _cleanup_closedir_ DIR *d = NULL;
552 /* Read in session data stored on disk */
553 d = opendir("/run/systemd/sessions");
558 return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
561 FOREACH_DIRENT(de, d, return -errno) {
564 if (!dirent_is_file(de))
567 if (!session_id_valid(de->d_name)) {
568 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
573 k = manager_add_session(m, de->d_name, &s);
575 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
580 session_add_to_gc_queue(s);
587 /* We might be restarted and PID1 could have sent us back the
588 * session device fds we previously saved. */
589 k = manager_attach_fds(m);
591 log_warning_errno(k, "Failed to reattach session device fds: %m");
596 static int manager_enumerate_inhibitors(Manager *m) {
597 _cleanup_closedir_ DIR *d = NULL;
603 d = opendir("/run/systemd/inhibit");
608 return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
611 FOREACH_DIRENT(de, d, return -errno) {
615 if (!dirent_is_file(de))
618 k = manager_add_inhibitor(m, de->d_name, &i);
620 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
625 k = inhibitor_load(i);
633 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
634 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
635 Manager *m = userdata;
639 d = udev_monitor_receive_device(m->udev_seat_monitor);
643 manager_process_seat_device(m, d);
647 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
648 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
649 Manager *m = userdata;
653 d = udev_monitor_receive_device(m->udev_device_monitor);
657 manager_process_seat_device(m, d);
661 #if 0 /// UNNEEDED by elogind
662 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
663 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
664 Manager *m = userdata;
669 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
673 name = udev_device_get_sysname(d);
675 /* Whenever a VCSA device is removed try to reallocate our
676 * VTs, to make sure our auto VTs never go away. */
678 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
679 seat_preallocate_vts(m->seat0);
685 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
686 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
687 Manager *m = userdata;
691 d = udev_monitor_receive_device(m->udev_button_monitor);
695 manager_process_button_device(m, d);
699 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
700 Manager *m = userdata;
704 assert(m->console_active_fd == fd);
706 seat_read_active_vt(m->seat0);
710 #if 0 /// UNNEEDED by elogind
711 static int manager_reserve_vt(Manager *m) {
712 _cleanup_free_ char *p = NULL;
716 if (m->reserve_vt <= 0)
719 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
722 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
723 if (m->reserve_vt_fd < 0) {
725 /* Don't complain on VT-less systems */
727 log_warning_errno(errno, "Failed to pin reserved VT: %m");
735 static int manager_connect_bus(Manager *m) {
741 r = sd_bus_default_system(&m->bus);
743 return log_error_errno(r, "Failed to connect to system bus: %m");
745 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
747 return log_error_errno(r, "Failed to add manager object vtable: %m");
749 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
751 return log_error_errno(r, "Failed to add seat object vtable: %m");
753 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
755 return log_error_errno(r, "Failed to add seat enumerator: %m");
757 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
759 return log_error_errno(r, "Failed to add session object vtable: %m");
761 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
763 return log_error_errno(r, "Failed to add session enumerator: %m");
765 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
767 return log_error_errno(r, "Failed to add user object vtable: %m");
769 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
771 return log_error_errno(r, "Failed to add user enumerator: %m");
773 #if 0 /// elogind does not support systemd as PID 1
774 r = sd_bus_match_signal_async(
777 "org.freedesktop.systemd1",
778 "/org/freedesktop/systemd1",
779 "org.freedesktop.systemd1.Manager",
781 match_job_removed, NULL, m);
783 return log_error_errno(r, "Failed to request match for JobRemoved: %m");
785 r = sd_bus_match_signal_async(
788 "org.freedesktop.systemd1",
789 "/org/freedesktop/systemd1",
790 "org.freedesktop.systemd1.Manager",
792 match_unit_removed, NULL, m);
794 return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
796 r = sd_bus_match_signal_async(
799 "org.freedesktop.systemd1",
801 "org.freedesktop.DBus.Properties",
803 match_properties_changed, NULL, m);
805 return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
807 r = sd_bus_match_signal_async(
810 "org.freedesktop.systemd1",
811 "/org/freedesktop/systemd1",
812 "org.freedesktop.systemd1.Manager",
814 match_reloading, NULL, m);
816 return log_error_errno(r, "Failed to request match for Reloading: %m");
818 r = sd_bus_call_method_async(
821 "org.freedesktop.systemd1",
822 "/org/freedesktop/systemd1",
823 "org.freedesktop.systemd1.Manager",
829 return log_error_errno(r, "Failed to enable subscription: %m");
831 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
833 return log_error_errno(r, "Failed to request name: %m");
835 r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
837 return log_error_errno(r, "Failed to attach bus to event loop: %m");
839 #if 0 /// elogind has to setup its release agent
842 r = elogind_setup_cgroups_agent(m);
848 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
850 Session *active, *iter;
853 * We got a VT-switch signal and we have to acknowledge it immediately.
854 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
855 * old user-space might run multiple sessions on a single VT, *sigh*.
856 * Therefore, we have to iterate all sessions and find one with a vtfd
857 * on the requested VT.
858 * As only VTs with active controllers have VT_PROCESS set, our current
859 * notion of the active VT might be wrong (for instance if the switch
860 * happens while we setup VT_PROCESS). Therefore, read the current VT
861 * first and then use s->active->vtnr as reference. Note that this is
862 * not racy, as no further VT-switch can happen as long as we're in
863 * synchronous VT_PROCESS mode.
867 seat_read_active_vt(m->seat0);
869 active = m->seat0->active;
870 if (!active || active->vtnr < 1) {
871 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
875 if (active->vtfd >= 0) {
876 session_leave_vt(active);
878 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
879 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
880 session_leave_vt(iter);
889 static int manager_connect_console(Manager *m) {
893 assert(m->console_active_fd < 0);
895 /* On certain architectures (S390 and Xen, and containers),
896 /dev/tty0 does not exist, so don't fail if we can't open
898 if (access("/dev/tty0", F_OK) < 0)
901 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
902 if (m->console_active_fd < 0) {
904 /* On some systems the device node /dev/tty0 may exist
905 * even though /sys/class/tty/tty0 does not. */
909 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
912 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
914 log_error("Failed to watch foreground console");
919 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
920 * as VT-acquire signal. We ignore any acquire-events (yes, we still
921 * have to provide a valid signal-number for it!) and acknowledge all
922 * release events immediately.
925 if (SIGRTMIN + 1 > SIGRTMAX) {
926 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
930 assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0);
931 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
933 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
940 static int manager_connect_udev(Manager *m) {
944 assert(!m->udev_seat_monitor);
945 assert(!m->udev_device_monitor);
946 assert(!m->udev_vcsa_monitor);
947 assert(!m->udev_button_monitor);
949 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
950 if (!m->udev_seat_monitor)
953 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
957 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
961 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);
965 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
966 if (!m->udev_device_monitor)
969 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
973 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
977 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
981 r = udev_monitor_enable_receiving(m->udev_device_monitor);
985 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);
989 /* Don't watch keys if nobody cares */
990 if (!manager_all_buttons_ignored(m)) {
991 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
992 if (!m->udev_button_monitor)
995 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
999 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1003 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1007 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);
1012 /* Don't bother watching VCSA devices, if nobody cares */
1013 #if 0 /// elogind does not support autospawning of vts
1014 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1016 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1017 if (!m->udev_vcsa_monitor)
1020 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1024 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1028 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);
1037 static void manager_gc(Manager *m, bool drop_not_started) {
1044 while ((seat = m->seat_gc_queue)) {
1045 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1046 seat->in_gc_queue = false;
1048 if (seat_may_gc(seat, drop_not_started)) {
1049 seat_stop(seat, false);
1054 while ((session = m->session_gc_queue)) {
1055 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1056 session->in_gc_queue = false;
1058 /* First, if we are not closing yet, initiate stopping */
1059 if (session_may_gc(session, drop_not_started) &&
1060 session_get_state(session) != SESSION_CLOSING)
1061 session_stop(session, false);
1063 /* Normally, this should make the session referenced
1064 * again, if it doesn't then let's get rid of it
1066 if (session_may_gc(session, drop_not_started)) {
1067 session_finalize(session);
1068 session_free(session);
1072 while ((user = m->user_gc_queue)) {
1073 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1074 user->in_gc_queue = false;
1076 /* First step: queue stop jobs */
1077 if (user_may_gc(user, drop_not_started))
1078 user_stop(user, false);
1080 /* Second step: finalize user */
1081 if (user_may_gc(user, drop_not_started)) {
1082 user_finalize(user);
1088 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1089 Manager *m = userdata;
1090 struct dual_timestamp since;
1096 if (m->idle_action == HANDLE_IGNORE ||
1097 m->idle_action_usec <= 0)
1100 n = now(CLOCK_MONOTONIC);
1102 r = manager_get_idle_hint(m, &since);
1104 /* Not idle. Let's check if after a timeout it might be idle then. */
1105 elapse = n + m->idle_action_usec;
1107 /* Idle! Let's see if it's time to do something, or if
1108 * we shall sleep for longer. */
1110 if (n >= since.monotonic + m->idle_action_usec &&
1111 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1112 log_info("System idle. Taking action.");
1114 manager_handle_action(m, 0, m->idle_action, false, false);
1115 m->idle_action_not_before_usec = n;
1118 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1121 if (!m->idle_action_event_source) {
1123 r = sd_event_add_time(
1125 &m->idle_action_event_source,
1127 elapse, USEC_PER_SEC*30,
1128 manager_dispatch_idle_action, m);
1130 return log_error_errno(r, "Failed to add idle event source: %m");
1132 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1134 return log_error_errno(r, "Failed to set idle event source priority: %m");
1136 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1138 return log_error_errno(r, "Failed to set idle event timer: %m");
1140 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1142 return log_error_errno(r, "Failed to enable idle event timer: %m");
1148 static int manager_parse_config_file(Manager *m) {
1149 #if 0 /// elogind parses its own config file
1152 return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
1153 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
1155 config_item_perf_lookup, logind_gperf_lookup,
1157 const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1162 logind_conf = PKGSYSCONFDIR "/logind.conf";
1164 return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1165 config_item_perf_lookup, logind_gperf_lookup,
1167 CONFIG_PARSE_WARN, m);
1170 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1171 Manager *m = userdata;
1174 manager_reset_config(m);
1175 r = manager_parse_config_file(m);
1177 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1179 log_info("Config file reloaded.");
1181 #if 1 /// elogind needs an Add-On for sleep configuration
1182 elogind_manager_reset_config(m);
1187 static int manager_startup(Manager *m) {
1193 Inhibitor *inhibitor;
1198 assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
1200 r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1202 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1204 #if 1 /// elogind needs some extra preparations before connecting...
1205 elogind_manager_startup(m);
1207 /* Connect to console */
1208 r = manager_connect_console(m);
1212 /* Connect to udev */
1213 r = manager_connect_udev(m);
1215 return log_error_errno(r, "Failed to create udev watchers: %m");
1217 /* Connect to the bus */
1218 r = manager_connect_bus(m);
1222 /* Instantiate magic seat 0 */
1223 r = manager_add_seat(m, "seat0", &m->seat0);
1225 return log_error_errno(r, "Failed to add seat0: %m");
1227 r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1229 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1231 /* Deserialize state */
1232 r = manager_enumerate_devices(m);
1234 log_warning_errno(r, "Device enumeration failed: %m");
1236 r = manager_enumerate_seats(m);
1238 log_warning_errno(r, "Seat enumeration failed: %m");
1240 r = manager_enumerate_users(m);
1242 log_warning_errno(r, "User enumeration failed: %m");
1244 r = manager_enumerate_sessions(m);
1246 log_warning_errno(r, "Session enumeration failed: %m");
1248 r = manager_enumerate_inhibitors(m);
1250 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1252 r = manager_enumerate_buttons(m);
1254 log_warning_errno(r, "Button enumeration failed: %m");
1256 /* Remove stale objects before we start them */
1257 manager_gc(m, false);
1259 /* Reserve the special reserved VT */
1260 #if 0 /// elogind does not support autospawning of vts
1261 manager_reserve_vt(m);
1264 /* And start everything */
1265 HASHMAP_FOREACH(seat, m->seats, i)
1268 HASHMAP_FOREACH(user, m->users, i)
1271 HASHMAP_FOREACH(session, m->sessions, i)
1272 session_start(session);
1274 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1275 inhibitor_start(inhibitor);
1277 HASHMAP_FOREACH(button, m->buttons, i)
1278 button_check_switches(button);
1280 manager_dispatch_idle_action(NULL, 0, m);
1285 static int manager_run(Manager *m) {
1291 r = sd_event_get_state(m->event);
1294 if (r == SD_EVENT_FINISHED)
1297 manager_gc(m, true);
1299 r = manager_dispatch_delayed(m, false);
1305 r = sd_event_run(m->event, (uint64_t) -1);
1311 int main(int argc, char *argv[]) {
1315 #if 1 /// perform extra checks for elogind startup
1316 r = elogind_startup(argc, argv);
1318 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1320 elogind_set_program_name(argv[0]);
1321 log_set_target(LOG_TARGET_AUTO);
1322 log_set_facility(LOG_AUTH);
1323 log_parse_environment();
1324 #if ENABLE_DEBUG_ELOGIND
1325 log_set_max_level(LOG_DEBUG);
1326 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1327 #endif // ENABLE_DEBUG_ELOGIND
1332 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1334 log_error("This program takes no arguments.");
1340 r = mac_selinux_init();
1342 log_error_errno(r, "Could not initialize labelling: %m");
1346 /* Always create the directories people can create inotify
1347 * watches in. Note that some applications might check for the
1348 * existence of /run/systemd/seats/ to determine whether
1349 * logind is available, so please always make sure this check
1351 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1352 mkdir_label("/run/systemd/seats", 0755);
1353 mkdir_label("/run/systemd/users", 0755);
1354 mkdir_label("/run/systemd/sessions", 0755);
1356 r = mkdir_label("/run/systemd", 0755);
1357 if ( (r < 0) && (-EEXIST != r) )
1358 return log_error_errno(r, "Failed to create /run/systemd : %m");
1359 r = mkdir_label("/run/systemd/seats", 0755);
1360 if ( r < 0 && (-EEXIST != r) )
1361 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1362 r = mkdir_label("/run/systemd/users", 0755);
1363 if ( r < 0 && (-EEXIST != r) )
1364 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1365 r = mkdir_label("/run/systemd/sessions", 0755);
1366 if ( r < 0 && (-EEXIST != r) )
1367 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1368 r = mkdir_label("/run/systemd/machines", 0755);
1369 if ( r < 0 && (-EEXIST != r) )
1370 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1379 manager_parse_config_file(m);
1381 #if 1 /// elogind needs an Add-On for sleep configuration
1382 elogind_manager_reset_config(m);
1384 r = manager_startup(m);
1386 log_error_errno(r, "Failed to fully start up daemon: %m");
1390 log_debug("elogind running as pid "PID_FMT, getpid_cached());
1394 "STATUS=Processing requests...");
1398 log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1403 "STATUS=Shutting down...");
1407 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;