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 <sys/epoll.h>
29 #include <sys/ioctl.h>
31 #include <sys/timerfd.h>
33 #include <systemd/sd-daemon.h>
36 #include "dbus-common.h"
37 #include "dbus-loop.h"
39 #include "conf-parser.h"
42 Manager *manager_new(void) {
49 m->console_active_fd = -1;
53 m->udev_button_fd = -1;
55 m->reserve_vt_fd = -1;
59 m->inhibit_delay_max = 5 * USEC_PER_SEC;
60 m->handle_power_key = HANDLE_POWEROFF;
61 m->handle_suspend_key = HANDLE_SUSPEND;
62 m->handle_hibernate_key = HANDLE_HIBERNATE;
63 m->handle_lid_switch = HANDLE_SUSPEND;
64 m->lid_switch_ignore_inhibited = true;
66 m->idle_action_fd = -1;
67 m->idle_action_usec = 30 * USEC_PER_MINUTE;
68 m->idle_action = HANDLE_IGNORE;
69 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
71 m->devices = hashmap_new(string_hash_func, string_compare_func);
72 m->seats = hashmap_new(string_hash_func, string_compare_func);
73 m->sessions = hashmap_new(string_hash_func, string_compare_func);
74 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
75 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
76 m->buttons = hashmap_new(string_hash_func, string_compare_func);
78 m->user_units = hashmap_new(string_hash_func, string_compare_func);
79 m->session_units = hashmap_new(string_hash_func, string_compare_func);
81 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
82 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
83 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
85 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
86 !m->user_units || !m->session_units ||
87 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
92 m->kill_exclude_users = strv_new("root", NULL);
93 if (!m->kill_exclude_users) {
107 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 hashmap_free(m->devices);
136 hashmap_free(m->seats);
137 hashmap_free(m->sessions);
138 hashmap_free(m->users);
139 hashmap_free(m->inhibitors);
140 hashmap_free(m->buttons);
142 hashmap_free(m->user_units);
143 hashmap_free(m->session_units);
145 hashmap_free(m->session_fds);
146 hashmap_free(m->inhibitor_fds);
147 hashmap_free(m->button_fds);
149 if (m->console_active_fd >= 0)
150 close_nointr_nofail(m->console_active_fd);
152 if (m->udev_seat_monitor)
153 udev_monitor_unref(m->udev_seat_monitor);
154 if (m->udev_vcsa_monitor)
155 udev_monitor_unref(m->udev_vcsa_monitor);
156 if (m->udev_button_monitor)
157 udev_monitor_unref(m->udev_button_monitor);
163 dbus_connection_flush(m->bus);
164 dbus_connection_close(m->bus);
165 dbus_connection_unref(m->bus);
169 close_nointr_nofail(m->bus_fd);
171 if (m->epoll_fd >= 0)
172 close_nointr_nofail(m->epoll_fd);
174 if (m->reserve_vt_fd >= 0)
175 close_nointr_nofail(m->reserve_vt_fd);
177 if (m->idle_action_fd >= 0)
178 close_nointr_nofail(m->idle_action_fd);
180 strv_free(m->kill_only_users);
181 strv_free(m->kill_exclude_users);
187 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
193 d = hashmap_get(m->devices, sysfs);
201 d = device_new(m, sysfs);
211 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
217 s = hashmap_get(m->seats, id);
235 int manager_add_session(Manager *m, const char *id, Session **_session) {
241 s = hashmap_get(m->sessions, id);
249 s = session_new(m, id);
259 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
265 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
273 u = user_new(m, uid, gid, name);
283 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
291 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
295 return manager_add_user(m, uid, gid, name, _user);
298 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
306 return errno ? -errno : -ENOENT;
308 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
311 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
317 i = hashmap_get(m->inhibitors, id);
325 i = inhibitor_new(m, id);
335 int manager_add_button(Manager *m, const char *name, Button **_button) {
341 b = hashmap_get(m->buttons, name);
349 b = button_new(m, name);
359 int manager_process_seat_device(Manager *m, struct udev_device *d) {
365 if (streq_ptr(udev_device_get_action(d), "remove")) {
367 device = hashmap_get(m->devices, udev_device_get_syspath(d));
371 seat_add_to_gc_queue(device->seat);
378 sn = udev_device_get_property_value(d, "ID_SEAT");
382 if (!seat_name_is_valid(sn)) {
383 log_warning("Device with invalid seat name %s found, ignoring.", sn);
387 r = manager_add_device(m, udev_device_get_syspath(d), &device);
391 r = manager_add_seat(m, sn, &seat);
399 device_attach(device, seat);
406 int manager_process_button_device(Manager *m, struct udev_device *d) {
413 if (streq_ptr(udev_device_get_action(d), "remove")) {
415 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
424 r = manager_add_button(m, udev_device_get_sysname(d), &b);
428 sn = udev_device_get_property_value(d, "ID_SEAT");
432 button_set_seat(b, sn);
439 int manager_enumerate_devices(Manager *m) {
440 struct udev_list_entry *item = NULL, *first = NULL;
441 struct udev_enumerate *e;
446 /* Loads devices from udev and creates seats for them as
449 e = udev_enumerate_new(m->udev);
455 r = udev_enumerate_add_match_tag(e, "master-of-seat");
459 r = udev_enumerate_scan_devices(e);
463 first = udev_enumerate_get_list_entry(e);
464 udev_list_entry_foreach(item, first) {
465 struct udev_device *d;
468 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
474 k = manager_process_seat_device(m, d);
475 udev_device_unref(d);
483 udev_enumerate_unref(e);
488 int manager_enumerate_buttons(Manager *m) {
489 struct udev_list_entry *item = NULL, *first = NULL;
490 struct udev_enumerate *e;
495 /* Loads buttons from udev */
497 if (m->handle_power_key == HANDLE_IGNORE &&
498 m->handle_suspend_key == HANDLE_IGNORE &&
499 m->handle_hibernate_key == HANDLE_IGNORE &&
500 m->handle_lid_switch == HANDLE_IGNORE)
503 e = udev_enumerate_new(m->udev);
509 r = udev_enumerate_add_match_subsystem(e, "input");
513 r = udev_enumerate_add_match_tag(e, "power-switch");
517 r = udev_enumerate_scan_devices(e);
521 first = udev_enumerate_get_list_entry(e);
522 udev_list_entry_foreach(item, first) {
523 struct udev_device *d;
526 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
532 k = manager_process_button_device(m, d);
533 udev_device_unref(d);
541 udev_enumerate_unref(e);
546 int manager_enumerate_seats(Manager *m) {
547 _cleanup_closedir_ DIR *d = NULL;
553 /* This loads data about seats stored on disk, but does not
554 * actually create any seats. Removes data of seats that no
557 d = opendir("/run/systemd/seats");
562 log_error("Failed to open /run/systemd/seats: %m");
566 FOREACH_DIRENT(de, d, return -errno) {
570 if (!dirent_is_file(de))
573 s = hashmap_get(m->seats, de->d_name);
575 unlinkat(dirfd(d), de->d_name, 0);
587 static int manager_enumerate_linger_users(Manager *m) {
588 _cleanup_closedir_ DIR *d = NULL;
594 d = opendir("/var/lib/systemd/linger");
599 log_error("Failed to open /var/lib/systemd/linger/: %m");
603 FOREACH_DIRENT(de, d, return -errno) {
606 if (!dirent_is_file(de))
609 k = manager_add_user_by_name(m, de->d_name, NULL);
611 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
619 int manager_enumerate_users(Manager *m) {
620 _cleanup_closedir_ DIR *d = NULL;
626 /* Add lingering users */
627 r = manager_enumerate_linger_users(m);
629 /* Read in user data stored on disk */
630 d = opendir("/run/systemd/users");
635 log_error("Failed to open /run/systemd/users: %m");
639 FOREACH_DIRENT(de, d, return -errno) {
642 if (!dirent_is_file(de))
645 k = manager_add_user_by_name(m, de->d_name, &u);
647 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
653 user_add_to_gc_queue(u);
663 int manager_enumerate_sessions(Manager *m) {
664 _cleanup_closedir_ DIR *d = NULL;
670 /* Read in session data stored on disk */
671 d = opendir("/run/systemd/sessions");
676 log_error("Failed to open /run/systemd/sessions: %m");
680 FOREACH_DIRENT(de, d, return -errno) {
684 if (!dirent_is_file(de))
687 k = manager_add_session(m, de->d_name, &s);
689 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
695 session_add_to_gc_queue(s);
705 int manager_enumerate_inhibitors(Manager *m) {
706 _cleanup_closedir_ DIR *d = NULL;
712 d = opendir("/run/systemd/inhibit");
717 log_error("Failed to open /run/systemd/inhibit: %m");
721 FOREACH_DIRENT(de, d, return -errno) {
725 if (!dirent_is_file(de))
728 k = manager_add_inhibitor(m, de->d_name, &i);
730 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
735 k = inhibitor_load(i);
743 int manager_dispatch_seat_udev(Manager *m) {
744 struct udev_device *d;
749 d = udev_monitor_receive_device(m->udev_seat_monitor);
753 r = manager_process_seat_device(m, d);
754 udev_device_unref(d);
759 int manager_dispatch_vcsa_udev(Manager *m) {
760 struct udev_device *d;
766 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
770 name = udev_device_get_sysname(d);
772 /* Whenever a VCSA device is removed try to reallocate our
773 * VTs, to make sure our auto VTs never go away. */
775 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
776 r = seat_preallocate_vts(m->vtconsole);
778 udev_device_unref(d);
783 int manager_dispatch_button_udev(Manager *m) {
784 struct udev_device *d;
789 d = udev_monitor_receive_device(m->udev_button_monitor);
793 r = manager_process_button_device(m, d);
794 udev_device_unref(d);
799 int manager_dispatch_console(Manager *m) {
803 seat_read_active_vt(m->vtconsole);
808 static int vt_is_busy(int vtnr) {
809 struct vt_stat vt_stat;
814 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
815 * we'd open the latter we'd open the foreground tty which
816 * hence would be unconditionally busy. By opening /dev/tty1
817 * we avoid this. Since tty1 is special and needs to be an
818 * explicitly loaded getty or DM this is safe. */
820 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
824 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
827 r = !!(vt_stat.v_state & (1 << vtnr));
829 close_nointr_nofail(fd);
834 int manager_spawn_autovt(Manager *m, int vtnr) {
837 const char *mode = "fail";
842 if ((unsigned) vtnr > m->n_autovts &&
843 (unsigned) vtnr != m->reserve_vt)
846 if ((unsigned) vtnr != m->reserve_vt) {
847 /* If this is the reserved TTY, we'll start the getty
848 * on it in any case, but otherwise only if it is not
851 r = vt_is_busy(vtnr);
858 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
859 log_error("Could not allocate service name.");
864 r = bus_method_call_with_reply (
866 "org.freedesktop.systemd1",
867 "/org/freedesktop/systemd1",
868 "org.freedesktop.systemd1.Manager",
872 DBUS_TYPE_STRING, &name,
873 DBUS_TYPE_STRING, &mode,
882 static int manager_reserve_vt(Manager *m) {
883 _cleanup_free_ char *p = NULL;
887 if (m->reserve_vt <= 0)
890 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
893 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
894 if (m->reserve_vt_fd < 0) {
896 /* Don't complain on VT-less systems */
898 log_warning("Failed to pin reserved VT: %m");
905 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
906 _cleanup_free_ char *unit = NULL;
914 r = cg_pid_get_unit(pid, &unit);
918 s = hashmap_get(m->session_units, unit);
926 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
927 _cleanup_free_ char *unit = NULL;
935 r = cg_pid_get_slice(pid, &unit);
939 u = hashmap_get(m->user_units, unit);
947 static void manager_dispatch_other(Manager *m, int fd) {
955 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
957 assert(s->fifo_fd == fd);
958 session_remove_fifo(s);
963 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
965 assert(i->fifo_fd == fd);
971 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
978 assert_not_reached("Got event for unknown fd");
981 static int manager_connect_bus(Manager *m) {
984 struct epoll_event ev = {
991 assert(m->bus_fd < 0);
993 dbus_error_init(&error);
995 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
997 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1002 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1003 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1004 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1005 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1006 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1011 dbus_bus_add_match(m->bus,
1013 "sender='org.freedesktop.systemd1',"
1014 "interface='org.freedesktop.systemd1.Manager',"
1015 "member='JobRemoved',"
1016 "path='/org/freedesktop/systemd1'",
1018 if (dbus_error_is_set(&error)) {
1019 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
1020 dbus_error_free(&error);
1023 dbus_bus_add_match(m->bus,
1025 "sender='org.freedesktop.systemd1',"
1026 "interface='org.freedesktop.systemd1.Manager',"
1027 "member='UnitRemoved',"
1028 "path='/org/freedesktop/systemd1'",
1030 if (dbus_error_is_set(&error)) {
1031 log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
1032 dbus_error_free(&error);
1035 dbus_bus_add_match(m->bus,
1037 "sender='org.freedesktop.systemd1',"
1038 "interface='org.freedesktop.DBus.Properties',"
1039 "member='PropertiesChanged'",
1042 if (dbus_error_is_set(&error)) {
1043 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
1044 dbus_error_free(&error);
1047 r = bus_method_call_with_reply(
1049 "org.freedesktop.systemd1",
1050 "/org/freedesktop/systemd1",
1051 "org.freedesktop.systemd1.Manager",
1057 log_error("Failed to enable subscription: %s", bus_error(&error, r));
1058 dbus_error_free(&error);
1061 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1062 if (dbus_error_is_set(&error)) {
1063 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1068 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1069 log_error("Failed to acquire name.");
1074 m->bus_fd = bus_loop_open(m->bus);
1075 if (m->bus_fd < 0) {
1080 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1086 dbus_error_free(&error);
1091 static int manager_connect_console(Manager *m) {
1092 struct epoll_event ev = {
1094 .data.u32 = FD_CONSOLE,
1098 assert(m->console_active_fd < 0);
1100 /* On certain architectures (S390 and Xen, and containers),
1101 /dev/tty0 does not exist, so don't fail if we can't open
1103 if (access("/dev/tty0", F_OK) < 0) {
1104 m->console_active_fd = -1;
1108 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1109 if (m->console_active_fd < 0) {
1111 /* On some systems the device node /dev/tty0 may exist
1112 * even though /sys/class/tty/tty0 does not. */
1113 if (errno == ENOENT)
1116 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1120 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1126 static int manager_connect_udev(Manager *m) {
1128 struct epoll_event ev = {
1130 .data.u32 = FD_SEAT_UDEV,
1134 assert(!m->udev_seat_monitor);
1135 assert(!m->udev_vcsa_monitor);
1136 assert(!m->udev_button_monitor);
1138 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1139 if (!m->udev_seat_monitor)
1142 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1146 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1150 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1152 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1155 /* Don't watch keys if nobody cares */
1156 if (m->handle_power_key != HANDLE_IGNORE ||
1157 m->handle_suspend_key != HANDLE_IGNORE ||
1158 m->handle_hibernate_key != HANDLE_IGNORE ||
1159 m->handle_lid_switch != HANDLE_IGNORE) {
1161 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1162 if (!m->udev_button_monitor)
1165 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1169 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1173 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1177 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1180 ev.events = EPOLLIN;
1181 ev.data.u32 = FD_BUTTON_UDEV;
1182 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1186 /* Don't bother watching VCSA devices, if nobody cares */
1187 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1189 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1190 if (!m->udev_vcsa_monitor)
1193 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1197 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1201 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1204 ev.events = EPOLLIN;
1205 ev.data.u32 = FD_VCSA_UDEV;
1206 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1213 void manager_gc(Manager *m, bool drop_not_started) {
1220 while ((seat = m->seat_gc_queue)) {
1221 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1222 seat->in_gc_queue = false;
1224 if (seat_check_gc(seat, drop_not_started) == 0) {
1230 while ((session = m->session_gc_queue)) {
1231 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1232 session->in_gc_queue = false;
1234 if (session_check_gc(session, drop_not_started) == 0) {
1235 session_stop(session);
1236 session_free(session);
1240 while ((user = m->user_gc_queue)) {
1241 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1242 user->in_gc_queue = false;
1244 if (user_check_gc(user, drop_not_started) == 0) {
1251 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1254 dual_timestamp ts = { 0, 0 };
1259 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1261 HASHMAP_FOREACH(s, m->sessions, i) {
1265 ih = session_get_idle_hint(s, &k);
1271 if (k.monotonic < ts.monotonic)
1277 } else if (idle_hint) {
1279 if (k.monotonic > ts.monotonic)
1290 int manager_dispatch_idle_action(Manager *m) {
1291 struct dual_timestamp since;
1292 struct itimerspec its = {};
1298 if (m->idle_action == HANDLE_IGNORE ||
1299 m->idle_action_usec <= 0) {
1304 n = now(CLOCK_MONOTONIC);
1306 r = manager_get_idle_hint(m, &since);
1308 /* Not idle. Let's check if after a timeout it might be idle then. */
1309 timespec_store(&its.it_value, n + m->idle_action_usec);
1311 /* Idle! Let's see if it's time to do something, or if
1312 * we shall sleep for longer. */
1314 if (n >= since.monotonic + m->idle_action_usec &&
1315 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1316 log_info("System idle. Taking action.");
1318 manager_handle_action(m, 0, m->idle_action, false, false);
1319 m->idle_action_not_before_usec = n;
1322 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1325 if (m->idle_action_fd < 0) {
1326 struct epoll_event ev = {
1328 .data.u32 = FD_IDLE_ACTION,
1331 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1332 if (m->idle_action_fd < 0) {
1333 log_error("Failed to create idle action timer: %m");
1338 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1339 log_error("Failed to add idle action timer to epoll: %m");
1345 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1346 log_error("Failed to reset timerfd: %m");
1354 if (m->idle_action_fd >= 0) {
1355 close_nointr_nofail(m->idle_action_fd);
1356 m->idle_action_fd = -1;
1361 int manager_startup(Manager *m) {
1366 Inhibitor *inhibitor;
1370 assert(m->epoll_fd <= 0);
1372 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1373 if (m->epoll_fd < 0)
1376 /* Connect to console */
1377 r = manager_connect_console(m);
1381 /* Connect to udev */
1382 r = manager_connect_udev(m);
1386 /* Connect to the bus */
1387 r = manager_connect_bus(m);
1391 /* Instantiate magic seat 0 */
1392 r = manager_add_seat(m, "seat0", &m->vtconsole);
1396 /* Deserialize state */
1397 manager_enumerate_devices(m);
1398 manager_enumerate_seats(m);
1399 manager_enumerate_users(m);
1400 manager_enumerate_sessions(m);
1401 manager_enumerate_inhibitors(m);
1402 manager_enumerate_buttons(m);
1404 /* Remove stale objects before we start them */
1405 manager_gc(m, false);
1407 /* Reserve the special reserved VT */
1408 manager_reserve_vt(m);
1410 /* And start everything */
1411 HASHMAP_FOREACH(seat, m->seats, i)
1414 HASHMAP_FOREACH(user, m->users, i)
1417 HASHMAP_FOREACH(session, m->sessions, i)
1418 session_start(session);
1420 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1421 inhibitor_start(inhibitor);
1423 manager_dispatch_idle_action(m);
1428 static int manager_recheck_buttons(Manager *m) {
1435 HASHMAP_FOREACH(b, m->buttons, i) {
1438 q = button_recheck(b);
1448 int manager_run(Manager *m) {
1452 struct epoll_event event;
1456 manager_gc(m, true);
1458 if (manager_dispatch_delayed(m) > 0)
1461 if (manager_recheck_buttons(m) > 0)
1464 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1467 manager_gc(m, true);
1469 if (m->action_what != 0 && !m->action_job) {
1472 x = now(CLOCK_MONOTONIC);
1473 y = m->action_timestamp + m->inhibit_delay_max;
1475 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1478 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1480 if (errno == EINTR || errno == EAGAIN)
1483 log_error("epoll() failed: %m");
1490 switch (event.data.u32) {
1493 manager_dispatch_seat_udev(m);
1497 manager_dispatch_vcsa_udev(m);
1500 case FD_BUTTON_UDEV:
1501 manager_dispatch_button_udev(m);
1505 manager_dispatch_console(m);
1508 case FD_IDLE_ACTION:
1509 manager_dispatch_idle_action(m);
1513 bus_loop_dispatch(m->bus_fd);
1517 if (event.data.u32 >= FD_OTHER_BASE)
1518 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1525 static int manager_parse_config_file(Manager *m) {
1526 static const char fn[] = "/etc/systemd/logind.conf";
1527 _cleanup_fclose_ FILE *f = NULL;
1532 f = fopen(fn, "re");
1534 if (errno == ENOENT)
1537 log_warning("Failed to open configuration file %s: %m", fn);
1541 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1542 (void*) logind_gperf_lookup, false, false, m);
1544 log_warning("Failed to parse configuration file: %s", strerror(-r));
1549 int main(int argc, char *argv[]) {
1553 log_set_target(LOG_TARGET_AUTO);
1554 log_set_facility(LOG_AUTH);
1555 log_parse_environment();
1561 log_error("This program takes no arguments.");
1566 /* Always create the directories people can create inotify
1567 * watches in. Note that some applications might check for the
1568 * existence of /run/systemd/seats/ to determine whether
1569 * logind is available, so please always make sure this check
1571 mkdir_label("/run/systemd/seats", 0755);
1572 mkdir_label("/run/systemd/users", 0755);
1573 mkdir_label("/run/systemd/sessions", 0755);
1581 manager_parse_config_file(m);
1583 r = manager_startup(m);
1585 log_error("Failed to fully start up daemon: %s", strerror(-r));
1589 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1593 "STATUS=Processing requests...");
1597 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1601 "STATUS=Shutting down...");
1606 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;