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>
32 #include <systemd/sd-daemon.h>
35 #include "dbus-common.h"
36 #include "dbus-loop.h"
38 #include "conf-parser.h"
40 Manager *manager_new(void) {
47 m->console_active_fd = -1;
51 m->udev_button_fd = -1;
53 m->reserve_vt_fd = -1;
57 m->inhibit_delay_max = 5 * USEC_PER_SEC;
58 m->handle_power_key = HANDLE_POWEROFF;
59 m->handle_suspend_key = HANDLE_SUSPEND;
60 m->handle_hibernate_key = HANDLE_HIBERNATE;
61 m->handle_lid_switch = HANDLE_SUSPEND;
62 m->lid_switch_ignore_inhibited = true;
64 m->devices = hashmap_new(string_hash_func, string_compare_func);
65 m->seats = hashmap_new(string_hash_func, string_compare_func);
66 m->sessions = hashmap_new(string_hash_func, string_compare_func);
67 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
68 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
69 m->buttons = hashmap_new(string_hash_func, string_compare_func);
71 m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
72 m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
74 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
75 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
76 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
78 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
79 !m->user_cgroups || !m->session_cgroups ||
80 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
85 m->reset_controllers = strv_new("cpu", NULL);
86 m->kill_exclude_users = strv_new("root", NULL);
87 if (!m->reset_controllers || !m->kill_exclude_users) {
98 if (cg_get_user_path(&m->cgroup_path) < 0) {
106 void manager_free(Manager *m) {
116 while ((session = hashmap_first(m->sessions)))
117 session_free(session);
119 while ((u = hashmap_first(m->users)))
122 while ((d = hashmap_first(m->devices)))
125 while ((s = hashmap_first(m->seats)))
128 while ((i = hashmap_first(m->inhibitors)))
131 while ((b = hashmap_first(m->buttons)))
134 hashmap_free(m->devices);
135 hashmap_free(m->seats);
136 hashmap_free(m->sessions);
137 hashmap_free(m->users);
138 hashmap_free(m->inhibitors);
139 hashmap_free(m->buttons);
141 hashmap_free(m->user_cgroups);
142 hashmap_free(m->session_cgroups);
144 hashmap_free(m->session_fds);
145 hashmap_free(m->inhibitor_fds);
146 hashmap_free(m->button_fds);
148 if (m->console_active_fd >= 0)
149 close_nointr_nofail(m->console_active_fd);
151 if (m->udev_seat_monitor)
152 udev_monitor_unref(m->udev_seat_monitor);
153 if (m->udev_vcsa_monitor)
154 udev_monitor_unref(m->udev_vcsa_monitor);
155 if (m->udev_button_monitor)
156 udev_monitor_unref(m->udev_button_monitor);
162 dbus_connection_flush(m->bus);
163 dbus_connection_close(m->bus);
164 dbus_connection_unref(m->bus);
168 close_nointr_nofail(m->bus_fd);
170 if (m->epoll_fd >= 0)
171 close_nointr_nofail(m->epoll_fd);
173 if (m->reserve_vt_fd >= 0)
174 close_nointr_nofail(m->reserve_vt_fd);
176 strv_free(m->controllers);
177 strv_free(m->reset_controllers);
178 strv_free(m->kill_only_users);
179 strv_free(m->kill_exclude_users);
181 free(m->cgroup_path);
185 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
191 d = hashmap_get(m->devices, sysfs);
199 d = device_new(m, sysfs);
209 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
215 s = hashmap_get(m->seats, id);
233 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
239 s = hashmap_get(m->sessions, id);
247 s = session_new(m, u, id);
257 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
263 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
271 u = user_new(m, uid, gid, name);
281 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
289 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
293 return manager_add_user(m, uid, gid, name, _user);
296 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
304 return errno ? -errno : -ENOENT;
306 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
309 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
315 i = hashmap_get(m->inhibitors, id);
323 i = inhibitor_new(m, id);
333 int manager_add_button(Manager *m, const char *name, Button **_button) {
339 b = hashmap_get(m->buttons, name);
347 b = button_new(m, name);
357 int manager_process_seat_device(Manager *m, struct udev_device *d) {
363 if (streq_ptr(udev_device_get_action(d), "remove")) {
365 device = hashmap_get(m->devices, udev_device_get_syspath(d));
369 seat_add_to_gc_queue(device->seat);
376 sn = udev_device_get_property_value(d, "ID_SEAT");
380 if (!seat_name_is_valid(sn)) {
381 log_warning("Device with invalid seat name %s found, ignoring.", sn);
385 r = manager_add_device(m, udev_device_get_syspath(d), &device);
389 r = manager_add_seat(m, sn, &seat);
397 device_attach(device, seat);
404 int manager_process_button_device(Manager *m, struct udev_device *d) {
411 if (streq_ptr(udev_device_get_action(d), "remove")) {
413 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
422 r = manager_add_button(m, udev_device_get_sysname(d), &b);
426 sn = udev_device_get_property_value(d, "ID_SEAT");
430 button_set_seat(b, sn);
437 int manager_enumerate_devices(Manager *m) {
438 struct udev_list_entry *item = NULL, *first = NULL;
439 struct udev_enumerate *e;
444 /* Loads devices from udev and creates seats for them as
447 e = udev_enumerate_new(m->udev);
453 r = udev_enumerate_add_match_subsystem(e, "graphics");
457 r = udev_enumerate_add_match_tag(e, "seat");
461 r = udev_enumerate_scan_devices(e);
465 first = udev_enumerate_get_list_entry(e);
466 udev_list_entry_foreach(item, first) {
467 struct udev_device *d;
470 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
476 k = manager_process_seat_device(m, d);
477 udev_device_unref(d);
485 udev_enumerate_unref(e);
490 int manager_enumerate_buttons(Manager *m) {
491 struct udev_list_entry *item = NULL, *first = NULL;
492 struct udev_enumerate *e;
497 /* Loads buttons from udev */
499 if (m->handle_power_key == HANDLE_IGNORE &&
500 m->handle_suspend_key == HANDLE_IGNORE &&
501 m->handle_hibernate_key == HANDLE_IGNORE &&
502 m->handle_lid_switch == HANDLE_IGNORE)
505 e = udev_enumerate_new(m->udev);
511 r = udev_enumerate_add_match_subsystem(e, "input");
515 r = udev_enumerate_add_match_tag(e, "power-switch");
519 r = udev_enumerate_scan_devices(e);
523 first = udev_enumerate_get_list_entry(e);
524 udev_list_entry_foreach(item, first) {
525 struct udev_device *d;
528 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
534 k = manager_process_button_device(m, d);
535 udev_device_unref(d);
543 udev_enumerate_unref(e);
548 int manager_enumerate_seats(Manager *m) {
555 /* This loads data about seats stored on disk, but does not
556 * actually create any seats. Removes data of seats that no
559 d = opendir("/run/systemd/seats");
564 log_error("Failed to open /run/systemd/seats: %m");
568 while ((de = readdir(d))) {
572 if (!dirent_is_file(de))
575 s = hashmap_get(m->seats, de->d_name);
577 unlinkat(dirfd(d), de->d_name, 0);
591 static int manager_enumerate_users_from_cgroup(Manager *m) {
596 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
601 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
605 while ((k = cg_read_subgroup(d, &name)) > 0) {
608 k = manager_add_user_by_name(m, name, &user);
615 user_add_to_gc_queue(user);
617 if (!user->cgroup_path)
618 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
635 static int manager_enumerate_linger_users(Manager *m) {
640 d = opendir("/var/lib/systemd/linger");
645 log_error("Failed to open /var/lib/systemd/linger/: %m");
649 while ((de = readdir(d))) {
652 if (!dirent_is_file(de))
655 k = manager_add_user_by_name(m, de->d_name, NULL);
657 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
667 int manager_enumerate_users(Manager *m) {
674 /* First, enumerate user cgroups */
675 r = manager_enumerate_users_from_cgroup(m);
677 /* Second, add lingering users on top */
678 k = manager_enumerate_linger_users(m);
682 /* Third, read in user data stored on disk */
683 d = opendir("/run/systemd/users");
688 log_error("Failed to open /run/systemd/users: %m");
692 while ((de = readdir(d))) {
696 if (!dirent_is_file(de))
699 k = parse_uid(de->d_name, &uid);
701 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
705 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
707 unlinkat(dirfd(d), de->d_name, 0);
721 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
726 HASHMAP_FOREACH(u, m->users, i) {
734 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
739 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
744 while ((k = cg_read_subgroup(d, &name)) > 0) {
747 if (streq(name, "shared"))
750 k = manager_add_session(m, u, name, &session);
756 session_add_to_gc_queue(session);
758 if (!session->cgroup_path)
759 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
777 int manager_enumerate_sessions(Manager *m) {
784 /* First enumerate session cgroups */
785 r = manager_enumerate_sessions_from_cgroup(m);
787 /* Second, read in session data stored on disk */
788 d = opendir("/run/systemd/sessions");
793 log_error("Failed to open /run/systemd/sessions: %m");
797 while ((de = readdir(d))) {
801 if (!dirent_is_file(de))
804 s = hashmap_get(m->sessions, de->d_name);
806 unlinkat(dirfd(d), de->d_name, 0);
820 int manager_enumerate_inhibitors(Manager *m) {
827 d = opendir("/run/systemd/inhibit");
832 log_error("Failed to open /run/systemd/inhibit: %m");
836 while ((de = readdir(d))) {
840 if (!dirent_is_file(de))
843 k = manager_add_inhibitor(m, de->d_name, &i);
845 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
850 k = inhibitor_load(i);
860 int manager_dispatch_seat_udev(Manager *m) {
861 struct udev_device *d;
866 d = udev_monitor_receive_device(m->udev_seat_monitor);
870 r = manager_process_seat_device(m, d);
871 udev_device_unref(d);
876 int manager_dispatch_vcsa_udev(Manager *m) {
877 struct udev_device *d;
883 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
887 name = udev_device_get_sysname(d);
889 /* Whenever a VCSA device is removed try to reallocate our
890 * VTs, to make sure our auto VTs never go away. */
892 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
893 r = seat_preallocate_vts(m->vtconsole);
895 udev_device_unref(d);
900 int manager_dispatch_button_udev(Manager *m) {
901 struct udev_device *d;
906 d = udev_monitor_receive_device(m->udev_button_monitor);
910 r = manager_process_button_device(m, d);
911 udev_device_unref(d);
916 int manager_dispatch_console(Manager *m) {
920 seat_read_active_vt(m->vtconsole);
925 static int vt_is_busy(int vtnr) {
926 struct vt_stat vt_stat;
931 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
932 * we'd open the latter we'd open the foreground tty which
933 * hence would be unconditionally busy. By opening /dev/tty1
934 * we avoid this. Since tty1 is special and needs to be an
935 * explicitly loaded getty or DM this is safe. */
937 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
941 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
944 r = !!(vt_stat.v_state & (1 << vtnr));
946 close_nointr_nofail(fd);
951 int manager_spawn_autovt(Manager *m, int vtnr) {
954 const char *mode = "fail";
959 if ((unsigned) vtnr > m->n_autovts &&
960 (unsigned) vtnr != m->reserve_vt)
963 if ((unsigned) vtnr != m->reserve_vt) {
964 /* If this is the reserved TTY, we'll start the getty
965 * on it in any case, but otherwise only if it is not
968 r = vt_is_busy(vtnr);
975 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
976 log_error("Could not allocate service name.");
981 r = bus_method_call_with_reply (
983 "org.freedesktop.systemd1",
984 "/org/freedesktop/systemd1",
985 "org.freedesktop.systemd1.Manager",
989 DBUS_TYPE_STRING, &name,
990 DBUS_TYPE_STRING, &mode,
999 static int manager_reserve_vt(Manager *m) {
1000 _cleanup_free_ char *p = NULL;
1004 if (m->reserve_vt <= 0)
1007 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1010 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1011 if (m->reserve_vt_fd < 0) {
1013 /* Don't complain on VT-less systems */
1014 if (errno != ENOENT)
1015 log_warning("Failed to pin reserved VT: %m");
1022 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1030 s = hashmap_get(m->session_cgroups, cgroup);
1043 e = strrchr(p, '/');
1052 s = hashmap_get(m->session_cgroups, p);
1061 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1069 u = hashmap_get(m->user_cgroups, cgroup);
1082 e = strrchr(p, '/');
1091 u = hashmap_get(m->user_cgroups, p);
1100 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1108 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1112 r = manager_get_session_by_cgroup(m, p, session);
1118 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1123 r = manager_get_session_by_cgroup(m, cgroup, &s);
1125 session_add_to_gc_queue(s);
1127 r = manager_get_user_by_cgroup(m, cgroup, &u);
1129 user_add_to_gc_queue(u);
1132 static void manager_dispatch_other(Manager *m, int fd) {
1140 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1142 assert(s->fifo_fd == fd);
1143 session_remove_fifo(s);
1148 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1150 assert(i->fifo_fd == fd);
1156 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1158 assert(b->fd == fd);
1163 assert_not_reached("Got event for unknown fd");
1166 static int manager_connect_bus(Manager *m) {
1169 struct epoll_event ev;
1173 assert(m->bus_fd < 0);
1175 dbus_error_init(&error);
1177 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1179 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1184 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1185 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1186 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1187 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1188 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1193 dbus_bus_add_match(m->bus,
1195 "interface='org.freedesktop.systemd1.Agent',"
1196 "member='Released',"
1197 "path='/org/freedesktop/systemd1/agent'",
1200 if (dbus_error_is_set(&error)) {
1201 log_error("Failed to register match: %s", bus_error_message(&error));
1206 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1207 if (dbus_error_is_set(&error)) {
1208 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1213 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1214 log_error("Failed to acquire name.");
1219 m->bus_fd = bus_loop_open(m->bus);
1220 if (m->bus_fd < 0) {
1226 ev.events = EPOLLIN;
1227 ev.data.u32 = FD_BUS;
1229 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1235 dbus_error_free(&error);
1240 static int manager_connect_console(Manager *m) {
1241 struct epoll_event ev;
1244 assert(m->console_active_fd < 0);
1246 /* On certain architectures (S390 and Xen, and containers),
1247 /dev/tty0 does not exist, so don't fail if we can't open
1249 if (access("/dev/tty0", F_OK) < 0) {
1250 m->console_active_fd = -1;
1254 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1255 if (m->console_active_fd < 0) {
1257 /* On some systems the device node /dev/tty0 may exist
1258 * even though /sys/class/tty/tty0 does not. */
1259 if (errno == ENOENT)
1262 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1268 ev.data.u32 = FD_CONSOLE;
1270 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1276 static int manager_connect_udev(Manager *m) {
1277 struct epoll_event ev;
1281 assert(!m->udev_seat_monitor);
1282 assert(!m->udev_vcsa_monitor);
1283 assert(!m->udev_button_monitor);
1285 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1286 if (!m->udev_seat_monitor)
1289 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1293 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1297 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1301 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1304 ev.events = EPOLLIN;
1305 ev.data.u32 = FD_SEAT_UDEV;
1306 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1309 /* Don't watch keys if nobody cares */
1310 if (m->handle_power_key != HANDLE_IGNORE ||
1311 m->handle_suspend_key != HANDLE_IGNORE ||
1312 m->handle_hibernate_key != HANDLE_IGNORE ||
1313 m->handle_lid_switch != HANDLE_IGNORE) {
1315 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1316 if (!m->udev_button_monitor)
1319 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1323 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1327 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1331 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1334 ev.events = EPOLLIN;
1335 ev.data.u32 = FD_BUTTON_UDEV;
1336 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1340 /* Don't bother watching VCSA devices, if nobody cares */
1341 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1343 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1344 if (!m->udev_vcsa_monitor)
1347 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1351 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1355 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1358 ev.events = EPOLLIN;
1359 ev.data.u32 = FD_VCSA_UDEV;
1360 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1367 void manager_gc(Manager *m, bool drop_not_started) {
1374 while ((seat = m->seat_gc_queue)) {
1375 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1376 seat->in_gc_queue = false;
1378 if (seat_check_gc(seat, drop_not_started) == 0) {
1384 while ((session = m->session_gc_queue)) {
1385 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1386 session->in_gc_queue = false;
1388 if (session_check_gc(session, drop_not_started) == 0) {
1389 session_stop(session);
1390 session_free(session);
1394 while ((user = m->user_gc_queue)) {
1395 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1396 user->in_gc_queue = false;
1398 if (user_check_gc(user, drop_not_started) == 0) {
1405 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1408 dual_timestamp ts = { 0, 0 };
1413 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1415 HASHMAP_FOREACH(s, m->sessions, i) {
1419 ih = session_get_idle_hint(s, &k);
1425 if (k.monotonic < ts.monotonic)
1431 } else if (idle_hint) {
1433 if (k.monotonic > ts.monotonic)
1444 int manager_startup(Manager *m) {
1449 Inhibitor *inhibitor;
1453 assert(m->epoll_fd <= 0);
1455 cg_shorten_controllers(m->reset_controllers);
1456 cg_shorten_controllers(m->controllers);
1458 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1459 if (m->epoll_fd < 0)
1462 /* Connect to console */
1463 r = manager_connect_console(m);
1467 /* Connect to udev */
1468 r = manager_connect_udev(m);
1472 /* Connect to the bus */
1473 r = manager_connect_bus(m);
1477 /* Instantiate magic seat 0 */
1478 r = manager_add_seat(m, "seat0", &m->vtconsole);
1482 /* Deserialize state */
1483 manager_enumerate_devices(m);
1484 manager_enumerate_seats(m);
1485 manager_enumerate_users(m);
1486 manager_enumerate_sessions(m);
1487 manager_enumerate_inhibitors(m);
1488 manager_enumerate_buttons(m);
1490 /* Remove stale objects before we start them */
1491 manager_gc(m, false);
1493 /* Reserve the special reserved VT */
1494 manager_reserve_vt(m);
1496 /* And start everything */
1497 HASHMAP_FOREACH(seat, m->seats, i)
1500 HASHMAP_FOREACH(user, m->users, i)
1503 HASHMAP_FOREACH(session, m->sessions, i)
1504 session_start(session);
1506 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1507 inhibitor_start(inhibitor);
1512 static int manager_recheck_buttons(Manager *m) {
1519 HASHMAP_FOREACH(b, m->buttons, i) {
1522 q = button_recheck(b);
1532 int manager_run(Manager *m) {
1536 struct epoll_event event;
1540 manager_gc(m, true);
1542 if (manager_dispatch_delayed(m) > 0)
1545 if (manager_recheck_buttons(m) > 0)
1548 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1551 manager_gc(m, true);
1553 if (m->delayed_unit) {
1556 x = now(CLOCK_MONOTONIC);
1557 y = m->delayed_timestamp + m->inhibit_delay_max;
1559 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1562 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1564 if (errno == EINTR || errno == EAGAIN)
1567 log_error("epoll() failed: %m");
1574 switch (event.data.u32) {
1577 manager_dispatch_seat_udev(m);
1581 manager_dispatch_vcsa_udev(m);
1584 case FD_BUTTON_UDEV:
1585 manager_dispatch_button_udev(m);
1589 manager_dispatch_console(m);
1593 bus_loop_dispatch(m->bus_fd);
1597 if (event.data.u32 >= FD_OTHER_BASE)
1598 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1605 static int manager_parse_config_file(Manager *m) {
1612 fn = "/etc/systemd/logind.conf";
1613 f = fopen(fn, "re");
1615 if (errno == ENOENT)
1618 log_warning("Failed to open configuration file %s: %m", fn);
1622 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1624 log_warning("Failed to parse configuration file: %s", strerror(-r));
1631 int main(int argc, char *argv[]) {
1635 log_set_target(LOG_TARGET_AUTO);
1636 log_set_facility(LOG_AUTH);
1637 log_parse_environment();
1643 log_error("This program takes no arguments.");
1654 manager_parse_config_file(m);
1656 r = manager_startup(m);
1658 log_error("Failed to fully start up daemon: %s", strerror(-r));
1662 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1666 "STATUS=Processing requests...");
1670 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1674 "STATUS=Shutting down...");
1679 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;