1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "sd-daemon.h"
30 #include "conf-parser.h"
32 #include "bus-error.h"
34 #include "udev-util.h"
35 #include "formats-util.h"
40 static void manager_free(Manager *m);
42 static Manager *manager_new(void) {
50 m->pin_cgroupfs_fd = -1;
52 m->console_active_fd = -1;
54 /// elogind does not support autospawning of vts
56 m->reserve_vt_fd = -1;
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->lid_switch_ignore_inhibited = true;
69 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
71 m->idle_action_usec = 30 * USEC_PER_MINUTE;
72 m->idle_action = HANDLE_IGNORE;
73 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
75 m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
77 m->devices = hashmap_new(&string_hash_ops);
78 m->seats = hashmap_new(&string_hash_ops);
79 m->sessions = hashmap_new(&string_hash_ops);
80 m->users = hashmap_new(NULL);
81 m->inhibitors = hashmap_new(&string_hash_ops);
82 m->buttons = hashmap_new(&string_hash_ops);
84 m->user_units = hashmap_new(&string_hash_ops);
85 m->session_units = hashmap_new(&string_hash_ops);
87 m->running_as = MANAGER_SYSTEM;
90 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
93 m->kill_exclude_users = strv_new("root", NULL);
94 if (!m->kill_exclude_users)
98 r = manager_setup_cgroup(m);
102 m->suspend_mode = NULL;
103 m->suspend_state = strv_new("mem", "standby", "freeze", NULL);
104 if (!m->suspend_state)
106 m->hibernate_mode = strv_new("platform", "shutdown", NULL);
107 if (!m->hibernate_mode)
109 m->hibernate_state = strv_new("disk", NULL);
110 if (!m->hibernate_state)
112 m->hybrid_sleep_mode = strv_new("suspend", "platform", "shutdown", NULL);
113 if (!m->hybrid_sleep_mode)
115 m->hybrid_sleep_state = strv_new("disk", NULL);
116 if (!m->hybrid_sleep_state)
119 m->udev = udev_new();
123 r = sd_event_default(&m->event);
127 sd_event_set_watchdog(m->event, true);
136 static void manager_free(Manager *m) {
146 while ((session = hashmap_first(m->sessions)))
147 session_free(session);
149 while ((u = hashmap_first(m->users)))
152 while ((d = hashmap_first(m->devices)))
155 while ((s = hashmap_first(m->seats)))
158 while ((i = hashmap_first(m->inhibitors)))
161 while ((b = hashmap_first(m->buttons)))
164 hashmap_free(m->devices);
165 hashmap_free(m->seats);
166 hashmap_free(m->sessions);
167 hashmap_free(m->users);
168 hashmap_free(m->inhibitors);
169 hashmap_free(m->buttons);
171 hashmap_free(m->user_units);
172 hashmap_free(m->session_units);
174 sd_event_source_unref(m->idle_action_event_source);
175 sd_event_source_unref(m->inhibit_timeout_source);
176 sd_event_source_unref(m->scheduled_shutdown_timeout_source);
177 sd_event_source_unref(m->nologin_timeout_source);
178 sd_event_source_unref(m->wall_message_timeout_source);
180 sd_event_source_unref(m->console_active_event_source);
181 sd_event_source_unref(m->udev_seat_event_source);
182 sd_event_source_unref(m->udev_device_event_source);
183 sd_event_source_unref(m->udev_vcsa_event_source);
184 sd_event_source_unref(m->udev_button_event_source);
185 sd_event_source_unref(m->lid_switch_ignore_event_source);
187 safe_close(m->console_active_fd);
189 udev_monitor_unref(m->udev_seat_monitor);
190 udev_monitor_unref(m->udev_device_monitor);
191 udev_monitor_unref(m->udev_vcsa_monitor);
192 udev_monitor_unref(m->udev_button_monitor);
196 if (m->unlink_nologin)
197 unlink("/run/nologin");
199 bus_verify_polkit_async_registry_free(m->polkit_registry);
201 sd_bus_unref(m->bus);
202 sd_event_unref(m->event);
204 /// elogind does not support autospawning of vts
206 safe_close(m->reserve_vt_fd);
209 manager_shutdown_cgroup(m, true);
211 strv_free(m->kill_only_users);
212 strv_free(m->kill_exclude_users);
214 free(m->scheduled_shutdown_type);
215 free(m->scheduled_shutdown_tty);
216 free(m->wall_message);
218 strv_free(m->suspend_mode);
219 strv_free(m->suspend_state);
220 strv_free(m->hibernate_mode);
221 strv_free(m->hibernate_state);
222 strv_free(m->hybrid_sleep_mode);
223 strv_free(m->hybrid_sleep_state);
228 static int manager_enumerate_devices(Manager *m) {
229 struct udev_list_entry *item = NULL, *first = NULL;
230 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
235 /* Loads devices from udev and creates seats for them as
238 e = udev_enumerate_new(m->udev);
242 r = udev_enumerate_add_match_tag(e, "master-of-seat");
246 r = udev_enumerate_add_match_is_initialized(e);
250 r = udev_enumerate_scan_devices(e);
254 first = udev_enumerate_get_list_entry(e);
255 udev_list_entry_foreach(item, first) {
256 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
259 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
263 k = manager_process_seat_device(m, d);
271 static int manager_enumerate_buttons(Manager *m) {
272 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
273 struct udev_list_entry *item = NULL, *first = NULL;
278 /* Loads buttons from udev */
280 if (m->handle_power_key == HANDLE_IGNORE &&
281 m->handle_suspend_key == HANDLE_IGNORE &&
282 m->handle_hibernate_key == HANDLE_IGNORE &&
283 m->handle_lid_switch == HANDLE_IGNORE &&
284 m->handle_lid_switch_docked == HANDLE_IGNORE)
287 e = udev_enumerate_new(m->udev);
291 r = udev_enumerate_add_match_subsystem(e, "input");
295 r = udev_enumerate_add_match_tag(e, "power-switch");
299 r = udev_enumerate_add_match_is_initialized(e);
303 r = udev_enumerate_scan_devices(e);
307 first = udev_enumerate_get_list_entry(e);
308 udev_list_entry_foreach(item, first) {
309 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
312 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
316 k = manager_process_button_device(m, d);
324 static int manager_enumerate_seats(Manager *m) {
325 _cleanup_closedir_ DIR *d = NULL;
331 /* This loads data about seats stored on disk, but does not
332 * actually create any seats. Removes data of seats that no
335 d = opendir("/run/systemd/seats");
340 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 log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
381 FOREACH_DIRENT(de, d, return -errno) {
384 if (!dirent_is_file(de))
387 k = manager_add_user_by_name(m, de->d_name, NULL);
389 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
397 static int manager_enumerate_users(Manager *m) {
398 _cleanup_closedir_ DIR *d = NULL;
404 /* Add lingering users */
405 r = manager_enumerate_linger_users(m);
407 /* Read in user data stored on disk */
408 d = opendir("/run/systemd/users");
413 log_error_errno(errno, "Failed to open /run/systemd/users: %m");
417 FOREACH_DIRENT(de, d, return -errno) {
420 if (!dirent_is_file(de))
423 k = manager_add_user_by_name(m, de->d_name, &u);
425 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
431 user_add_to_gc_queue(u);
441 static int manager_enumerate_sessions(Manager *m) {
442 _cleanup_closedir_ DIR *d = NULL;
448 /* Read in session data stored on disk */
449 d = opendir("/run/systemd/sessions");
454 log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
458 FOREACH_DIRENT(de, d, return -errno) {
462 if (!dirent_is_file(de))
465 if (!session_id_valid(de->d_name)) {
466 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
471 k = manager_add_session(m, de->d_name, &s);
473 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
479 session_add_to_gc_queue(s);
489 static int manager_enumerate_inhibitors(Manager *m) {
490 _cleanup_closedir_ DIR *d = NULL;
496 d = opendir("/run/systemd/inhibit");
501 log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
505 FOREACH_DIRENT(de, d, return -errno) {
509 if (!dirent_is_file(de))
512 k = manager_add_inhibitor(m, de->d_name, &i);
514 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
519 k = inhibitor_load(i);
527 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
528 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
529 Manager *m = userdata;
533 d = udev_monitor_receive_device(m->udev_seat_monitor);
537 manager_process_seat_device(m, d);
541 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
542 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
543 Manager *m = userdata;
547 d = udev_monitor_receive_device(m->udev_device_monitor);
551 manager_process_seat_device(m, d);
555 /// UNNEEDED by elogind
557 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
558 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
559 Manager *m = userdata;
564 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
568 name = udev_device_get_sysname(d);
570 /* Whenever a VCSA device is removed try to reallocate our
571 * VTs, to make sure our auto VTs never go away. */
573 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
574 seat_preallocate_vts(m->seat0);
580 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
581 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
582 Manager *m = userdata;
586 d = udev_monitor_receive_device(m->udev_button_monitor);
590 manager_process_button_device(m, d);
594 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
595 Manager *m = userdata;
599 assert(m->console_active_fd == fd);
601 seat_read_active_vt(m->seat0);
605 /// UNNEEDED by elogind
607 static int manager_reserve_vt(Manager *m) {
608 _cleanup_free_ char *p = NULL;
612 if (m->reserve_vt <= 0)
615 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
618 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
619 if (m->reserve_vt_fd < 0) {
621 /* Don't complain on VT-less systems */
623 log_warning_errno(errno, "Failed to pin reserved VT: %m");
631 static int manager_connect_bus(Manager *m) {
632 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
638 r = sd_bus_default_system(&m->bus);
640 return log_error_errno(r, "Failed to connect to system bus: %m");
642 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
644 return log_error_errno(r, "Failed to add manager object vtable: %m");
646 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
648 return log_error_errno(r, "Failed to add seat object vtable: %m");
650 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
652 return log_error_errno(r, "Failed to add seat enumerator: %m");
654 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
656 return log_error_errno(r, "Failed to add session object vtable: %m");
658 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
660 return log_error_errno(r, "Failed to add session enumerator: %m");
662 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
664 return log_error_errno(r, "Failed to add user object vtable: %m");
666 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
668 return log_error_errno(r, "Failed to add user enumerator: %m");
670 /// elogind does not support systemd action jobs
672 r = sd_bus_add_match(m->bus,
675 "sender='org.freedesktop.systemd1',"
676 "interface='org.freedesktop.systemd1.Manager',"
677 "member='JobRemoved',"
678 "path='/org/freedesktop/systemd1'",
679 match_job_removed, m);
681 log_warning_errno(r, "Failed to add match for JobRemoved: %m");
684 r = sd_bus_add_match(m->bus,
687 "sender='org.freedesktop.systemd1',"
688 "interface='org.freedesktop.systemd1.Manager',"
689 "member='UnitRemoved',"
690 "path='/org/freedesktop/systemd1'",
691 match_unit_removed, m);
693 log_warning_errno(r, "Failed to add match for UnitRemoved: %m");
695 r = sd_bus_add_match(m->bus,
698 "sender='org.freedesktop.systemd1',"
699 "interface='org.freedesktop.DBus.Properties',"
700 "member='PropertiesChanged'",
701 match_properties_changed, m);
703 log_warning_errno(r, "Failed to add match for PropertiesChanged: %m");
705 r = sd_bus_add_match(m->bus,
708 "sender='org.freedesktop.systemd1',"
709 "interface='org.freedesktop.systemd1.Manager',"
710 "member='Reloading',"
711 "path='/org/freedesktop/systemd1'",
714 log_warning_errno(r, "Failed to add match for Reloading: %m");
716 r = sd_bus_call_method(
718 "org.freedesktop.systemd1",
719 "/org/freedesktop/systemd1",
720 "org.freedesktop.systemd1.Manager",
725 log_notice("Failed to enable subscription: %s", bus_error_message(&error, r));
727 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
729 return log_error_errno(r, "Failed to register name: %m");
731 r = sd_bus_attach_event(m->bus, m->event, 0);
733 return log_error_errno(r, "Failed to attach bus to event loop: %m");
738 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
740 Session *active, *iter;
743 * We got a VT-switch signal and we have to acknowledge it immediately.
744 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
745 * old user-space might run multiple sessions on a single VT, *sigh*.
746 * Therefore, we have to iterate all sessions and find one with a vtfd
747 * on the requested VT.
748 * As only VTs with active controllers have VT_PROCESS set, our current
749 * notion of the active VT might be wrong (for instance if the switch
750 * happens while we setup VT_PROCESS). Therefore, read the current VT
751 * first and then use s->active->vtnr as reference. Note that this is
752 * not racy, as no further VT-switch can happen as long as we're in
753 * synchronous VT_PROCESS mode.
757 seat_read_active_vt(m->seat0);
759 active = m->seat0->active;
760 if (!active || active->vtnr < 1) {
761 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
765 if (active->vtfd >= 0) {
766 session_leave_vt(active);
768 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
769 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
770 session_leave_vt(iter);
779 static int manager_connect_console(Manager *m) {
783 assert(m->console_active_fd < 0);
785 /* On certain architectures (S390 and Xen, and containers),
786 /dev/tty0 does not exist, so don't fail if we can't open
788 if (access("/dev/tty0", F_OK) < 0)
791 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
792 if (m->console_active_fd < 0) {
794 /* On some systems the device node /dev/tty0 may exist
795 * even though /sys/class/tty/tty0 does not. */
799 log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
803 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
805 log_error("Failed to watch foreground console");
810 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
811 * as VT-acquire signal. We ignore any acquire-events (yes, we still
812 * have to provide a valid signal-number for it!) and acknowledge all
813 * release events immediately.
816 if (SIGRTMIN + 1 > SIGRTMAX) {
817 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
821 r = ignore_signals(SIGRTMIN + 1, -1);
823 return log_error_errno(r, "Cannot ignore SIGRTMIN + 1: %m");
825 r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1);
827 return log_error_errno(r, "Cannot block SIGRTMIN: %m");
829 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
836 static int manager_connect_udev(Manager *m) {
840 assert(!m->udev_seat_monitor);
841 assert(!m->udev_device_monitor);
842 assert(!m->udev_vcsa_monitor);
843 assert(!m->udev_button_monitor);
845 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
846 if (!m->udev_seat_monitor)
849 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
853 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
857 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);
861 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
862 if (!m->udev_device_monitor)
865 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
869 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
873 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
877 r = udev_monitor_enable_receiving(m->udev_device_monitor);
881 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);
885 /* Don't watch keys if nobody cares */
886 if (m->handle_power_key != HANDLE_IGNORE ||
887 m->handle_suspend_key != HANDLE_IGNORE ||
888 m->handle_hibernate_key != HANDLE_IGNORE ||
889 m->handle_lid_switch != HANDLE_IGNORE ||
890 m->handle_lid_switch_docked != HANDLE_IGNORE) {
892 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
893 if (!m->udev_button_monitor)
896 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
900 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
904 r = udev_monitor_enable_receiving(m->udev_button_monitor);
908 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);
913 /* Don't bother watching VCSA devices, if nobody cares */
914 /// elogind does not support autospawning of vts
916 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
918 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
919 if (!m->udev_vcsa_monitor)
922 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
926 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
930 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);
939 static void manager_gc(Manager *m, bool drop_not_started) {
946 while ((seat = m->seat_gc_queue)) {
947 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
948 seat->in_gc_queue = false;
950 if (!seat_check_gc(seat, drop_not_started)) {
951 seat_stop(seat, false);
956 while ((session = m->session_gc_queue)) {
957 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
958 session->in_gc_queue = false;
960 /* First, if we are not closing yet, initiate stopping */
961 if (!session_check_gc(session, drop_not_started) &&
962 session_get_state(session) != SESSION_CLOSING)
963 session_stop(session, false);
965 /* Normally, this should make the session referenced
966 * again, if it doesn't then let's get rid of it
968 if (!session_check_gc(session, drop_not_started)) {
969 session_finalize(session);
970 session_free(session);
974 while ((user = m->user_gc_queue)) {
975 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
976 user->in_gc_queue = false;
978 /* First step: queue stop jobs */
979 if (!user_check_gc(user, drop_not_started))
980 user_stop(user, false);
982 /* Second step: finalize user */
983 if (!user_check_gc(user, drop_not_started)) {
990 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
991 Manager *m = userdata;
992 struct dual_timestamp since;
998 if (m->idle_action == HANDLE_IGNORE ||
999 m->idle_action_usec <= 0)
1002 n = now(CLOCK_MONOTONIC);
1004 r = manager_get_idle_hint(m, &since);
1006 /* Not idle. Let's check if after a timeout it might be idle then. */
1007 elapse = n + m->idle_action_usec;
1009 /* Idle! Let's see if it's time to do something, or if
1010 * we shall sleep for longer. */
1012 if (n >= since.monotonic + m->idle_action_usec &&
1013 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1014 log_info("System idle. Taking action.");
1016 manager_handle_action(m, 0, m->idle_action, false, false);
1017 m->idle_action_not_before_usec = n;
1020 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1023 if (!m->idle_action_event_source) {
1025 r = sd_event_add_time(
1027 &m->idle_action_event_source,
1029 elapse, USEC_PER_SEC*30,
1030 manager_dispatch_idle_action, m);
1032 return log_error_errno(r, "Failed to add idle event source: %m");
1034 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1036 return log_error_errno(r, "Failed to set idle event source priority: %m");
1038 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1040 return log_error_errno(r, "Failed to set idle event timer: %m");
1042 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1044 return log_error_errno(r, "Failed to enable idle event timer: %m");
1050 static int manager_startup(Manager *m) {
1056 Inhibitor *inhibitor;
1061 /* Connect to console */
1062 r = manager_connect_console(m);
1066 /* Connect to udev */
1067 r = manager_connect_udev(m);
1069 return log_error_errno(r, "Failed to create udev watchers: %m");
1071 /* Connect to the bus */
1072 r = manager_connect_bus(m);
1076 /* Instantiate magic seat 0 */
1077 r = manager_add_seat(m, "seat0", &m->seat0);
1079 return log_error_errno(r, "Failed to add seat0: %m");
1081 r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1083 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1085 /* Deserialize state */
1086 r = manager_enumerate_devices(m);
1088 log_warning_errno(r, "Device enumeration failed: %m");
1090 r = manager_enumerate_seats(m);
1092 log_warning_errno(r, "Seat enumeration failed: %m");
1094 r = manager_enumerate_users(m);
1096 log_warning_errno(r, "User enumeration failed: %m");
1098 r = manager_enumerate_sessions(m);
1100 log_warning_errno(r, "Session enumeration failed: %m");
1102 r = manager_enumerate_inhibitors(m);
1104 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1106 r = manager_enumerate_buttons(m);
1108 log_warning_errno(r, "Button enumeration failed: %m");
1110 /* Remove stale objects before we start them */
1111 manager_gc(m, false);
1113 /* Reserve the special reserved VT */
1114 /// elogind does not support autospawning of vts
1116 manager_reserve_vt(m);
1119 /* And start everything */
1120 HASHMAP_FOREACH(seat, m->seats, i)
1123 HASHMAP_FOREACH(user, m->users, i)
1126 HASHMAP_FOREACH(session, m->sessions, i)
1127 session_start(session);
1129 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1130 inhibitor_start(inhibitor);
1132 HASHMAP_FOREACH(button, m->buttons, i)
1133 button_check_switches(button);
1135 manager_dispatch_idle_action(NULL, 0, m);
1140 static int manager_run(Manager *m) {
1146 r = sd_event_get_state(m->event);
1149 if (r == SD_EVENT_FINISHED)
1152 manager_gc(m, true);
1154 r = sd_event_run(m->event, (uint64_t) -1);
1160 static int manager_parse_config_file(Manager *m) {
1161 const char *unit = NULL, *logind_conf, *sections;
1163 bool relaxed = false, allow_include = false, warn = true;
1167 /// elogind parses its own config file
1169 return config_parse_many("/etc/systemd/logind.conf",
1170 CONF_DIRS_NULSTR("systemd/logind.conf"),
1172 config_item_perf_lookup, logind_gperf_lookup,
1176 logind_conf = getenv("ELOGIND_CONF_FILE");
1178 logind_conf = PKGSYSCONFDIR "/logind.conf";
1179 sections = "Login\0Sleep\0";
1181 return config_parse(unit, logind_conf, file, sections,
1182 config_item_perf_lookup, logind_gperf_lookup,
1183 relaxed, allow_include, warn, m);
1186 int main(int argc, char *argv[]) {
1190 log_set_target(LOG_TARGET_AUTO);
1191 log_set_facility(LOG_AUTH);
1192 log_parse_environment();
1198 log_error("This program takes no arguments.");
1203 /* Always create the directories people can create inotify
1204 * watches in. Note that some applications might check for the
1205 * existence of /run/systemd/seats/ to determine whether
1206 * logind is available, so please always make sure this check
1208 r = mkdir_label("/run/systemd", 0755);
1209 if ( (r < 0) && (-EEXIST != r) )
1210 return log_error_errno(r, "Failed to create /run/systemd : %m");
1211 r = mkdir_label("/run/systemd/seats", 0755);
1212 if ( r < 0 && (-EEXIST != r) )
1213 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1214 r = mkdir_label("/run/systemd/users", 0755);
1215 if ( r < 0 && (-EEXIST != r) )
1216 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1217 r = mkdir_label("/run/systemd/sessions", 0755);
1218 if ( r < 0 && (-EEXIST != r) )
1219 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1220 r = mkdir_label("/run/systemd/machines", 0755);
1221 if ( r < 0 && (-EEXIST != r) )
1222 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1230 manager_parse_config_file(m);
1232 r = manager_startup(m);
1234 log_error_errno(r, "Failed to fully start up daemon: %m");
1238 log_debug("logind running as pid "PID_FMT, getpid());
1242 "STATUS=Processing requests...");
1246 log_debug("logind stopped as pid "PID_FMT, getpid());
1251 "STATUS=Shutting down...");
1255 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;