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);
190 free(m->cgroup_path);
194 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
200 d = hashmap_get(m->devices, sysfs);
208 d = device_new(m, sysfs);
218 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
224 s = hashmap_get(m->seats, id);
242 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
248 s = hashmap_get(m->sessions, id);
256 s = session_new(m, u, id);
266 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
272 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
280 u = user_new(m, uid, gid, name);
290 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
298 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
302 return manager_add_user(m, uid, gid, name, _user);
305 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
313 return errno ? -errno : -ENOENT;
315 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
318 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
324 i = hashmap_get(m->inhibitors, id);
332 i = inhibitor_new(m, id);
342 int manager_add_button(Manager *m, const char *name, Button **_button) {
348 b = hashmap_get(m->buttons, name);
356 b = button_new(m, name);
366 int manager_process_seat_device(Manager *m, struct udev_device *d) {
372 if (streq_ptr(udev_device_get_action(d), "remove")) {
374 device = hashmap_get(m->devices, udev_device_get_syspath(d));
378 seat_add_to_gc_queue(device->seat);
385 sn = udev_device_get_property_value(d, "ID_SEAT");
389 if (!seat_name_is_valid(sn)) {
390 log_warning("Device with invalid seat name %s found, ignoring.", sn);
394 r = manager_add_device(m, udev_device_get_syspath(d), &device);
398 r = manager_add_seat(m, sn, &seat);
406 device_attach(device, seat);
413 int manager_process_button_device(Manager *m, struct udev_device *d) {
420 if (streq_ptr(udev_device_get_action(d), "remove")) {
422 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
431 r = manager_add_button(m, udev_device_get_sysname(d), &b);
435 sn = udev_device_get_property_value(d, "ID_SEAT");
439 button_set_seat(b, sn);
446 int manager_enumerate_devices(Manager *m) {
447 struct udev_list_entry *item = NULL, *first = NULL;
448 struct udev_enumerate *e;
453 /* Loads devices from udev and creates seats for them as
456 e = udev_enumerate_new(m->udev);
462 r = udev_enumerate_add_match_tag(e, "seat-master");
466 r = udev_enumerate_scan_devices(e);
470 first = udev_enumerate_get_list_entry(e);
471 udev_list_entry_foreach(item, first) {
472 struct udev_device *d;
475 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
481 k = manager_process_seat_device(m, d);
482 udev_device_unref(d);
490 udev_enumerate_unref(e);
495 int manager_enumerate_buttons(Manager *m) {
496 struct udev_list_entry *item = NULL, *first = NULL;
497 struct udev_enumerate *e;
502 /* Loads buttons from udev */
504 if (m->handle_power_key == HANDLE_IGNORE &&
505 m->handle_suspend_key == HANDLE_IGNORE &&
506 m->handle_hibernate_key == HANDLE_IGNORE &&
507 m->handle_lid_switch == HANDLE_IGNORE)
510 e = udev_enumerate_new(m->udev);
516 r = udev_enumerate_add_match_subsystem(e, "input");
520 r = udev_enumerate_add_match_tag(e, "power-switch");
524 r = udev_enumerate_scan_devices(e);
528 first = udev_enumerate_get_list_entry(e);
529 udev_list_entry_foreach(item, first) {
530 struct udev_device *d;
533 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
539 k = manager_process_button_device(m, d);
540 udev_device_unref(d);
548 udev_enumerate_unref(e);
553 int manager_enumerate_seats(Manager *m) {
560 /* This loads data about seats stored on disk, but does not
561 * actually create any seats. Removes data of seats that no
564 d = opendir("/run/systemd/seats");
569 log_error("Failed to open /run/systemd/seats: %m");
573 while ((de = readdir(d))) {
577 if (!dirent_is_file(de))
580 s = hashmap_get(m->seats, de->d_name);
582 unlinkat(dirfd(d), de->d_name, 0);
596 static int manager_enumerate_users_from_cgroup(Manager *m) {
601 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
606 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
610 while ((k = cg_read_subgroup(d, &name)) > 0) {
613 k = manager_add_user_by_name(m, name, &user);
620 user_add_to_gc_queue(user);
622 if (!user->cgroup_path)
623 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
640 static int manager_enumerate_linger_users(Manager *m) {
645 d = opendir("/var/lib/systemd/linger");
650 log_error("Failed to open /var/lib/systemd/linger/: %m");
654 while ((de = readdir(d))) {
657 if (!dirent_is_file(de))
660 k = manager_add_user_by_name(m, de->d_name, NULL);
662 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
672 int manager_enumerate_users(Manager *m) {
679 /* First, enumerate user cgroups */
680 r = manager_enumerate_users_from_cgroup(m);
682 /* Second, add lingering users on top */
683 k = manager_enumerate_linger_users(m);
687 /* Third, read in user data stored on disk */
688 d = opendir("/run/systemd/users");
693 log_error("Failed to open /run/systemd/users: %m");
697 while ((de = readdir(d))) {
701 if (!dirent_is_file(de))
704 k = parse_uid(de->d_name, &uid);
706 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
710 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
712 unlinkat(dirfd(d), de->d_name, 0);
726 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
731 HASHMAP_FOREACH(u, m->users, i) {
739 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
744 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
749 while ((k = cg_read_subgroup(d, &name)) > 0) {
752 if (streq(name, "shared"))
755 k = manager_add_session(m, u, name, &session);
761 session_add_to_gc_queue(session);
763 if (!session->cgroup_path)
764 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
782 int manager_enumerate_sessions(Manager *m) {
789 /* First enumerate session cgroups */
790 r = manager_enumerate_sessions_from_cgroup(m);
792 /* Second, read in session data stored on disk */
793 d = opendir("/run/systemd/sessions");
798 log_error("Failed to open /run/systemd/sessions: %m");
802 while ((de = readdir(d))) {
806 if (!dirent_is_file(de))
809 s = hashmap_get(m->sessions, de->d_name);
811 unlinkat(dirfd(d), de->d_name, 0);
825 int manager_enumerate_inhibitors(Manager *m) {
832 d = opendir("/run/systemd/inhibit");
837 log_error("Failed to open /run/systemd/inhibit: %m");
841 while ((de = readdir(d))) {
845 if (!dirent_is_file(de))
848 k = manager_add_inhibitor(m, de->d_name, &i);
850 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
855 k = inhibitor_load(i);
865 int manager_dispatch_seat_udev(Manager *m) {
866 struct udev_device *d;
871 d = udev_monitor_receive_device(m->udev_seat_monitor);
875 r = manager_process_seat_device(m, d);
876 udev_device_unref(d);
881 int manager_dispatch_vcsa_udev(Manager *m) {
882 struct udev_device *d;
888 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
892 name = udev_device_get_sysname(d);
894 /* Whenever a VCSA device is removed try to reallocate our
895 * VTs, to make sure our auto VTs never go away. */
897 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
898 r = seat_preallocate_vts(m->vtconsole);
900 udev_device_unref(d);
905 int manager_dispatch_button_udev(Manager *m) {
906 struct udev_device *d;
911 d = udev_monitor_receive_device(m->udev_button_monitor);
915 r = manager_process_button_device(m, d);
916 udev_device_unref(d);
921 int manager_dispatch_console(Manager *m) {
925 seat_read_active_vt(m->vtconsole);
930 static int vt_is_busy(int vtnr) {
931 struct vt_stat vt_stat;
936 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
937 * we'd open the latter we'd open the foreground tty which
938 * hence would be unconditionally busy. By opening /dev/tty1
939 * we avoid this. Since tty1 is special and needs to be an
940 * explicitly loaded getty or DM this is safe. */
942 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
946 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
949 r = !!(vt_stat.v_state & (1 << vtnr));
951 close_nointr_nofail(fd);
956 int manager_spawn_autovt(Manager *m, int vtnr) {
959 const char *mode = "fail";
964 if ((unsigned) vtnr > m->n_autovts &&
965 (unsigned) vtnr != m->reserve_vt)
968 if ((unsigned) vtnr != m->reserve_vt) {
969 /* If this is the reserved TTY, we'll start the getty
970 * on it in any case, but otherwise only if it is not
973 r = vt_is_busy(vtnr);
980 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
981 log_error("Could not allocate service name.");
986 r = bus_method_call_with_reply (
988 "org.freedesktop.systemd1",
989 "/org/freedesktop/systemd1",
990 "org.freedesktop.systemd1.Manager",
994 DBUS_TYPE_STRING, &name,
995 DBUS_TYPE_STRING, &mode,
1004 static int manager_reserve_vt(Manager *m) {
1005 _cleanup_free_ char *p = NULL;
1009 if (m->reserve_vt <= 0)
1012 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1015 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1016 if (m->reserve_vt_fd < 0) {
1018 /* Don't complain on VT-less systems */
1019 if (errno != ENOENT)
1020 log_warning("Failed to pin reserved VT: %m");
1027 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1035 s = hashmap_get(m->session_cgroups, cgroup);
1048 e = strrchr(p, '/');
1057 s = hashmap_get(m->session_cgroups, p);
1066 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1074 u = hashmap_get(m->user_cgroups, cgroup);
1087 e = strrchr(p, '/');
1096 u = hashmap_get(m->user_cgroups, p);
1105 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1113 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1117 r = manager_get_session_by_cgroup(m, p, session);
1123 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1128 r = manager_get_session_by_cgroup(m, cgroup, &s);
1130 session_add_to_gc_queue(s);
1132 r = manager_get_user_by_cgroup(m, cgroup, &u);
1134 user_add_to_gc_queue(u);
1137 static void manager_dispatch_other(Manager *m, int fd) {
1145 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1147 assert(s->fifo_fd == fd);
1148 session_remove_fifo(s);
1153 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1155 assert(i->fifo_fd == fd);
1161 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1163 assert(b->fd == fd);
1168 assert_not_reached("Got event for unknown fd");
1171 static int manager_connect_bus(Manager *m) {
1174 struct epoll_event ev;
1178 assert(m->bus_fd < 0);
1180 dbus_error_init(&error);
1182 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1184 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1189 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1190 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1191 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1192 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1193 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1198 dbus_bus_add_match(m->bus,
1200 "interface='org.freedesktop.systemd1.Agent',"
1201 "member='Released',"
1202 "path='/org/freedesktop/systemd1/agent'",
1205 if (dbus_error_is_set(&error)) {
1206 log_error("Failed to register match: %s", bus_error_message(&error));
1211 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1212 if (dbus_error_is_set(&error)) {
1213 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1218 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1219 log_error("Failed to acquire name.");
1224 m->bus_fd = bus_loop_open(m->bus);
1225 if (m->bus_fd < 0) {
1231 ev.events = EPOLLIN;
1232 ev.data.u32 = FD_BUS;
1234 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1240 dbus_error_free(&error);
1245 static int manager_connect_console(Manager *m) {
1246 struct epoll_event ev;
1249 assert(m->console_active_fd < 0);
1251 /* On certain architectures (S390 and Xen, and containers),
1252 /dev/tty0 does not exist, so don't fail if we can't open
1254 if (access("/dev/tty0", F_OK) < 0) {
1255 m->console_active_fd = -1;
1259 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1260 if (m->console_active_fd < 0) {
1262 /* On some systems the device node /dev/tty0 may exist
1263 * even though /sys/class/tty/tty0 does not. */
1264 if (errno == ENOENT)
1267 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1273 ev.data.u32 = FD_CONSOLE;
1275 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1281 static int manager_connect_udev(Manager *m) {
1282 struct epoll_event ev;
1286 assert(!m->udev_seat_monitor);
1287 assert(!m->udev_vcsa_monitor);
1288 assert(!m->udev_button_monitor);
1290 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1291 if (!m->udev_seat_monitor)
1294 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat-master");
1298 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1302 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1305 ev.events = EPOLLIN;
1306 ev.data.u32 = FD_SEAT_UDEV;
1307 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1310 /* Don't watch keys if nobody cares */
1311 if (m->handle_power_key != HANDLE_IGNORE ||
1312 m->handle_suspend_key != HANDLE_IGNORE ||
1313 m->handle_hibernate_key != HANDLE_IGNORE ||
1314 m->handle_lid_switch != HANDLE_IGNORE) {
1316 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1317 if (!m->udev_button_monitor)
1320 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1324 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1328 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1332 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1335 ev.events = EPOLLIN;
1336 ev.data.u32 = FD_BUTTON_UDEV;
1337 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1341 /* Don't bother watching VCSA devices, if nobody cares */
1342 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1344 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1345 if (!m->udev_vcsa_monitor)
1348 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1352 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1356 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1359 ev.events = EPOLLIN;
1360 ev.data.u32 = FD_VCSA_UDEV;
1361 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1368 void manager_gc(Manager *m, bool drop_not_started) {
1375 while ((seat = m->seat_gc_queue)) {
1376 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1377 seat->in_gc_queue = false;
1379 if (seat_check_gc(seat, drop_not_started) == 0) {
1385 while ((session = m->session_gc_queue)) {
1386 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1387 session->in_gc_queue = false;
1389 if (session_check_gc(session, drop_not_started) == 0) {
1390 session_stop(session);
1391 session_free(session);
1395 while ((user = m->user_gc_queue)) {
1396 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1397 user->in_gc_queue = false;
1399 if (user_check_gc(user, drop_not_started) == 0) {
1406 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1409 dual_timestamp ts = { 0, 0 };
1414 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1416 HASHMAP_FOREACH(s, m->sessions, i) {
1420 ih = session_get_idle_hint(s, &k);
1426 if (k.monotonic < ts.monotonic)
1432 } else if (idle_hint) {
1434 if (k.monotonic > ts.monotonic)
1445 int manager_dispatch_idle_action(Manager *m) {
1446 struct dual_timestamp since;
1447 struct itimerspec its;
1453 if (m->idle_action == HANDLE_IGNORE ||
1454 m->idle_action_usec <= 0) {
1460 n = now(CLOCK_MONOTONIC);
1462 r = manager_get_idle_hint(m, &since);
1464 /* Not idle. Let's check if after a timeout it it might be idle then. */
1465 timespec_store(&its.it_value, n + m->idle_action_usec);
1467 /* Idle! Let's see if it's time to do something, or if
1468 * we shall sleep for longer. */
1470 if (n >= since.monotonic + m->idle_action_usec &&
1471 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1472 log_info("System idle. Taking action.");
1474 manager_handle_action(m, 0, m->idle_action, false, false);
1475 m->idle_action_not_before_usec = n;
1478 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1481 if (m->idle_action_fd < 0) {
1482 struct epoll_event ev;
1484 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1485 if (m->idle_action_fd < 0) {
1486 log_error("Failed to create idle action timer: %m");
1492 ev.events = EPOLLIN;
1493 ev.data.u32 = FD_IDLE_ACTION;
1495 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1496 log_error("Failed to add idle action timer to epoll: %m");
1502 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1503 log_error("Failed to reset timerfd: %m");
1511 if (m->idle_action_fd >= 0) {
1512 close_nointr_nofail(m->idle_action_fd);
1513 m->idle_action_fd = -1;
1518 int manager_startup(Manager *m) {
1523 Inhibitor *inhibitor;
1527 assert(m->epoll_fd <= 0);
1529 cg_shorten_controllers(m->reset_controllers);
1530 cg_shorten_controllers(m->controllers);
1532 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1533 if (m->epoll_fd < 0)
1536 /* Connect to console */
1537 r = manager_connect_console(m);
1541 /* Connect to udev */
1542 r = manager_connect_udev(m);
1546 /* Connect to the bus */
1547 r = manager_connect_bus(m);
1551 /* Instantiate magic seat 0 */
1552 r = manager_add_seat(m, "seat0", &m->vtconsole);
1556 /* Deserialize state */
1557 manager_enumerate_devices(m);
1558 manager_enumerate_seats(m);
1559 manager_enumerate_users(m);
1560 manager_enumerate_sessions(m);
1561 manager_enumerate_inhibitors(m);
1562 manager_enumerate_buttons(m);
1564 /* Remove stale objects before we start them */
1565 manager_gc(m, false);
1567 /* Reserve the special reserved VT */
1568 manager_reserve_vt(m);
1570 /* And start everything */
1571 HASHMAP_FOREACH(seat, m->seats, i)
1574 HASHMAP_FOREACH(user, m->users, i)
1577 HASHMAP_FOREACH(session, m->sessions, i)
1578 session_start(session);
1580 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1581 inhibitor_start(inhibitor);
1583 manager_dispatch_idle_action(m);
1588 static int manager_recheck_buttons(Manager *m) {
1595 HASHMAP_FOREACH(b, m->buttons, i) {
1598 q = button_recheck(b);
1608 int manager_run(Manager *m) {
1612 struct epoll_event event;
1616 manager_gc(m, true);
1618 if (manager_dispatch_delayed(m) > 0)
1621 if (manager_recheck_buttons(m) > 0)
1624 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1627 manager_gc(m, true);
1629 if (m->delayed_unit) {
1632 x = now(CLOCK_MONOTONIC);
1633 y = m->delayed_timestamp + m->inhibit_delay_max;
1635 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1638 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1640 if (errno == EINTR || errno == EAGAIN)
1643 log_error("epoll() failed: %m");
1650 switch (event.data.u32) {
1653 manager_dispatch_seat_udev(m);
1657 manager_dispatch_vcsa_udev(m);
1660 case FD_BUTTON_UDEV:
1661 manager_dispatch_button_udev(m);
1665 manager_dispatch_console(m);
1668 case FD_IDLE_ACTION:
1669 manager_dispatch_idle_action(m);
1673 bus_loop_dispatch(m->bus_fd);
1677 if (event.data.u32 >= FD_OTHER_BASE)
1678 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1685 static int manager_parse_config_file(Manager *m) {
1692 fn = "/etc/systemd/logind.conf";
1693 f = fopen(fn, "re");
1695 if (errno == ENOENT)
1698 log_warning("Failed to open configuration file %s: %m", fn);
1702 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1704 log_warning("Failed to parse configuration file: %s", strerror(-r));
1711 int main(int argc, char *argv[]) {
1715 log_set_target(LOG_TARGET_AUTO);
1716 log_set_facility(LOG_AUTH);
1717 log_parse_environment();
1723 log_error("This program takes no arguments.");
1734 manager_parse_config_file(m);
1736 r = manager_startup(m);
1738 log_error("Failed to fully start up daemon: %s", strerror(-r));
1742 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1746 "STATUS=Processing requests...");
1750 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1754 "STATUS=Shutting down...");
1759 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;