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/>.
27 #include <sys/epoll.h>
29 #include <sys/timerfd.h>
31 #include <systemd/sd-daemon.h>
34 #include "dbus-common.h"
35 #include "dbus-loop.h"
37 #include "conf-parser.h"
40 Manager *manager_new(void) {
47 m->console_active_fd = -1;
51 m->udev_button_fd = -1;
53 m->reserve_vt_fd = -1;
57 m->inhibit_delay_max = 5 * USEC_PER_SEC;
58 m->handle_power_key = HANDLE_POWEROFF;
59 m->handle_suspend_key = HANDLE_SUSPEND;
60 m->handle_hibernate_key = HANDLE_HIBERNATE;
61 m->handle_lid_switch = HANDLE_SUSPEND;
62 m->lid_switch_ignore_inhibited = true;
64 m->idle_action_fd = -1;
65 m->idle_action_usec = 30 * USEC_PER_MINUTE;
66 m->idle_action = HANDLE_IGNORE;
67 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
69 m->devices = hashmap_new(string_hash_func, string_compare_func);
70 m->seats = hashmap_new(string_hash_func, string_compare_func);
71 m->sessions = hashmap_new(string_hash_func, string_compare_func);
72 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
73 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
74 m->buttons = hashmap_new(string_hash_func, string_compare_func);
75 m->busnames = hashmap_new(string_hash_func, string_compare_func);
77 m->user_units = hashmap_new(string_hash_func, string_compare_func);
78 m->session_units = hashmap_new(string_hash_func, string_compare_func);
80 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
81 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
82 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
84 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
85 !m->user_units || !m->session_units ||
86 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
91 m->kill_exclude_users = strv_new("root", NULL);
92 if (!m->kill_exclude_users) {
106 void manager_free(Manager *m) {
117 while ((session = hashmap_first(m->sessions)))
118 session_free(session);
120 while ((u = hashmap_first(m->users)))
123 while ((d = hashmap_first(m->devices)))
126 while ((s = hashmap_first(m->seats)))
129 while ((i = hashmap_first(m->inhibitors)))
132 while ((b = hashmap_first(m->buttons)))
135 while ((n = hashmap_first(m->busnames)))
136 free(hashmap_remove(m->busnames, n));
138 hashmap_free(m->devices);
139 hashmap_free(m->seats);
140 hashmap_free(m->sessions);
141 hashmap_free(m->users);
142 hashmap_free(m->inhibitors);
143 hashmap_free(m->buttons);
144 hashmap_free(m->busnames);
146 hashmap_free(m->user_units);
147 hashmap_free(m->session_units);
149 hashmap_free(m->session_fds);
150 hashmap_free(m->inhibitor_fds);
151 hashmap_free(m->button_fds);
153 if (m->console_active_fd >= 0)
154 close_nointr_nofail(m->console_active_fd);
156 if (m->udev_seat_monitor)
157 udev_monitor_unref(m->udev_seat_monitor);
158 if (m->udev_device_monitor)
159 udev_monitor_unref(m->udev_device_monitor);
160 if (m->udev_vcsa_monitor)
161 udev_monitor_unref(m->udev_vcsa_monitor);
162 if (m->udev_button_monitor)
163 udev_monitor_unref(m->udev_button_monitor);
169 dbus_connection_flush(m->bus);
170 dbus_connection_close(m->bus);
171 dbus_connection_unref(m->bus);
175 close_nointr_nofail(m->bus_fd);
177 if (m->epoll_fd >= 0)
178 close_nointr_nofail(m->epoll_fd);
180 if (m->reserve_vt_fd >= 0)
181 close_nointr_nofail(m->reserve_vt_fd);
183 if (m->idle_action_fd >= 0)
184 close_nointr_nofail(m->idle_action_fd);
186 strv_free(m->kill_only_users);
187 strv_free(m->kill_exclude_users);
193 int manager_enumerate_devices(Manager *m) {
194 struct udev_list_entry *item = NULL, *first = NULL;
195 struct udev_enumerate *e;
200 /* Loads devices from udev and creates seats for them as
203 e = udev_enumerate_new(m->udev);
209 r = udev_enumerate_add_match_tag(e, "master-of-seat");
213 r = udev_enumerate_scan_devices(e);
217 first = udev_enumerate_get_list_entry(e);
218 udev_list_entry_foreach(item, first) {
219 struct udev_device *d;
222 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
228 k = manager_process_seat_device(m, d);
229 udev_device_unref(d);
237 udev_enumerate_unref(e);
242 int manager_enumerate_buttons(Manager *m) {
243 struct udev_list_entry *item = NULL, *first = NULL;
244 struct udev_enumerate *e;
249 /* Loads buttons from udev */
251 if (m->handle_power_key == HANDLE_IGNORE &&
252 m->handle_suspend_key == HANDLE_IGNORE &&
253 m->handle_hibernate_key == HANDLE_IGNORE &&
254 m->handle_lid_switch == HANDLE_IGNORE)
257 e = udev_enumerate_new(m->udev);
263 r = udev_enumerate_add_match_subsystem(e, "input");
267 r = udev_enumerate_add_match_tag(e, "power-switch");
271 r = udev_enumerate_scan_devices(e);
275 first = udev_enumerate_get_list_entry(e);
276 udev_list_entry_foreach(item, first) {
277 struct udev_device *d;
280 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
286 k = manager_process_button_device(m, d);
287 udev_device_unref(d);
295 udev_enumerate_unref(e);
300 int manager_enumerate_seats(Manager *m) {
301 _cleanup_closedir_ DIR *d = NULL;
307 /* This loads data about seats stored on disk, but does not
308 * actually create any seats. Removes data of seats that no
311 d = opendir("/run/systemd/seats");
316 log_error("Failed to open /run/systemd/seats: %m");
320 FOREACH_DIRENT(de, d, return -errno) {
324 if (!dirent_is_file(de))
327 s = hashmap_get(m->seats, de->d_name);
329 unlinkat(dirfd(d), de->d_name, 0);
341 static int manager_enumerate_linger_users(Manager *m) {
342 _cleanup_closedir_ DIR *d = NULL;
348 d = opendir("/var/lib/systemd/linger");
353 log_error("Failed to open /var/lib/systemd/linger/: %m");
357 FOREACH_DIRENT(de, d, return -errno) {
360 if (!dirent_is_file(de))
363 k = manager_add_user_by_name(m, de->d_name, NULL);
365 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
373 int manager_enumerate_users(Manager *m) {
374 _cleanup_closedir_ DIR *d = NULL;
380 /* Add lingering users */
381 r = manager_enumerate_linger_users(m);
383 /* Read in user data stored on disk */
384 d = opendir("/run/systemd/users");
389 log_error("Failed to open /run/systemd/users: %m");
393 FOREACH_DIRENT(de, d, return -errno) {
396 if (!dirent_is_file(de))
399 k = manager_add_user_by_name(m, de->d_name, &u);
401 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
407 user_add_to_gc_queue(u);
417 int manager_enumerate_sessions(Manager *m) {
418 _cleanup_closedir_ DIR *d = NULL;
424 /* Read in session data stored on disk */
425 d = opendir("/run/systemd/sessions");
430 log_error("Failed to open /run/systemd/sessions: %m");
434 FOREACH_DIRENT(de, d, return -errno) {
438 if (!dirent_is_file(de))
441 if (!session_id_valid(de->d_name)) {
442 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
447 k = manager_add_session(m, de->d_name, &s);
449 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
455 session_add_to_gc_queue(s);
465 int manager_enumerate_inhibitors(Manager *m) {
466 _cleanup_closedir_ DIR *d = NULL;
472 d = opendir("/run/systemd/inhibit");
477 log_error("Failed to open /run/systemd/inhibit: %m");
481 FOREACH_DIRENT(de, d, return -errno) {
485 if (!dirent_is_file(de))
488 k = manager_add_inhibitor(m, de->d_name, &i);
490 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
495 k = inhibitor_load(i);
503 int manager_dispatch_seat_udev(Manager *m) {
504 struct udev_device *d;
509 d = udev_monitor_receive_device(m->udev_seat_monitor);
513 r = manager_process_seat_device(m, d);
514 udev_device_unref(d);
519 static int manager_dispatch_device_udev(Manager *m) {
520 struct udev_device *d;
525 d = udev_monitor_receive_device(m->udev_device_monitor);
529 r = manager_process_seat_device(m, d);
530 udev_device_unref(d);
535 int manager_dispatch_vcsa_udev(Manager *m) {
536 struct udev_device *d;
542 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
546 name = udev_device_get_sysname(d);
548 /* Whenever a VCSA device is removed try to reallocate our
549 * VTs, to make sure our auto VTs never go away. */
551 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
552 r = seat_preallocate_vts(m->seat0);
554 udev_device_unref(d);
559 int manager_dispatch_button_udev(Manager *m) {
560 struct udev_device *d;
565 d = udev_monitor_receive_device(m->udev_button_monitor);
569 r = manager_process_button_device(m, d);
570 udev_device_unref(d);
575 int manager_dispatch_console(Manager *m) {
579 seat_read_active_vt(m->seat0);
584 static int manager_reserve_vt(Manager *m) {
585 _cleanup_free_ char *p = NULL;
589 if (m->reserve_vt <= 0)
592 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
595 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
596 if (m->reserve_vt_fd < 0) {
598 /* Don't complain on VT-less systems */
600 log_warning("Failed to pin reserved VT: %m");
607 static void manager_dispatch_other(Manager *m, int fd) {
615 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
617 assert(s->fifo_fd == fd);
618 session_remove_fifo(s);
623 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
625 assert(i->fifo_fd == fd);
631 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
638 assert_not_reached("Got event for unknown fd");
641 static int manager_connect_bus(Manager *m) {
644 struct epoll_event ev = {
651 assert(m->bus_fd < 0);
653 dbus_error_init(&error);
655 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
657 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
662 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
663 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
664 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
665 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
666 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
671 dbus_bus_add_match(m->bus,
673 "sender='"DBUS_SERVICE_DBUS"',"
674 "interface='"DBUS_INTERFACE_DBUS"',"
675 "member='NameOwnerChanged',"
676 "path='"DBUS_PATH_DBUS"'",
678 if (dbus_error_is_set(&error)) {
679 log_error("Failed to add match for NameOwnerChanged: %s", bus_error_message(&error));
680 dbus_error_free(&error);
683 dbus_bus_add_match(m->bus,
685 "sender='org.freedesktop.systemd1',"
686 "interface='org.freedesktop.systemd1.Manager',"
687 "member='JobRemoved',"
688 "path='/org/freedesktop/systemd1'",
690 if (dbus_error_is_set(&error)) {
691 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
692 dbus_error_free(&error);
695 dbus_bus_add_match(m->bus,
697 "sender='org.freedesktop.systemd1',"
698 "interface='org.freedesktop.systemd1.Manager',"
699 "member='UnitRemoved',"
700 "path='/org/freedesktop/systemd1'",
702 if (dbus_error_is_set(&error)) {
703 log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
704 dbus_error_free(&error);
707 dbus_bus_add_match(m->bus,
709 "sender='org.freedesktop.systemd1',"
710 "interface='org.freedesktop.DBus.Properties',"
711 "member='PropertiesChanged'",
713 if (dbus_error_is_set(&error)) {
714 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
715 dbus_error_free(&error);
718 dbus_bus_add_match(m->bus,
720 "sender='org.freedesktop.systemd1',"
721 "interface='org.freedesktop.systemd1.Manager',"
722 "member='Reloading',"
723 "path='/org/freedesktop/systemd1'",
725 if (dbus_error_is_set(&error)) {
726 log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
727 dbus_error_free(&error);
730 r = bus_method_call_with_reply(
732 "org.freedesktop.systemd1",
733 "/org/freedesktop/systemd1",
734 "org.freedesktop.systemd1.Manager",
740 log_error("Failed to enable subscription: %s", bus_error(&error, r));
741 dbus_error_free(&error);
744 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
745 if (dbus_error_is_set(&error)) {
746 log_error("Failed to register name on bus: %s", bus_error_message(&error));
751 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
752 log_error("Failed to acquire name.");
757 m->bus_fd = bus_loop_open(m->bus);
763 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
769 dbus_error_free(&error);
774 static int manager_connect_console(Manager *m) {
775 struct epoll_event ev = {
777 .data.u32 = FD_CONSOLE,
781 assert(m->console_active_fd < 0);
783 /* On certain architectures (S390 and Xen, and containers),
784 /dev/tty0 does not exist, so don't fail if we can't open
786 if (access("/dev/tty0", F_OK) < 0) {
787 m->console_active_fd = -1;
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("Failed to open /sys/class/tty/tty0/active: %m");
803 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
809 static int manager_connect_udev(Manager *m) {
811 struct epoll_event ev = {
813 .data.u32 = FD_SEAT_UDEV,
817 assert(!m->udev_seat_monitor);
818 assert(!m->udev_device_monitor);
819 assert(!m->udev_vcsa_monitor);
820 assert(!m->udev_button_monitor);
822 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
823 if (!m->udev_seat_monitor)
826 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
830 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
834 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
836 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
839 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
840 if (!m->udev_device_monitor)
843 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
847 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
851 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
855 r = udev_monitor_enable_receiving(m->udev_device_monitor);
859 m->udev_device_fd = udev_monitor_get_fd(m->udev_device_monitor);
862 ev.data.u32 = FD_DEVICE_UDEV;
863 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_device_fd, &ev) < 0)
866 /* Don't watch keys if nobody cares */
867 if (m->handle_power_key != HANDLE_IGNORE ||
868 m->handle_suspend_key != HANDLE_IGNORE ||
869 m->handle_hibernate_key != HANDLE_IGNORE ||
870 m->handle_lid_switch != HANDLE_IGNORE) {
872 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
873 if (!m->udev_button_monitor)
876 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
880 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
884 r = udev_monitor_enable_receiving(m->udev_button_monitor);
888 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
892 ev.data.u32 = FD_BUTTON_UDEV;
893 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
897 /* Don't bother watching VCSA devices, if nobody cares */
898 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
900 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
901 if (!m->udev_vcsa_monitor)
904 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
908 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
912 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
916 ev.data.u32 = FD_VCSA_UDEV;
917 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
924 void manager_gc(Manager *m, bool drop_not_started) {
931 while ((seat = m->seat_gc_queue)) {
932 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
933 seat->in_gc_queue = false;
935 if (seat_check_gc(seat, drop_not_started) == 0) {
941 while ((session = m->session_gc_queue)) {
942 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
943 session->in_gc_queue = false;
945 if (session_check_gc(session, drop_not_started) == 0) {
946 session_stop(session);
947 session_finalize(session);
948 session_free(session);
952 while ((user = m->user_gc_queue)) {
953 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
954 user->in_gc_queue = false;
956 if (user_check_gc(user, drop_not_started) == 0) {
964 int manager_dispatch_idle_action(Manager *m) {
965 struct dual_timestamp since;
966 struct itimerspec its = {};
972 if (m->idle_action == HANDLE_IGNORE ||
973 m->idle_action_usec <= 0) {
978 n = now(CLOCK_MONOTONIC);
980 r = manager_get_idle_hint(m, &since);
982 /* Not idle. Let's check if after a timeout it might be idle then. */
983 timespec_store(&its.it_value, n + m->idle_action_usec);
985 /* Idle! Let's see if it's time to do something, or if
986 * we shall sleep for longer. */
988 if (n >= since.monotonic + m->idle_action_usec &&
989 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
990 log_info("System idle. Taking action.");
992 manager_handle_action(m, 0, m->idle_action, false, false);
993 m->idle_action_not_before_usec = n;
996 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
999 if (m->idle_action_fd < 0) {
1000 struct epoll_event ev = {
1002 .data.u32 = FD_IDLE_ACTION,
1005 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1006 if (m->idle_action_fd < 0) {
1007 log_error("Failed to create idle action timer: %m");
1012 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1013 log_error("Failed to add idle action timer to epoll: %m");
1019 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1020 log_error("Failed to reset timerfd: %m");
1028 if (m->idle_action_fd >= 0) {
1029 close_nointr_nofail(m->idle_action_fd);
1030 m->idle_action_fd = -1;
1035 int manager_startup(Manager *m) {
1040 Inhibitor *inhibitor;
1044 assert(m->epoll_fd <= 0);
1046 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1047 if (m->epoll_fd < 0)
1050 /* Connect to console */
1051 r = manager_connect_console(m);
1055 /* Connect to udev */
1056 r = manager_connect_udev(m);
1060 /* Connect to the bus */
1061 r = manager_connect_bus(m);
1065 /* Instantiate magic seat 0 */
1066 r = manager_add_seat(m, "seat0", &m->seat0);
1070 /* Deserialize state */
1071 r = manager_enumerate_devices(m);
1073 log_warning("Device enumeration failed: %s", strerror(-r));
1075 r = manager_enumerate_seats(m);
1077 log_warning("Seat enumeration failed: %s", strerror(-r));
1079 r = manager_enumerate_users(m);
1081 log_warning("User enumeration failed: %s", strerror(-r));
1083 r = manager_enumerate_sessions(m);
1085 log_warning("Session enumeration failed: %s", strerror(-r));
1087 r = manager_enumerate_inhibitors(m);
1089 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1091 r = manager_enumerate_buttons(m);
1093 log_warning("Button enumeration failed: %s", strerror(-r));
1095 /* Remove stale objects before we start them */
1096 manager_gc(m, false);
1098 /* Reserve the special reserved VT */
1099 manager_reserve_vt(m);
1101 /* And start everything */
1102 HASHMAP_FOREACH(seat, m->seats, i)
1105 HASHMAP_FOREACH(user, m->users, i)
1108 HASHMAP_FOREACH(session, m->sessions, i)
1109 session_start(session);
1111 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1112 inhibitor_start(inhibitor);
1114 manager_dispatch_idle_action(m);
1119 static int manager_recheck_buttons(Manager *m) {
1126 HASHMAP_FOREACH(b, m->buttons, i) {
1129 q = button_recheck(b);
1139 int manager_run(Manager *m) {
1143 struct epoll_event event;
1147 manager_gc(m, true);
1149 if (manager_dispatch_delayed(m) > 0)
1152 if (manager_recheck_buttons(m) > 0)
1155 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1158 manager_gc(m, true);
1160 if (m->action_what != 0 && !m->action_job) {
1163 x = now(CLOCK_MONOTONIC);
1164 y = m->action_timestamp + m->inhibit_delay_max;
1166 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1169 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1171 if (errno == EINTR || errno == EAGAIN)
1174 log_error("epoll() failed: %m");
1181 switch (event.data.u32) {
1184 manager_dispatch_seat_udev(m);
1187 case FD_DEVICE_UDEV:
1188 manager_dispatch_device_udev(m);
1192 manager_dispatch_vcsa_udev(m);
1195 case FD_BUTTON_UDEV:
1196 manager_dispatch_button_udev(m);
1200 manager_dispatch_console(m);
1203 case FD_IDLE_ACTION:
1204 manager_dispatch_idle_action(m);
1208 bus_loop_dispatch(m->bus_fd);
1212 if (event.data.u32 >= FD_OTHER_BASE)
1213 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1220 static int manager_parse_config_file(Manager *m) {
1221 static const char fn[] = "/etc/systemd/logind.conf";
1222 _cleanup_fclose_ FILE *f = NULL;
1227 f = fopen(fn, "re");
1229 if (errno == ENOENT)
1232 log_warning("Failed to open configuration file %s: %m", fn);
1236 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1237 (void*) logind_gperf_lookup, false, false, m);
1239 log_warning("Failed to parse configuration file: %s", strerror(-r));
1244 int main(int argc, char *argv[]) {
1248 log_set_target(LOG_TARGET_AUTO);
1249 log_set_facility(LOG_AUTH);
1250 log_parse_environment();
1256 log_error("This program takes no arguments.");
1261 /* Always create the directories people can create inotify
1262 * watches in. Note that some applications might check for the
1263 * existence of /run/systemd/seats/ to determine whether
1264 * logind is available, so please always make sure this check
1266 mkdir_label("/run/systemd/seats", 0755);
1267 mkdir_label("/run/systemd/users", 0755);
1268 mkdir_label("/run/systemd/sessions", 0755);
1276 manager_parse_config_file(m);
1278 r = manager_startup(m);
1280 log_error("Failed to fully start up daemon: %s", strerror(-r));
1284 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1288 "STATUS=Processing requests...");
1292 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1296 "STATUS=Shutting down...");
1301 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;