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_subsystem(e, "graphics");
466 r = udev_enumerate_add_match_tag(e, "seat");
470 r = udev_enumerate_scan_devices(e);
474 first = udev_enumerate_get_list_entry(e);
475 udev_list_entry_foreach(item, first) {
476 struct udev_device *d;
479 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
485 k = manager_process_seat_device(m, d);
486 udev_device_unref(d);
494 udev_enumerate_unref(e);
499 int manager_enumerate_buttons(Manager *m) {
500 struct udev_list_entry *item = NULL, *first = NULL;
501 struct udev_enumerate *e;
506 /* Loads buttons from udev */
508 if (m->handle_power_key == HANDLE_IGNORE &&
509 m->handle_suspend_key == HANDLE_IGNORE &&
510 m->handle_hibernate_key == HANDLE_IGNORE &&
511 m->handle_lid_switch == HANDLE_IGNORE)
514 e = udev_enumerate_new(m->udev);
520 r = udev_enumerate_add_match_subsystem(e, "input");
524 r = udev_enumerate_add_match_tag(e, "power-switch");
528 r = udev_enumerate_scan_devices(e);
532 first = udev_enumerate_get_list_entry(e);
533 udev_list_entry_foreach(item, first) {
534 struct udev_device *d;
537 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
543 k = manager_process_button_device(m, d);
544 udev_device_unref(d);
552 udev_enumerate_unref(e);
557 int manager_enumerate_seats(Manager *m) {
564 /* This loads data about seats stored on disk, but does not
565 * actually create any seats. Removes data of seats that no
568 d = opendir("/run/systemd/seats");
573 log_error("Failed to open /run/systemd/seats: %m");
577 while ((de = readdir(d))) {
581 if (!dirent_is_file(de))
584 s = hashmap_get(m->seats, de->d_name);
586 unlinkat(dirfd(d), de->d_name, 0);
600 static int manager_enumerate_users_from_cgroup(Manager *m) {
605 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
610 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
614 while ((k = cg_read_subgroup(d, &name)) > 0) {
617 k = manager_add_user_by_name(m, name, &user);
624 user_add_to_gc_queue(user);
626 if (!user->cgroup_path)
627 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
644 static int manager_enumerate_linger_users(Manager *m) {
649 d = opendir("/var/lib/systemd/linger");
654 log_error("Failed to open /var/lib/systemd/linger/: %m");
658 while ((de = readdir(d))) {
661 if (!dirent_is_file(de))
664 k = manager_add_user_by_name(m, de->d_name, NULL);
666 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
676 int manager_enumerate_users(Manager *m) {
683 /* First, enumerate user cgroups */
684 r = manager_enumerate_users_from_cgroup(m);
686 /* Second, add lingering users on top */
687 k = manager_enumerate_linger_users(m);
691 /* Third, read in user data stored on disk */
692 d = opendir("/run/systemd/users");
697 log_error("Failed to open /run/systemd/users: %m");
701 while ((de = readdir(d))) {
705 if (!dirent_is_file(de))
708 k = parse_uid(de->d_name, &uid);
710 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
714 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
716 unlinkat(dirfd(d), de->d_name, 0);
730 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
735 HASHMAP_FOREACH(u, m->users, i) {
743 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
748 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
753 while ((k = cg_read_subgroup(d, &name)) > 0) {
756 if (streq(name, "shared"))
759 k = manager_add_session(m, u, name, &session);
765 session_add_to_gc_queue(session);
767 if (!session->cgroup_path)
768 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
786 int manager_enumerate_sessions(Manager *m) {
793 /* First enumerate session cgroups */
794 r = manager_enumerate_sessions_from_cgroup(m);
796 /* Second, read in session data stored on disk */
797 d = opendir("/run/systemd/sessions");
802 log_error("Failed to open /run/systemd/sessions: %m");
806 while ((de = readdir(d))) {
810 if (!dirent_is_file(de))
813 s = hashmap_get(m->sessions, de->d_name);
815 unlinkat(dirfd(d), de->d_name, 0);
829 int manager_enumerate_inhibitors(Manager *m) {
836 d = opendir("/run/systemd/inhibit");
841 log_error("Failed to open /run/systemd/inhibit: %m");
845 while ((de = readdir(d))) {
849 if (!dirent_is_file(de))
852 k = manager_add_inhibitor(m, de->d_name, &i);
854 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
859 k = inhibitor_load(i);
869 int manager_dispatch_seat_udev(Manager *m) {
870 struct udev_device *d;
875 d = udev_monitor_receive_device(m->udev_seat_monitor);
879 r = manager_process_seat_device(m, d);
880 udev_device_unref(d);
885 int manager_dispatch_vcsa_udev(Manager *m) {
886 struct udev_device *d;
892 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
896 name = udev_device_get_sysname(d);
898 /* Whenever a VCSA device is removed try to reallocate our
899 * VTs, to make sure our auto VTs never go away. */
901 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
902 r = seat_preallocate_vts(m->vtconsole);
904 udev_device_unref(d);
909 int manager_dispatch_button_udev(Manager *m) {
910 struct udev_device *d;
915 d = udev_monitor_receive_device(m->udev_button_monitor);
919 r = manager_process_button_device(m, d);
920 udev_device_unref(d);
925 int manager_dispatch_console(Manager *m) {
929 seat_read_active_vt(m->vtconsole);
934 static int vt_is_busy(int vtnr) {
935 struct vt_stat vt_stat;
940 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
941 * we'd open the latter we'd open the foreground tty which
942 * hence would be unconditionally busy. By opening /dev/tty1
943 * we avoid this. Since tty1 is special and needs to be an
944 * explicitly loaded getty or DM this is safe. */
946 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
950 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
953 r = !!(vt_stat.v_state & (1 << vtnr));
955 close_nointr_nofail(fd);
960 int manager_spawn_autovt(Manager *m, int vtnr) {
963 const char *mode = "fail";
968 if ((unsigned) vtnr > m->n_autovts &&
969 (unsigned) vtnr != m->reserve_vt)
972 if ((unsigned) vtnr != m->reserve_vt) {
973 /* If this is the reserved TTY, we'll start the getty
974 * on it in any case, but otherwise only if it is not
977 r = vt_is_busy(vtnr);
984 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
985 log_error("Could not allocate service name.");
990 r = bus_method_call_with_reply (
992 "org.freedesktop.systemd1",
993 "/org/freedesktop/systemd1",
994 "org.freedesktop.systemd1.Manager",
998 DBUS_TYPE_STRING, &name,
999 DBUS_TYPE_STRING, &mode,
1008 static int manager_reserve_vt(Manager *m) {
1009 _cleanup_free_ char *p = NULL;
1013 if (m->reserve_vt <= 0)
1016 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1019 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1020 if (m->reserve_vt_fd < 0) {
1022 /* Don't complain on VT-less systems */
1023 if (errno != ENOENT)
1024 log_warning("Failed to pin reserved VT: %m");
1031 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1039 s = hashmap_get(m->session_cgroups, cgroup);
1052 e = strrchr(p, '/');
1061 s = hashmap_get(m->session_cgroups, p);
1070 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1078 u = hashmap_get(m->user_cgroups, cgroup);
1091 e = strrchr(p, '/');
1100 u = hashmap_get(m->user_cgroups, p);
1109 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1117 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1121 r = manager_get_session_by_cgroup(m, p, session);
1127 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1132 r = manager_get_session_by_cgroup(m, cgroup, &s);
1134 session_add_to_gc_queue(s);
1136 r = manager_get_user_by_cgroup(m, cgroup, &u);
1138 user_add_to_gc_queue(u);
1141 static void manager_dispatch_other(Manager *m, int fd) {
1149 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1151 assert(s->fifo_fd == fd);
1152 session_remove_fifo(s);
1157 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1159 assert(i->fifo_fd == fd);
1165 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1167 assert(b->fd == fd);
1172 assert_not_reached("Got event for unknown fd");
1175 static int manager_connect_bus(Manager *m) {
1178 struct epoll_event ev;
1182 assert(m->bus_fd < 0);
1184 dbus_error_init(&error);
1186 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1188 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1193 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1194 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1195 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1196 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1197 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1202 dbus_bus_add_match(m->bus,
1204 "interface='org.freedesktop.systemd1.Agent',"
1205 "member='Released',"
1206 "path='/org/freedesktop/systemd1/agent'",
1209 if (dbus_error_is_set(&error)) {
1210 log_error("Failed to register match: %s", bus_error_message(&error));
1215 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1216 if (dbus_error_is_set(&error)) {
1217 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1222 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1223 log_error("Failed to acquire name.");
1228 m->bus_fd = bus_loop_open(m->bus);
1229 if (m->bus_fd < 0) {
1235 ev.events = EPOLLIN;
1236 ev.data.u32 = FD_BUS;
1238 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1244 dbus_error_free(&error);
1249 static int manager_connect_console(Manager *m) {
1250 struct epoll_event ev;
1253 assert(m->console_active_fd < 0);
1255 /* On certain architectures (S390 and Xen, and containers),
1256 /dev/tty0 does not exist, so don't fail if we can't open
1258 if (access("/dev/tty0", F_OK) < 0) {
1259 m->console_active_fd = -1;
1263 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1264 if (m->console_active_fd < 0) {
1266 /* On some systems the device node /dev/tty0 may exist
1267 * even though /sys/class/tty/tty0 does not. */
1268 if (errno == ENOENT)
1271 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1277 ev.data.u32 = FD_CONSOLE;
1279 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1285 static int manager_connect_udev(Manager *m) {
1286 struct epoll_event ev;
1290 assert(!m->udev_seat_monitor);
1291 assert(!m->udev_vcsa_monitor);
1292 assert(!m->udev_button_monitor);
1294 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1295 if (!m->udev_seat_monitor)
1298 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1302 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1306 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1310 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1313 ev.events = EPOLLIN;
1314 ev.data.u32 = FD_SEAT_UDEV;
1315 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1318 /* Don't watch keys if nobody cares */
1319 if (m->handle_power_key != HANDLE_IGNORE ||
1320 m->handle_suspend_key != HANDLE_IGNORE ||
1321 m->handle_hibernate_key != HANDLE_IGNORE ||
1322 m->handle_lid_switch != HANDLE_IGNORE) {
1324 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1325 if (!m->udev_button_monitor)
1328 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1332 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1336 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1340 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1343 ev.events = EPOLLIN;
1344 ev.data.u32 = FD_BUTTON_UDEV;
1345 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1349 /* Don't bother watching VCSA devices, if nobody cares */
1350 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1352 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1353 if (!m->udev_vcsa_monitor)
1356 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1360 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1364 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1367 ev.events = EPOLLIN;
1368 ev.data.u32 = FD_VCSA_UDEV;
1369 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1376 void manager_gc(Manager *m, bool drop_not_started) {
1383 while ((seat = m->seat_gc_queue)) {
1384 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1385 seat->in_gc_queue = false;
1387 if (seat_check_gc(seat, drop_not_started) == 0) {
1393 while ((session = m->session_gc_queue)) {
1394 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1395 session->in_gc_queue = false;
1397 if (session_check_gc(session, drop_not_started) == 0) {
1398 session_stop(session);
1399 session_free(session);
1403 while ((user = m->user_gc_queue)) {
1404 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1405 user->in_gc_queue = false;
1407 if (user_check_gc(user, drop_not_started) == 0) {
1414 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1417 dual_timestamp ts = { 0, 0 };
1422 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1424 HASHMAP_FOREACH(s, m->sessions, i) {
1428 ih = session_get_idle_hint(s, &k);
1434 if (k.monotonic < ts.monotonic)
1440 } else if (idle_hint) {
1442 if (k.monotonic > ts.monotonic)
1453 int manager_dispatch_idle_action(Manager *m) {
1454 struct dual_timestamp since;
1455 struct itimerspec its;
1461 if (m->idle_action == HANDLE_IGNORE ||
1462 m->idle_action_usec <= 0) {
1468 n = now(CLOCK_MONOTONIC);
1470 r = manager_get_idle_hint(m, &since);
1472 /* Not idle. Let's check if after a timeout it it might be idle then. */
1473 timespec_store(&its.it_value, n + m->idle_action_usec);
1475 /* Idle! Let's see if it's time to do something, or if
1476 * we shall sleep for longer. */
1478 if (n >= since.monotonic + m->idle_action_usec &&
1479 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1480 log_info("System idle. Taking action.");
1482 manager_handle_action(m, 0, m->idle_action, false, false);
1483 m->idle_action_not_before_usec = n;
1486 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1489 if (m->idle_action_fd < 0) {
1490 struct epoll_event ev;
1492 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1493 if (m->idle_action_fd < 0) {
1494 log_error("Failed to create idle action timer: %m");
1500 ev.events = EPOLLIN;
1501 ev.data.u32 = FD_IDLE_ACTION;
1503 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1504 log_error("Failed to add idle action timer to epoll: %m");
1510 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1511 log_error("Failed to reset timerfd: %m");
1519 if (m->idle_action_fd >= 0) {
1520 close_nointr_nofail(m->idle_action_fd);
1521 m->idle_action_fd = -1;
1526 int manager_startup(Manager *m) {
1531 Inhibitor *inhibitor;
1535 assert(m->epoll_fd <= 0);
1537 cg_shorten_controllers(m->reset_controllers);
1538 cg_shorten_controllers(m->controllers);
1540 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1541 if (m->epoll_fd < 0)
1544 /* Connect to console */
1545 r = manager_connect_console(m);
1549 /* Connect to udev */
1550 r = manager_connect_udev(m);
1554 /* Connect to the bus */
1555 r = manager_connect_bus(m);
1559 /* Instantiate magic seat 0 */
1560 r = manager_add_seat(m, "seat0", &m->vtconsole);
1564 /* Deserialize state */
1565 manager_enumerate_devices(m);
1566 manager_enumerate_seats(m);
1567 manager_enumerate_users(m);
1568 manager_enumerate_sessions(m);
1569 manager_enumerate_inhibitors(m);
1570 manager_enumerate_buttons(m);
1572 /* Remove stale objects before we start them */
1573 manager_gc(m, false);
1575 /* Reserve the special reserved VT */
1576 manager_reserve_vt(m);
1578 /* And start everything */
1579 HASHMAP_FOREACH(seat, m->seats, i)
1582 HASHMAP_FOREACH(user, m->users, i)
1585 HASHMAP_FOREACH(session, m->sessions, i)
1586 session_start(session);
1588 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1589 inhibitor_start(inhibitor);
1591 manager_dispatch_idle_action(m);
1596 static int manager_recheck_buttons(Manager *m) {
1603 HASHMAP_FOREACH(b, m->buttons, i) {
1606 q = button_recheck(b);
1616 int manager_run(Manager *m) {
1620 struct epoll_event event;
1624 manager_gc(m, true);
1626 if (manager_dispatch_delayed(m) > 0)
1629 if (manager_recheck_buttons(m) > 0)
1632 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1635 manager_gc(m, true);
1637 if (m->delayed_unit) {
1640 x = now(CLOCK_MONOTONIC);
1641 y = m->delayed_timestamp + m->inhibit_delay_max;
1643 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1646 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1648 if (errno == EINTR || errno == EAGAIN)
1651 log_error("epoll() failed: %m");
1658 switch (event.data.u32) {
1661 manager_dispatch_seat_udev(m);
1665 manager_dispatch_vcsa_udev(m);
1668 case FD_BUTTON_UDEV:
1669 manager_dispatch_button_udev(m);
1673 manager_dispatch_console(m);
1676 case FD_IDLE_ACTION:
1677 manager_dispatch_idle_action(m);
1681 bus_loop_dispatch(m->bus_fd);
1685 if (event.data.u32 >= FD_OTHER_BASE)
1686 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1693 static int manager_parse_config_file(Manager *m) {
1700 fn = "/etc/systemd/logind.conf";
1701 f = fopen(fn, "re");
1703 if (errno == ENOENT)
1706 log_warning("Failed to open configuration file %s: %m", fn);
1710 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1712 log_warning("Failed to parse configuration file: %s", strerror(-r));
1719 int main(int argc, char *argv[]) {
1723 log_set_target(LOG_TARGET_AUTO);
1724 log_set_facility(LOG_AUTH);
1725 log_parse_environment();
1731 log_error("This program takes no arguments.");
1742 manager_parse_config_file(m);
1744 r = manager_startup(m);
1746 log_error("Failed to fully start up daemon: %s", strerror(-r));
1750 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1754 "STATUS=Processing requests...");
1758 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1762 "STATUS=Shutting down...");
1767 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;