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_cgroups = hashmap_new(string_hash_func, string_compare_func);
79 m->session_cgroups = 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_cgroups || !m->session_cgroups ||
87 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
92 m->reset_controllers = strv_new("cpu", NULL);
93 m->kill_exclude_users = strv_new("root", NULL);
94 if (!m->reset_controllers || !m->kill_exclude_users) {
105 if (cg_get_user_path(&m->cgroup_path) < 0) {
113 void manager_free(Manager *m) {
123 while ((session = hashmap_first(m->sessions)))
124 session_free(session);
126 while ((u = hashmap_first(m->users)))
129 while ((d = hashmap_first(m->devices)))
132 while ((s = hashmap_first(m->seats)))
135 while ((i = hashmap_first(m->inhibitors)))
138 while ((b = hashmap_first(m->buttons)))
141 hashmap_free(m->devices);
142 hashmap_free(m->seats);
143 hashmap_free(m->sessions);
144 hashmap_free(m->users);
145 hashmap_free(m->inhibitors);
146 hashmap_free(m->buttons);
148 hashmap_free(m->user_cgroups);
149 hashmap_free(m->session_cgroups);
151 hashmap_free(m->session_fds);
152 hashmap_free(m->inhibitor_fds);
153 hashmap_free(m->button_fds);
155 if (m->console_active_fd >= 0)
156 close_nointr_nofail(m->console_active_fd);
158 if (m->udev_seat_monitor)
159 udev_monitor_unref(m->udev_seat_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->controllers);
187 strv_free(m->reset_controllers);
188 strv_free(m->kill_only_users);
189 strv_free(m->kill_exclude_users);
193 free(m->cgroup_path);
197 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
203 d = hashmap_get(m->devices, sysfs);
211 d = device_new(m, sysfs);
221 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
227 s = hashmap_get(m->seats, id);
245 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
251 s = hashmap_get(m->sessions, id);
259 s = session_new(m, u, id);
269 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
275 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
283 u = user_new(m, uid, gid, name);
293 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
301 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
305 return manager_add_user(m, uid, gid, name, _user);
308 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
316 return errno ? -errno : -ENOENT;
318 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
321 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
327 i = hashmap_get(m->inhibitors, id);
335 i = inhibitor_new(m, id);
345 int manager_add_button(Manager *m, const char *name, Button **_button) {
351 b = hashmap_get(m->buttons, name);
359 b = button_new(m, name);
369 int manager_process_seat_device(Manager *m, struct udev_device *d) {
375 if (streq_ptr(udev_device_get_action(d), "remove")) {
377 device = hashmap_get(m->devices, udev_device_get_syspath(d));
381 seat_add_to_gc_queue(device->seat);
388 sn = udev_device_get_property_value(d, "ID_SEAT");
392 if (!seat_name_is_valid(sn)) {
393 log_warning("Device with invalid seat name %s found, ignoring.", sn);
397 r = manager_add_device(m, udev_device_get_syspath(d), &device);
401 r = manager_add_seat(m, sn, &seat);
409 device_attach(device, seat);
416 int manager_process_button_device(Manager *m, struct udev_device *d) {
423 if (streq_ptr(udev_device_get_action(d), "remove")) {
425 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
434 r = manager_add_button(m, udev_device_get_sysname(d), &b);
438 sn = udev_device_get_property_value(d, "ID_SEAT");
442 button_set_seat(b, sn);
449 int manager_enumerate_devices(Manager *m) {
450 struct udev_list_entry *item = NULL, *first = NULL;
451 struct udev_enumerate *e;
456 /* Loads devices from udev and creates seats for them as
459 e = udev_enumerate_new(m->udev);
465 r = udev_enumerate_add_match_tag(e, "master-of-seat");
469 r = udev_enumerate_scan_devices(e);
473 first = udev_enumerate_get_list_entry(e);
474 udev_list_entry_foreach(item, first) {
475 struct udev_device *d;
478 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
484 k = manager_process_seat_device(m, d);
485 udev_device_unref(d);
493 udev_enumerate_unref(e);
498 int manager_enumerate_buttons(Manager *m) {
499 struct udev_list_entry *item = NULL, *first = NULL;
500 struct udev_enumerate *e;
505 /* Loads buttons from udev */
507 if (m->handle_power_key == HANDLE_IGNORE &&
508 m->handle_suspend_key == HANDLE_IGNORE &&
509 m->handle_hibernate_key == HANDLE_IGNORE &&
510 m->handle_lid_switch == HANDLE_IGNORE)
513 e = udev_enumerate_new(m->udev);
519 r = udev_enumerate_add_match_subsystem(e, "input");
523 r = udev_enumerate_add_match_tag(e, "power-switch");
527 r = udev_enumerate_scan_devices(e);
531 first = udev_enumerate_get_list_entry(e);
532 udev_list_entry_foreach(item, first) {
533 struct udev_device *d;
536 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
542 k = manager_process_button_device(m, d);
543 udev_device_unref(d);
551 udev_enumerate_unref(e);
556 int manager_enumerate_seats(Manager *m) {
563 /* This loads data about seats stored on disk, but does not
564 * actually create any seats. Removes data of seats that no
567 d = opendir("/run/systemd/seats");
572 log_error("Failed to open /run/systemd/seats: %m");
576 while ((de = readdir(d))) {
580 if (!dirent_is_file(de))
583 s = hashmap_get(m->seats, de->d_name);
585 unlinkat(dirfd(d), de->d_name, 0);
599 static int manager_enumerate_users_from_cgroup(Manager *m) {
604 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
609 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
613 while ((k = cg_read_subgroup(d, &name)) > 0) {
616 k = manager_add_user_by_name(m, name, &user);
623 user_add_to_gc_queue(user);
625 if (!user->cgroup_path)
626 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
643 static int manager_enumerate_linger_users(Manager *m) {
648 d = opendir("/var/lib/systemd/linger");
653 log_error("Failed to open /var/lib/systemd/linger/: %m");
657 while ((de = readdir(d))) {
660 if (!dirent_is_file(de))
663 k = manager_add_user_by_name(m, de->d_name, NULL);
665 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
675 int manager_enumerate_users(Manager *m) {
682 /* First, enumerate user cgroups */
683 r = manager_enumerate_users_from_cgroup(m);
685 /* Second, add lingering users on top */
686 k = manager_enumerate_linger_users(m);
690 /* Third, read in user data stored on disk */
691 d = opendir("/run/systemd/users");
696 log_error("Failed to open /run/systemd/users: %m");
700 while ((de = readdir(d))) {
704 if (!dirent_is_file(de))
707 k = parse_uid(de->d_name, &uid);
709 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
713 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
715 unlinkat(dirfd(d), de->d_name, 0);
729 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
734 HASHMAP_FOREACH(u, m->users, i) {
742 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
747 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
752 while ((k = cg_read_subgroup(d, &name)) > 0) {
755 if (streq(name, "shared"))
758 k = manager_add_session(m, u, name, &session);
764 session_add_to_gc_queue(session);
766 if (!session->cgroup_path)
767 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
785 int manager_enumerate_sessions(Manager *m) {
792 /* First enumerate session cgroups */
793 r = manager_enumerate_sessions_from_cgroup(m);
795 /* Second, read in session data stored on disk */
796 d = opendir("/run/systemd/sessions");
801 log_error("Failed to open /run/systemd/sessions: %m");
805 while ((de = readdir(d))) {
809 if (!dirent_is_file(de))
812 s = hashmap_get(m->sessions, de->d_name);
814 unlinkat(dirfd(d), de->d_name, 0);
828 int manager_enumerate_inhibitors(Manager *m) {
835 d = opendir("/run/systemd/inhibit");
840 log_error("Failed to open /run/systemd/inhibit: %m");
844 while ((de = readdir(d))) {
848 if (!dirent_is_file(de))
851 k = manager_add_inhibitor(m, de->d_name, &i);
853 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
858 k = inhibitor_load(i);
868 int manager_dispatch_seat_udev(Manager *m) {
869 struct udev_device *d;
874 d = udev_monitor_receive_device(m->udev_seat_monitor);
878 r = manager_process_seat_device(m, d);
879 udev_device_unref(d);
884 int manager_dispatch_vcsa_udev(Manager *m) {
885 struct udev_device *d;
891 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
895 name = udev_device_get_sysname(d);
897 /* Whenever a VCSA device is removed try to reallocate our
898 * VTs, to make sure our auto VTs never go away. */
900 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
901 r = seat_preallocate_vts(m->vtconsole);
903 udev_device_unref(d);
908 int manager_dispatch_button_udev(Manager *m) {
909 struct udev_device *d;
914 d = udev_monitor_receive_device(m->udev_button_monitor);
918 r = manager_process_button_device(m, d);
919 udev_device_unref(d);
924 int manager_dispatch_console(Manager *m) {
928 seat_read_active_vt(m->vtconsole);
933 static int vt_is_busy(int vtnr) {
934 struct vt_stat vt_stat;
939 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
940 * we'd open the latter we'd open the foreground tty which
941 * hence would be unconditionally busy. By opening /dev/tty1
942 * we avoid this. Since tty1 is special and needs to be an
943 * explicitly loaded getty or DM this is safe. */
945 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
949 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
952 r = !!(vt_stat.v_state & (1 << vtnr));
954 close_nointr_nofail(fd);
959 int manager_spawn_autovt(Manager *m, int vtnr) {
962 const char *mode = "fail";
967 if ((unsigned) vtnr > m->n_autovts &&
968 (unsigned) vtnr != m->reserve_vt)
971 if ((unsigned) vtnr != m->reserve_vt) {
972 /* If this is the reserved TTY, we'll start the getty
973 * on it in any case, but otherwise only if it is not
976 r = vt_is_busy(vtnr);
983 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
984 log_error("Could not allocate service name.");
989 r = bus_method_call_with_reply (
991 "org.freedesktop.systemd1",
992 "/org/freedesktop/systemd1",
993 "org.freedesktop.systemd1.Manager",
997 DBUS_TYPE_STRING, &name,
998 DBUS_TYPE_STRING, &mode,
1007 static int manager_reserve_vt(Manager *m) {
1008 _cleanup_free_ char *p = NULL;
1012 if (m->reserve_vt <= 0)
1015 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1018 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1019 if (m->reserve_vt_fd < 0) {
1021 /* Don't complain on VT-less systems */
1022 if (errno != ENOENT)
1023 log_warning("Failed to pin reserved VT: %m");
1030 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1038 s = hashmap_get(m->session_cgroups, cgroup);
1051 e = strrchr(p, '/');
1060 s = hashmap_get(m->session_cgroups, p);
1069 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1077 u = hashmap_get(m->user_cgroups, cgroup);
1090 e = strrchr(p, '/');
1099 u = hashmap_get(m->user_cgroups, p);
1108 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1116 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1120 r = manager_get_session_by_cgroup(m, p, session);
1126 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1131 r = manager_get_session_by_cgroup(m, cgroup, &s);
1133 session_add_to_gc_queue(s);
1135 r = manager_get_user_by_cgroup(m, cgroup, &u);
1137 user_add_to_gc_queue(u);
1140 static void manager_dispatch_other(Manager *m, int fd) {
1148 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1150 assert(s->fifo_fd == fd);
1151 session_remove_fifo(s);
1156 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1158 assert(i->fifo_fd == fd);
1164 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1166 assert(b->fd == fd);
1171 assert_not_reached("Got event for unknown fd");
1174 static int manager_connect_bus(Manager *m) {
1177 struct epoll_event ev;
1181 assert(m->bus_fd < 0);
1183 dbus_error_init(&error);
1185 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1187 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1192 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1193 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1194 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1195 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1196 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1201 dbus_bus_add_match(m->bus,
1203 "interface='org.freedesktop.systemd1.Agent',"
1204 "member='Released',"
1205 "path='/org/freedesktop/systemd1/agent'",
1208 if (dbus_error_is_set(&error)) {
1209 log_error("Failed to register match: %s", bus_error_message(&error));
1214 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1215 if (dbus_error_is_set(&error)) {
1216 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1221 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1222 log_error("Failed to acquire name.");
1227 m->bus_fd = bus_loop_open(m->bus);
1228 if (m->bus_fd < 0) {
1234 ev.events = EPOLLIN;
1235 ev.data.u32 = FD_BUS;
1237 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1243 dbus_error_free(&error);
1248 static int manager_connect_console(Manager *m) {
1249 struct epoll_event ev;
1252 assert(m->console_active_fd < 0);
1254 /* On certain architectures (S390 and Xen, and containers),
1255 /dev/tty0 does not exist, so don't fail if we can't open
1257 if (access("/dev/tty0", F_OK) < 0) {
1258 m->console_active_fd = -1;
1262 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1263 if (m->console_active_fd < 0) {
1265 /* On some systems the device node /dev/tty0 may exist
1266 * even though /sys/class/tty/tty0 does not. */
1267 if (errno == ENOENT)
1270 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1276 ev.data.u32 = FD_CONSOLE;
1278 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1284 static int manager_connect_udev(Manager *m) {
1285 struct epoll_event ev;
1289 assert(!m->udev_seat_monitor);
1290 assert(!m->udev_vcsa_monitor);
1291 assert(!m->udev_button_monitor);
1293 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1294 if (!m->udev_seat_monitor)
1297 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1301 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1305 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1308 ev.events = EPOLLIN;
1309 ev.data.u32 = FD_SEAT_UDEV;
1310 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1313 /* Don't watch keys if nobody cares */
1314 if (m->handle_power_key != HANDLE_IGNORE ||
1315 m->handle_suspend_key != HANDLE_IGNORE ||
1316 m->handle_hibernate_key != HANDLE_IGNORE ||
1317 m->handle_lid_switch != HANDLE_IGNORE) {
1319 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1320 if (!m->udev_button_monitor)
1323 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1327 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1331 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1335 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1338 ev.events = EPOLLIN;
1339 ev.data.u32 = FD_BUTTON_UDEV;
1340 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1344 /* Don't bother watching VCSA devices, if nobody cares */
1345 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1347 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1348 if (!m->udev_vcsa_monitor)
1351 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1355 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1359 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1362 ev.events = EPOLLIN;
1363 ev.data.u32 = FD_VCSA_UDEV;
1364 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1371 void manager_gc(Manager *m, bool drop_not_started) {
1378 while ((seat = m->seat_gc_queue)) {
1379 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1380 seat->in_gc_queue = false;
1382 if (seat_check_gc(seat, drop_not_started) == 0) {
1388 while ((session = m->session_gc_queue)) {
1389 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1390 session->in_gc_queue = false;
1392 if (session_check_gc(session, drop_not_started) == 0) {
1393 session_stop(session);
1394 session_free(session);
1398 while ((user = m->user_gc_queue)) {
1399 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1400 user->in_gc_queue = false;
1402 if (user_check_gc(user, drop_not_started) == 0) {
1409 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1412 dual_timestamp ts = { 0, 0 };
1417 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1419 HASHMAP_FOREACH(s, m->sessions, i) {
1423 ih = session_get_idle_hint(s, &k);
1429 if (k.monotonic < ts.monotonic)
1435 } else if (idle_hint) {
1437 if (k.monotonic > ts.monotonic)
1448 int manager_dispatch_idle_action(Manager *m) {
1449 struct dual_timestamp since;
1450 struct itimerspec its;
1456 if (m->idle_action == HANDLE_IGNORE ||
1457 m->idle_action_usec <= 0) {
1463 n = now(CLOCK_MONOTONIC);
1465 r = manager_get_idle_hint(m, &since);
1467 /* Not idle. Let's check if after a timeout it might be idle then. */
1468 timespec_store(&its.it_value, n + m->idle_action_usec);
1470 /* Idle! Let's see if it's time to do something, or if
1471 * we shall sleep for longer. */
1473 if (n >= since.monotonic + m->idle_action_usec &&
1474 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1475 log_info("System idle. Taking action.");
1477 manager_handle_action(m, 0, m->idle_action, false, false);
1478 m->idle_action_not_before_usec = n;
1481 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1484 if (m->idle_action_fd < 0) {
1485 struct epoll_event ev;
1487 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1488 if (m->idle_action_fd < 0) {
1489 log_error("Failed to create idle action timer: %m");
1495 ev.events = EPOLLIN;
1496 ev.data.u32 = FD_IDLE_ACTION;
1498 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1499 log_error("Failed to add idle action timer to epoll: %m");
1505 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1506 log_error("Failed to reset timerfd: %m");
1514 if (m->idle_action_fd >= 0) {
1515 close_nointr_nofail(m->idle_action_fd);
1516 m->idle_action_fd = -1;
1521 int manager_startup(Manager *m) {
1526 Inhibitor *inhibitor;
1530 assert(m->epoll_fd <= 0);
1532 cg_shorten_controllers(m->reset_controllers);
1533 cg_shorten_controllers(m->controllers);
1535 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1536 if (m->epoll_fd < 0)
1539 /* Connect to console */
1540 r = manager_connect_console(m);
1544 /* Connect to udev */
1545 r = manager_connect_udev(m);
1549 /* Connect to the bus */
1550 r = manager_connect_bus(m);
1554 /* Instantiate magic seat 0 */
1555 r = manager_add_seat(m, "seat0", &m->vtconsole);
1559 /* Deserialize state */
1560 manager_enumerate_devices(m);
1561 manager_enumerate_seats(m);
1562 manager_enumerate_users(m);
1563 manager_enumerate_sessions(m);
1564 manager_enumerate_inhibitors(m);
1565 manager_enumerate_buttons(m);
1567 /* Remove stale objects before we start them */
1568 manager_gc(m, false);
1570 /* Reserve the special reserved VT */
1571 manager_reserve_vt(m);
1573 /* And start everything */
1574 HASHMAP_FOREACH(seat, m->seats, i)
1577 HASHMAP_FOREACH(user, m->users, i)
1580 HASHMAP_FOREACH(session, m->sessions, i)
1581 session_start(session);
1583 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1584 inhibitor_start(inhibitor);
1586 manager_dispatch_idle_action(m);
1591 static int manager_recheck_buttons(Manager *m) {
1598 HASHMAP_FOREACH(b, m->buttons, i) {
1601 q = button_recheck(b);
1611 int manager_run(Manager *m) {
1615 struct epoll_event event;
1619 manager_gc(m, true);
1621 if (manager_dispatch_delayed(m) > 0)
1624 if (manager_recheck_buttons(m) > 0)
1627 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1630 manager_gc(m, true);
1632 if (m->action_what != 0) {
1635 x = now(CLOCK_MONOTONIC);
1636 y = m->action_timestamp + m->inhibit_delay_max;
1638 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1641 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1643 if (errno == EINTR || errno == EAGAIN)
1646 log_error("epoll() failed: %m");
1653 switch (event.data.u32) {
1656 manager_dispatch_seat_udev(m);
1660 manager_dispatch_vcsa_udev(m);
1663 case FD_BUTTON_UDEV:
1664 manager_dispatch_button_udev(m);
1668 manager_dispatch_console(m);
1671 case FD_IDLE_ACTION:
1672 manager_dispatch_idle_action(m);
1676 bus_loop_dispatch(m->bus_fd);
1680 if (event.data.u32 >= FD_OTHER_BASE)
1681 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1688 static int manager_parse_config_file(Manager *m) {
1695 fn = "/etc/systemd/logind.conf";
1696 f = fopen(fn, "re");
1698 if (errno == ENOENT)
1701 log_warning("Failed to open configuration file %s: %m", fn);
1705 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1707 log_warning("Failed to parse configuration file: %s", strerror(-r));
1714 int main(int argc, char *argv[]) {
1718 log_set_target(LOG_TARGET_AUTO);
1719 log_set_facility(LOG_AUTH);
1720 log_parse_environment();
1726 log_error("This program takes no arguments.");
1731 /* Always create the directories people can create inotify
1732 * watches in. Note that some applications might check for the
1733 * existance of /run/systemd/seats/ to determine whether
1734 * logind is available, so please always make sure this check
1736 mkdir_label("/run/systemd/seats", 0755);
1737 mkdir_label("/run/systemd/users", 0755);
1738 mkdir_label("/run/systemd/sessions", 0755);
1746 manager_parse_config_file(m);
1748 r = manager_startup(m);
1750 log_error("Failed to fully start up daemon: %s", strerror(-r));
1754 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1758 "STATUS=Processing requests...");
1762 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1766 "STATUS=Shutting down...");
1771 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;