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"
41 Manager *manager_new(void) {
48 m->console_active_fd = -1;
52 m->udev_button_fd = -1;
54 m->reserve_vt_fd = -1;
58 m->inhibit_delay_max = 5 * USEC_PER_SEC;
59 m->handle_power_key = HANDLE_POWEROFF;
60 m->handle_suspend_key = HANDLE_SUSPEND;
61 m->handle_hibernate_key = HANDLE_HIBERNATE;
62 m->handle_lid_switch = HANDLE_SUSPEND;
63 m->lid_switch_ignore_inhibited = true;
65 m->idle_action_fd = -1;
66 m->idle_action_usec = 30 * USEC_PER_MINUTE;
67 m->idle_action = HANDLE_IGNORE;
68 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
70 m->devices = hashmap_new(string_hash_func, string_compare_func);
71 m->seats = hashmap_new(string_hash_func, string_compare_func);
72 m->sessions = hashmap_new(string_hash_func, string_compare_func);
73 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
74 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
75 m->buttons = hashmap_new(string_hash_func, string_compare_func);
77 m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
78 m->session_cgroups = 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 ||
85 !m->user_cgroups || !m->session_cgroups ||
86 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
91 m->reset_controllers = strv_new("cpu", NULL);
92 m->kill_exclude_users = strv_new("root", NULL);
93 if (!m->reset_controllers || !m->kill_exclude_users) {
104 if (cg_get_user_path(&m->cgroup_path) < 0) {
112 void manager_free(Manager *m) {
122 while ((session = hashmap_first(m->sessions)))
123 session_free(session);
125 while ((u = hashmap_first(m->users)))
128 while ((d = hashmap_first(m->devices)))
131 while ((s = hashmap_first(m->seats)))
134 while ((i = hashmap_first(m->inhibitors)))
137 while ((b = hashmap_first(m->buttons)))
140 hashmap_free(m->devices);
141 hashmap_free(m->seats);
142 hashmap_free(m->sessions);
143 hashmap_free(m->users);
144 hashmap_free(m->inhibitors);
145 hashmap_free(m->buttons);
147 hashmap_free(m->user_cgroups);
148 hashmap_free(m->session_cgroups);
150 hashmap_free(m->session_fds);
151 hashmap_free(m->inhibitor_fds);
152 hashmap_free(m->button_fds);
154 if (m->console_active_fd >= 0)
155 close_nointr_nofail(m->console_active_fd);
157 if (m->udev_seat_monitor)
158 udev_monitor_unref(m->udev_seat_monitor);
159 if (m->udev_vcsa_monitor)
160 udev_monitor_unref(m->udev_vcsa_monitor);
161 if (m->udev_button_monitor)
162 udev_monitor_unref(m->udev_button_monitor);
168 dbus_connection_flush(m->bus);
169 dbus_connection_close(m->bus);
170 dbus_connection_unref(m->bus);
174 close_nointr_nofail(m->bus_fd);
176 if (m->epoll_fd >= 0)
177 close_nointr_nofail(m->epoll_fd);
179 if (m->reserve_vt_fd >= 0)
180 close_nointr_nofail(m->reserve_vt_fd);
182 if (m->idle_action_fd >= 0)
183 close_nointr_nofail(m->idle_action_fd);
185 strv_free(m->controllers);
186 strv_free(m->reset_controllers);
187 strv_free(m->kill_only_users);
188 strv_free(m->kill_exclude_users);
192 free(m->cgroup_path);
196 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
202 d = hashmap_get(m->devices, sysfs);
210 d = device_new(m, sysfs);
220 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
226 s = hashmap_get(m->seats, id);
244 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
250 s = hashmap_get(m->sessions, id);
258 s = session_new(m, u, id);
268 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
274 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
282 u = user_new(m, uid, gid, name);
292 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
300 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
304 return manager_add_user(m, uid, gid, name, _user);
307 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
315 return errno ? -errno : -ENOENT;
317 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
320 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
326 i = hashmap_get(m->inhibitors, id);
334 i = inhibitor_new(m, id);
344 int manager_add_button(Manager *m, const char *name, Button **_button) {
350 b = hashmap_get(m->buttons, name);
358 b = button_new(m, name);
368 int manager_process_seat_device(Manager *m, struct udev_device *d) {
374 if (streq_ptr(udev_device_get_action(d), "remove")) {
376 device = hashmap_get(m->devices, udev_device_get_syspath(d));
380 seat_add_to_gc_queue(device->seat);
387 sn = udev_device_get_property_value(d, "ID_SEAT");
391 if (!seat_name_is_valid(sn)) {
392 log_warning("Device with invalid seat name %s found, ignoring.", sn);
396 r = manager_add_device(m, udev_device_get_syspath(d), &device);
400 r = manager_add_seat(m, sn, &seat);
408 device_attach(device, seat);
415 int manager_process_button_device(Manager *m, struct udev_device *d) {
422 if (streq_ptr(udev_device_get_action(d), "remove")) {
424 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
433 r = manager_add_button(m, udev_device_get_sysname(d), &b);
437 sn = udev_device_get_property_value(d, "ID_SEAT");
441 button_set_seat(b, sn);
448 int manager_enumerate_devices(Manager *m) {
449 struct udev_list_entry *item = NULL, *first = NULL;
450 struct udev_enumerate *e;
455 /* Loads devices from udev and creates seats for them as
458 e = udev_enumerate_new(m->udev);
464 r = udev_enumerate_add_match_tag(e, "master-of-seat");
468 r = udev_enumerate_scan_devices(e);
472 first = udev_enumerate_get_list_entry(e);
473 udev_list_entry_foreach(item, first) {
474 struct udev_device *d;
477 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
483 k = manager_process_seat_device(m, d);
484 udev_device_unref(d);
492 udev_enumerate_unref(e);
497 int manager_enumerate_buttons(Manager *m) {
498 struct udev_list_entry *item = NULL, *first = NULL;
499 struct udev_enumerate *e;
504 /* Loads buttons from udev */
506 if (m->handle_power_key == HANDLE_IGNORE &&
507 m->handle_suspend_key == HANDLE_IGNORE &&
508 m->handle_hibernate_key == HANDLE_IGNORE &&
509 m->handle_lid_switch == HANDLE_IGNORE)
512 e = udev_enumerate_new(m->udev);
518 r = udev_enumerate_add_match_subsystem(e, "input");
522 r = udev_enumerate_add_match_tag(e, "power-switch");
526 r = udev_enumerate_scan_devices(e);
530 first = udev_enumerate_get_list_entry(e);
531 udev_list_entry_foreach(item, first) {
532 struct udev_device *d;
535 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
541 k = manager_process_button_device(m, d);
542 udev_device_unref(d);
550 udev_enumerate_unref(e);
555 int manager_enumerate_seats(Manager *m) {
562 /* This loads data about seats stored on disk, but does not
563 * actually create any seats. Removes data of seats that no
566 d = opendir("/run/systemd/seats");
571 log_error("Failed to open /run/systemd/seats: %m");
575 while ((de = readdir(d))) {
579 if (!dirent_is_file(de))
582 s = hashmap_get(m->seats, de->d_name);
584 unlinkat(dirfd(d), de->d_name, 0);
598 static int manager_enumerate_users_from_cgroup(Manager *m) {
603 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
608 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
612 while ((k = cg_read_subgroup(d, &name)) > 0) {
615 k = manager_add_user_by_name(m, name, &user);
622 user_add_to_gc_queue(user);
624 if (!user->cgroup_path)
625 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
642 static int manager_enumerate_linger_users(Manager *m) {
647 d = opendir("/var/lib/systemd/linger");
652 log_error("Failed to open /var/lib/systemd/linger/: %m");
656 while ((de = readdir(d))) {
659 if (!dirent_is_file(de))
662 k = manager_add_user_by_name(m, de->d_name, NULL);
664 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
674 int manager_enumerate_users(Manager *m) {
681 /* First, enumerate user cgroups */
682 r = manager_enumerate_users_from_cgroup(m);
684 /* Second, add lingering users on top */
685 k = manager_enumerate_linger_users(m);
689 /* Third, read in user data stored on disk */
690 d = opendir("/run/systemd/users");
695 log_error("Failed to open /run/systemd/users: %m");
699 while ((de = readdir(d))) {
703 if (!dirent_is_file(de))
706 k = parse_uid(de->d_name, &uid);
708 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
712 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
714 unlinkat(dirfd(d), de->d_name, 0);
728 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
733 HASHMAP_FOREACH(u, m->users, i) {
741 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
746 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
751 while ((k = cg_read_subgroup(d, &name)) > 0) {
754 if (streq(name, "shared"))
757 k = manager_add_session(m, u, name, &session);
763 session_add_to_gc_queue(session);
765 if (!session->cgroup_path)
766 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
784 int manager_enumerate_sessions(Manager *m) {
791 /* First enumerate session cgroups */
792 r = manager_enumerate_sessions_from_cgroup(m);
794 /* Second, read in session data stored on disk */
795 d = opendir("/run/systemd/sessions");
800 log_error("Failed to open /run/systemd/sessions: %m");
804 while ((de = readdir(d))) {
808 if (!dirent_is_file(de))
811 s = hashmap_get(m->sessions, de->d_name);
813 unlinkat(dirfd(d), de->d_name, 0);
827 int manager_enumerate_inhibitors(Manager *m) {
834 d = opendir("/run/systemd/inhibit");
839 log_error("Failed to open /run/systemd/inhibit: %m");
843 while ((de = readdir(d))) {
847 if (!dirent_is_file(de))
850 k = manager_add_inhibitor(m, de->d_name, &i);
852 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
857 k = inhibitor_load(i);
867 int manager_dispatch_seat_udev(Manager *m) {
868 struct udev_device *d;
873 d = udev_monitor_receive_device(m->udev_seat_monitor);
877 r = manager_process_seat_device(m, d);
878 udev_device_unref(d);
883 int manager_dispatch_vcsa_udev(Manager *m) {
884 struct udev_device *d;
890 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
894 name = udev_device_get_sysname(d);
896 /* Whenever a VCSA device is removed try to reallocate our
897 * VTs, to make sure our auto VTs never go away. */
899 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
900 r = seat_preallocate_vts(m->vtconsole);
902 udev_device_unref(d);
907 int manager_dispatch_button_udev(Manager *m) {
908 struct udev_device *d;
913 d = udev_monitor_receive_device(m->udev_button_monitor);
917 r = manager_process_button_device(m, d);
918 udev_device_unref(d);
923 int manager_dispatch_console(Manager *m) {
927 seat_read_active_vt(m->vtconsole);
932 static int vt_is_busy(int vtnr) {
933 struct vt_stat vt_stat;
938 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
939 * we'd open the latter we'd open the foreground tty which
940 * hence would be unconditionally busy. By opening /dev/tty1
941 * we avoid this. Since tty1 is special and needs to be an
942 * explicitly loaded getty or DM this is safe. */
944 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
948 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
951 r = !!(vt_stat.v_state & (1 << vtnr));
953 close_nointr_nofail(fd);
958 int manager_spawn_autovt(Manager *m, int vtnr) {
961 const char *mode = "fail";
966 if ((unsigned) vtnr > m->n_autovts &&
967 (unsigned) vtnr != m->reserve_vt)
970 if ((unsigned) vtnr != m->reserve_vt) {
971 /* If this is the reserved TTY, we'll start the getty
972 * on it in any case, but otherwise only if it is not
975 r = vt_is_busy(vtnr);
982 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
983 log_error("Could not allocate service name.");
988 r = bus_method_call_with_reply (
990 "org.freedesktop.systemd1",
991 "/org/freedesktop/systemd1",
992 "org.freedesktop.systemd1.Manager",
996 DBUS_TYPE_STRING, &name,
997 DBUS_TYPE_STRING, &mode,
1006 static int manager_reserve_vt(Manager *m) {
1007 _cleanup_free_ char *p = NULL;
1011 if (m->reserve_vt <= 0)
1014 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1017 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1018 if (m->reserve_vt_fd < 0) {
1020 /* Don't complain on VT-less systems */
1021 if (errno != ENOENT)
1022 log_warning("Failed to pin reserved VT: %m");
1029 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1037 s = hashmap_get(m->session_cgroups, cgroup);
1050 e = strrchr(p, '/');
1059 s = hashmap_get(m->session_cgroups, p);
1068 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1076 u = hashmap_get(m->user_cgroups, cgroup);
1089 e = strrchr(p, '/');
1098 u = hashmap_get(m->user_cgroups, p);
1107 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1115 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1119 r = manager_get_session_by_cgroup(m, p, session);
1125 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1130 r = manager_get_session_by_cgroup(m, cgroup, &s);
1132 session_add_to_gc_queue(s);
1134 r = manager_get_user_by_cgroup(m, cgroup, &u);
1136 user_add_to_gc_queue(u);
1139 static void manager_dispatch_other(Manager *m, int fd) {
1147 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1149 assert(s->fifo_fd == fd);
1150 session_remove_fifo(s);
1155 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1157 assert(i->fifo_fd == fd);
1163 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1165 assert(b->fd == fd);
1170 assert_not_reached("Got event for unknown fd");
1173 static int manager_connect_bus(Manager *m) {
1176 struct epoll_event ev;
1180 assert(m->bus_fd < 0);
1182 dbus_error_init(&error);
1184 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1186 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1191 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1192 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1193 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1194 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1195 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1200 dbus_bus_add_match(m->bus,
1202 "interface='org.freedesktop.systemd1.Agent',"
1203 "member='Released',"
1204 "path='/org/freedesktop/systemd1/agent'",
1207 if (dbus_error_is_set(&error)) {
1208 log_error("Failed to register match: %s", bus_error_message(&error));
1213 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1214 if (dbus_error_is_set(&error)) {
1215 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1220 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1221 log_error("Failed to acquire name.");
1226 m->bus_fd = bus_loop_open(m->bus);
1227 if (m->bus_fd < 0) {
1233 ev.events = EPOLLIN;
1234 ev.data.u32 = FD_BUS;
1236 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1242 dbus_error_free(&error);
1247 static int manager_connect_console(Manager *m) {
1248 struct epoll_event ev;
1251 assert(m->console_active_fd < 0);
1253 /* On certain architectures (S390 and Xen, and containers),
1254 /dev/tty0 does not exist, so don't fail if we can't open
1256 if (access("/dev/tty0", F_OK) < 0) {
1257 m->console_active_fd = -1;
1261 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1262 if (m->console_active_fd < 0) {
1264 /* On some systems the device node /dev/tty0 may exist
1265 * even though /sys/class/tty/tty0 does not. */
1266 if (errno == ENOENT)
1269 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1275 ev.data.u32 = FD_CONSOLE;
1277 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1283 static int manager_connect_udev(Manager *m) {
1284 struct epoll_event ev;
1288 assert(!m->udev_seat_monitor);
1289 assert(!m->udev_vcsa_monitor);
1290 assert(!m->udev_button_monitor);
1292 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1293 if (!m->udev_seat_monitor)
1296 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1300 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1304 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1307 ev.events = EPOLLIN;
1308 ev.data.u32 = FD_SEAT_UDEV;
1309 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1312 /* Don't watch keys if nobody cares */
1313 if (m->handle_power_key != HANDLE_IGNORE ||
1314 m->handle_suspend_key != HANDLE_IGNORE ||
1315 m->handle_hibernate_key != HANDLE_IGNORE ||
1316 m->handle_lid_switch != HANDLE_IGNORE) {
1318 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1319 if (!m->udev_button_monitor)
1322 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1326 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1330 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1334 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1337 ev.events = EPOLLIN;
1338 ev.data.u32 = FD_BUTTON_UDEV;
1339 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1343 /* Don't bother watching VCSA devices, if nobody cares */
1344 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1346 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1347 if (!m->udev_vcsa_monitor)
1350 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1354 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1358 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1361 ev.events = EPOLLIN;
1362 ev.data.u32 = FD_VCSA_UDEV;
1363 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1370 void manager_gc(Manager *m, bool drop_not_started) {
1377 while ((seat = m->seat_gc_queue)) {
1378 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1379 seat->in_gc_queue = false;
1381 if (seat_check_gc(seat, drop_not_started) == 0) {
1387 while ((session = m->session_gc_queue)) {
1388 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1389 session->in_gc_queue = false;
1391 if (session_check_gc(session, drop_not_started) == 0) {
1392 session_stop(session);
1393 session_free(session);
1397 while ((user = m->user_gc_queue)) {
1398 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1399 user->in_gc_queue = false;
1401 if (user_check_gc(user, drop_not_started) == 0) {
1408 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1411 dual_timestamp ts = { 0, 0 };
1416 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1418 HASHMAP_FOREACH(s, m->sessions, i) {
1422 ih = session_get_idle_hint(s, &k);
1428 if (k.monotonic < ts.monotonic)
1434 } else if (idle_hint) {
1436 if (k.monotonic > ts.monotonic)
1447 int manager_dispatch_idle_action(Manager *m) {
1448 struct dual_timestamp since;
1449 struct itimerspec its;
1455 if (m->idle_action == HANDLE_IGNORE ||
1456 m->idle_action_usec <= 0) {
1462 n = now(CLOCK_MONOTONIC);
1464 r = manager_get_idle_hint(m, &since);
1466 /* Not idle. Let's check if after a timeout it might be idle then. */
1467 timespec_store(&its.it_value, n + m->idle_action_usec);
1469 /* Idle! Let's see if it's time to do something, or if
1470 * we shall sleep for longer. */
1472 if (n >= since.monotonic + m->idle_action_usec &&
1473 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1474 log_info("System idle. Taking action.");
1476 manager_handle_action(m, 0, m->idle_action, false, false);
1477 m->idle_action_not_before_usec = n;
1480 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1483 if (m->idle_action_fd < 0) {
1484 struct epoll_event ev;
1486 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1487 if (m->idle_action_fd < 0) {
1488 log_error("Failed to create idle action timer: %m");
1494 ev.events = EPOLLIN;
1495 ev.data.u32 = FD_IDLE_ACTION;
1497 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1498 log_error("Failed to add idle action timer to epoll: %m");
1504 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1505 log_error("Failed to reset timerfd: %m");
1513 if (m->idle_action_fd >= 0) {
1514 close_nointr_nofail(m->idle_action_fd);
1515 m->idle_action_fd = -1;
1520 int manager_startup(Manager *m) {
1525 Inhibitor *inhibitor;
1529 assert(m->epoll_fd <= 0);
1531 cg_shorten_controllers(m->reset_controllers);
1532 cg_shorten_controllers(m->controllers);
1534 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1535 if (m->epoll_fd < 0)
1538 /* Connect to console */
1539 r = manager_connect_console(m);
1543 /* Connect to udev */
1544 r = manager_connect_udev(m);
1548 /* Connect to the bus */
1549 r = manager_connect_bus(m);
1553 /* Instantiate magic seat 0 */
1554 r = manager_add_seat(m, "seat0", &m->vtconsole);
1558 /* Deserialize state */
1559 manager_enumerate_devices(m);
1560 manager_enumerate_seats(m);
1561 manager_enumerate_users(m);
1562 manager_enumerate_sessions(m);
1563 manager_enumerate_inhibitors(m);
1564 manager_enumerate_buttons(m);
1566 /* Remove stale objects before we start them */
1567 manager_gc(m, false);
1569 /* Reserve the special reserved VT */
1570 manager_reserve_vt(m);
1572 /* And start everything */
1573 HASHMAP_FOREACH(seat, m->seats, i)
1576 HASHMAP_FOREACH(user, m->users, i)
1579 HASHMAP_FOREACH(session, m->sessions, i)
1580 session_start(session);
1582 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1583 inhibitor_start(inhibitor);
1585 manager_dispatch_idle_action(m);
1590 static int manager_recheck_buttons(Manager *m) {
1597 HASHMAP_FOREACH(b, m->buttons, i) {
1600 q = button_recheck(b);
1610 int manager_run(Manager *m) {
1614 struct epoll_event event;
1618 manager_gc(m, true);
1620 if (manager_dispatch_delayed(m) > 0)
1623 if (manager_recheck_buttons(m) > 0)
1626 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1629 manager_gc(m, true);
1631 if (m->action_what != 0) {
1634 x = now(CLOCK_MONOTONIC);
1635 y = m->action_timestamp + m->inhibit_delay_max;
1637 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1640 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1642 if (errno == EINTR || errno == EAGAIN)
1645 log_error("epoll() failed: %m");
1652 switch (event.data.u32) {
1655 manager_dispatch_seat_udev(m);
1659 manager_dispatch_vcsa_udev(m);
1662 case FD_BUTTON_UDEV:
1663 manager_dispatch_button_udev(m);
1667 manager_dispatch_console(m);
1670 case FD_IDLE_ACTION:
1671 manager_dispatch_idle_action(m);
1675 bus_loop_dispatch(m->bus_fd);
1679 if (event.data.u32 >= FD_OTHER_BASE)
1680 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1687 static int manager_parse_config_file(Manager *m) {
1694 fn = "/etc/systemd/logind.conf";
1695 f = fopen(fn, "re");
1697 if (errno == ENOENT)
1700 log_warning("Failed to open configuration file %s: %m", fn);
1704 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1706 log_warning("Failed to parse configuration file: %s", strerror(-r));
1713 int main(int argc, char *argv[]) {
1717 log_set_target(LOG_TARGET_AUTO);
1718 log_set_facility(LOG_AUTH);
1719 log_parse_environment();
1725 log_error("This program takes no arguments.");
1736 manager_parse_config_file(m);
1738 r = manager_startup(m);
1740 log_error("Failed to fully start up daemon: %s", strerror(-r));
1744 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1748 "STATUS=Processing requests...");
1752 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1756 "STATUS=Shutting down...");
1761 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;