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_sleep_key = HANDLE_SUSPEND;
60 m->handle_lid_switch = HANDLE_SUSPEND;
61 m->lid_switch_ignore_inhibited = true;
63 m->devices = hashmap_new(string_hash_func, string_compare_func);
64 m->seats = hashmap_new(string_hash_func, string_compare_func);
65 m->sessions = hashmap_new(string_hash_func, string_compare_func);
66 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
67 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
68 m->buttons = hashmap_new(string_hash_func, string_compare_func);
70 m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
71 m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
73 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
74 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
75 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
77 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
78 !m->user_cgroups || !m->session_cgroups ||
79 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
84 m->reset_controllers = strv_new("cpu", NULL);
85 m->kill_exclude_users = strv_new("root", NULL);
86 if (!m->reset_controllers || !m->kill_exclude_users) {
97 if (cg_get_user_path(&m->cgroup_path) < 0) {
105 void manager_free(Manager *m) {
115 while ((session = hashmap_first(m->sessions)))
116 session_free(session);
118 while ((u = hashmap_first(m->users)))
121 while ((d = hashmap_first(m->devices)))
124 while ((s = hashmap_first(m->seats)))
127 while ((i = hashmap_first(m->inhibitors)))
130 while ((b = hashmap_first(m->buttons)))
133 hashmap_free(m->devices);
134 hashmap_free(m->seats);
135 hashmap_free(m->sessions);
136 hashmap_free(m->users);
137 hashmap_free(m->inhibitors);
138 hashmap_free(m->buttons);
140 hashmap_free(m->user_cgroups);
141 hashmap_free(m->session_cgroups);
143 hashmap_free(m->session_fds);
144 hashmap_free(m->inhibitor_fds);
145 hashmap_free(m->button_fds);
147 if (m->console_active_fd >= 0)
148 close_nointr_nofail(m->console_active_fd);
150 if (m->udev_seat_monitor)
151 udev_monitor_unref(m->udev_seat_monitor);
152 if (m->udev_vcsa_monitor)
153 udev_monitor_unref(m->udev_vcsa_monitor);
154 if (m->udev_button_monitor)
155 udev_monitor_unref(m->udev_button_monitor);
161 dbus_connection_flush(m->bus);
162 dbus_connection_close(m->bus);
163 dbus_connection_unref(m->bus);
167 close_nointr_nofail(m->bus_fd);
169 if (m->epoll_fd >= 0)
170 close_nointr_nofail(m->epoll_fd);
172 if (m->reserve_vt_fd >= 0)
173 close_nointr_nofail(m->reserve_vt_fd);
175 strv_free(m->controllers);
176 strv_free(m->reset_controllers);
177 strv_free(m->kill_only_users);
178 strv_free(m->kill_exclude_users);
180 free(m->cgroup_path);
184 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
190 d = hashmap_get(m->devices, sysfs);
198 d = device_new(m, sysfs);
208 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
214 s = hashmap_get(m->seats, id);
232 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
238 s = hashmap_get(m->sessions, id);
246 s = session_new(m, u, id);
256 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
262 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
270 u = user_new(m, uid, gid, name);
280 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
288 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
292 return manager_add_user(m, uid, gid, name, _user);
295 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
303 return errno ? -errno : -ENOENT;
305 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
308 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
314 i = hashmap_get(m->inhibitors, id);
322 i = inhibitor_new(m, id);
332 int manager_add_button(Manager *m, const char *name, Button **_button) {
338 b = hashmap_get(m->buttons, name);
346 b = button_new(m, name);
356 int manager_process_seat_device(Manager *m, struct udev_device *d) {
362 if (streq_ptr(udev_device_get_action(d), "remove")) {
364 device = hashmap_get(m->devices, udev_device_get_syspath(d));
368 seat_add_to_gc_queue(device->seat);
375 sn = udev_device_get_property_value(d, "ID_SEAT");
379 if (!seat_name_is_valid(sn)) {
380 log_warning("Device with invalid seat name %s found, ignoring.", sn);
384 r = manager_add_device(m, udev_device_get_syspath(d), &device);
388 r = manager_add_seat(m, sn, &seat);
396 device_attach(device, seat);
403 int manager_process_button_device(Manager *m, struct udev_device *d) {
410 if (streq_ptr(udev_device_get_action(d), "remove")) {
412 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
421 r = manager_add_button(m, udev_device_get_sysname(d), &b);
425 sn = udev_device_get_property_value(d, "ID_SEAT");
429 button_set_seat(b, sn);
436 int manager_enumerate_devices(Manager *m) {
437 struct udev_list_entry *item = NULL, *first = NULL;
438 struct udev_enumerate *e;
443 /* Loads devices from udev and creates seats for them as
446 e = udev_enumerate_new(m->udev);
452 r = udev_enumerate_add_match_subsystem(e, "graphics");
456 r = udev_enumerate_add_match_tag(e, "seat");
460 r = udev_enumerate_scan_devices(e);
464 first = udev_enumerate_get_list_entry(e);
465 udev_list_entry_foreach(item, first) {
466 struct udev_device *d;
469 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
475 k = manager_process_seat_device(m, d);
476 udev_device_unref(d);
484 udev_enumerate_unref(e);
489 int manager_enumerate_buttons(Manager *m) {
490 struct udev_list_entry *item = NULL, *first = NULL;
491 struct udev_enumerate *e;
496 /* Loads buttons from udev */
498 if (m->handle_power_key == HANDLE_IGNORE &&
499 m->handle_sleep_key == HANDLE_IGNORE &&
500 m->handle_lid_switch == HANDLE_IGNORE)
503 e = udev_enumerate_new(m->udev);
509 r = udev_enumerate_add_match_subsystem(e, "input");
513 r = udev_enumerate_add_match_tag(e, "power-switch");
517 r = udev_enumerate_scan_devices(e);
521 first = udev_enumerate_get_list_entry(e);
522 udev_list_entry_foreach(item, first) {
523 struct udev_device *d;
526 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
532 k = manager_process_button_device(m, d);
533 udev_device_unref(d);
541 udev_enumerate_unref(e);
546 int manager_enumerate_seats(Manager *m) {
553 /* This loads data about seats stored on disk, but does not
554 * actually create any seats. Removes data of seats that no
557 d = opendir("/run/systemd/seats");
562 log_error("Failed to open /run/systemd/seats: %m");
566 while ((de = readdir(d))) {
570 if (!dirent_is_file(de))
573 s = hashmap_get(m->seats, de->d_name);
575 unlinkat(dirfd(d), de->d_name, 0);
589 static int manager_enumerate_users_from_cgroup(Manager *m) {
594 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
599 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
603 while ((k = cg_read_subgroup(d, &name)) > 0) {
606 k = manager_add_user_by_name(m, name, &user);
613 user_add_to_gc_queue(user);
615 if (!user->cgroup_path)
616 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
633 static int manager_enumerate_linger_users(Manager *m) {
638 d = opendir("/var/lib/systemd/linger");
643 log_error("Failed to open /var/lib/systemd/linger/: %m");
647 while ((de = readdir(d))) {
650 if (!dirent_is_file(de))
653 k = manager_add_user_by_name(m, de->d_name, NULL);
655 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
665 int manager_enumerate_users(Manager *m) {
672 /* First, enumerate user cgroups */
673 r = manager_enumerate_users_from_cgroup(m);
675 /* Second, add lingering users on top */
676 k = manager_enumerate_linger_users(m);
680 /* Third, read in user data stored on disk */
681 d = opendir("/run/systemd/users");
686 log_error("Failed to open /run/systemd/users: %m");
690 while ((de = readdir(d))) {
694 if (!dirent_is_file(de))
697 k = parse_uid(de->d_name, &uid);
699 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
703 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
705 unlinkat(dirfd(d), de->d_name, 0);
719 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
724 HASHMAP_FOREACH(u, m->users, i) {
732 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
737 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
742 while ((k = cg_read_subgroup(d, &name)) > 0) {
745 if (streq(name, "shared"))
748 k = manager_add_session(m, u, name, &session);
754 session_add_to_gc_queue(session);
756 if (!session->cgroup_path)
757 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
775 int manager_enumerate_sessions(Manager *m) {
782 /* First enumerate session cgroups */
783 r = manager_enumerate_sessions_from_cgroup(m);
785 /* Second, read in session data stored on disk */
786 d = opendir("/run/systemd/sessions");
791 log_error("Failed to open /run/systemd/sessions: %m");
795 while ((de = readdir(d))) {
799 if (!dirent_is_file(de))
802 s = hashmap_get(m->sessions, de->d_name);
804 unlinkat(dirfd(d), de->d_name, 0);
818 int manager_enumerate_inhibitors(Manager *m) {
825 d = opendir("/run/systemd/inhibit");
830 log_error("Failed to open /run/systemd/inhibit: %m");
834 while ((de = readdir(d))) {
838 if (!dirent_is_file(de))
841 k = manager_add_inhibitor(m, de->d_name, &i);
843 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
848 k = inhibitor_load(i);
858 int manager_dispatch_seat_udev(Manager *m) {
859 struct udev_device *d;
864 d = udev_monitor_receive_device(m->udev_seat_monitor);
868 r = manager_process_seat_device(m, d);
869 udev_device_unref(d);
874 int manager_dispatch_vcsa_udev(Manager *m) {
875 struct udev_device *d;
881 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
885 name = udev_device_get_sysname(d);
887 /* Whenever a VCSA device is removed try to reallocate our
888 * VTs, to make sure our auto VTs never go away. */
890 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
891 r = seat_preallocate_vts(m->vtconsole);
893 udev_device_unref(d);
898 int manager_dispatch_button_udev(Manager *m) {
899 struct udev_device *d;
904 d = udev_monitor_receive_device(m->udev_button_monitor);
908 r = manager_process_button_device(m, d);
909 udev_device_unref(d);
914 int manager_dispatch_console(Manager *m) {
918 seat_read_active_vt(m->vtconsole);
923 static int vt_is_busy(int vtnr) {
924 struct vt_stat vt_stat;
929 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
930 * we'd open the latter we'd open the foreground tty which
931 * hence would be unconditionally busy. By opening /dev/tty1
932 * we avoid this. Since tty1 is special and needs to be an
933 * explicitly loaded getty or DM this is safe. */
935 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
939 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
942 r = !!(vt_stat.v_state & (1 << vtnr));
944 close_nointr_nofail(fd);
949 int manager_spawn_autovt(Manager *m, int vtnr) {
952 const char *mode = "fail";
957 if ((unsigned) vtnr > m->n_autovts &&
958 (unsigned) vtnr != m->reserve_vt)
961 if ((unsigned) vtnr != m->reserve_vt) {
962 /* If this is the reserved TTY, we'll start the getty
963 * on it in any case, but otherwise only if it is not
966 r = vt_is_busy(vtnr);
973 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
974 log_error("Could not allocate service name.");
979 r = bus_method_call_with_reply (
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &name,
988 DBUS_TYPE_STRING, &mode,
997 static int manager_reserve_vt(Manager *m) {
998 _cleanup_free_ char *p = NULL;
1002 if (m->reserve_vt <= 0)
1005 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1008 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1009 if (m->reserve_vt_fd < 0) {
1011 /* Don't complain on VT-less systems */
1012 if (errno != ENOENT)
1013 log_warning("Failed to pin reserved VT: %m");
1020 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1028 s = hashmap_get(m->session_cgroups, cgroup);
1041 e = strrchr(p, '/');
1050 s = hashmap_get(m->session_cgroups, p);
1059 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1067 u = hashmap_get(m->user_cgroups, cgroup);
1080 e = strrchr(p, '/');
1089 u = hashmap_get(m->user_cgroups, p);
1098 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1106 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1110 r = manager_get_session_by_cgroup(m, p, session);
1116 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1121 r = manager_get_session_by_cgroup(m, cgroup, &s);
1123 session_add_to_gc_queue(s);
1125 r = manager_get_user_by_cgroup(m, cgroup, &u);
1127 user_add_to_gc_queue(u);
1130 static void manager_dispatch_other(Manager *m, int fd) {
1138 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1140 assert(s->fifo_fd == fd);
1141 session_remove_fifo(s);
1146 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1148 assert(i->fifo_fd == fd);
1154 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1156 assert(b->fd == fd);
1161 assert_not_reached("Got event for unknown fd");
1164 static int manager_connect_bus(Manager *m) {
1167 struct epoll_event ev;
1171 assert(m->bus_fd < 0);
1173 dbus_error_init(&error);
1175 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1177 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1182 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1183 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1184 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1185 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1186 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1191 dbus_bus_add_match(m->bus,
1193 "interface='org.freedesktop.systemd1.Agent',"
1194 "member='Released',"
1195 "path='/org/freedesktop/systemd1/agent'",
1198 if (dbus_error_is_set(&error)) {
1199 log_error("Failed to register match: %s", bus_error_message(&error));
1204 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1205 if (dbus_error_is_set(&error)) {
1206 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1211 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1212 log_error("Failed to acquire name.");
1217 m->bus_fd = bus_loop_open(m->bus);
1218 if (m->bus_fd < 0) {
1224 ev.events = EPOLLIN;
1225 ev.data.u32 = FD_BUS;
1227 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1233 dbus_error_free(&error);
1238 static int manager_connect_console(Manager *m) {
1239 struct epoll_event ev;
1242 assert(m->console_active_fd < 0);
1244 /* On certain architectures (S390 and Xen, and containers),
1245 /dev/tty0 does not exist, so don't fail if we can't open
1247 if (access("/dev/tty0", F_OK) < 0) {
1248 m->console_active_fd = -1;
1252 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1253 if (m->console_active_fd < 0) {
1255 /* On some systems the device node /dev/tty0 may exist
1256 * even though /sys/class/tty/tty0 does not. */
1257 if (errno == ENOENT)
1260 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1266 ev.data.u32 = FD_CONSOLE;
1268 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1274 static int manager_connect_udev(Manager *m) {
1275 struct epoll_event ev;
1279 assert(!m->udev_seat_monitor);
1280 assert(!m->udev_vcsa_monitor);
1281 assert(!m->udev_button_monitor);
1283 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1284 if (!m->udev_seat_monitor)
1287 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1291 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1295 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1299 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1302 ev.events = EPOLLIN;
1303 ev.data.u32 = FD_SEAT_UDEV;
1304 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1307 /* Don't watch keys if nobody cares */
1308 if (m->handle_power_key != HANDLE_IGNORE ||
1309 m->handle_sleep_key != HANDLE_IGNORE ||
1310 m->handle_lid_switch != HANDLE_IGNORE) {
1312 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1313 if (!m->udev_button_monitor)
1316 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1320 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1324 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1328 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1331 ev.events = EPOLLIN;
1332 ev.data.u32 = FD_BUTTON_UDEV;
1333 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1337 /* Don't bother watching VCSA devices, if nobody cares */
1338 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1340 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1341 if (!m->udev_vcsa_monitor)
1344 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1348 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1352 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1355 ev.events = EPOLLIN;
1356 ev.data.u32 = FD_VCSA_UDEV;
1357 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1364 void manager_gc(Manager *m, bool drop_not_started) {
1371 while ((seat = m->seat_gc_queue)) {
1372 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1373 seat->in_gc_queue = false;
1375 if (seat_check_gc(seat, drop_not_started) == 0) {
1381 while ((session = m->session_gc_queue)) {
1382 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1383 session->in_gc_queue = false;
1385 if (session_check_gc(session, drop_not_started) == 0) {
1386 session_stop(session);
1387 session_free(session);
1391 while ((user = m->user_gc_queue)) {
1392 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1393 user->in_gc_queue = false;
1395 if (user_check_gc(user, drop_not_started) == 0) {
1402 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1405 dual_timestamp ts = { 0, 0 };
1410 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false);
1412 HASHMAP_FOREACH(s, m->sessions, i) {
1416 ih = session_get_idle_hint(s, &k);
1422 if (k.monotonic < ts.monotonic)
1428 } else if (idle_hint) {
1430 if (k.monotonic > ts.monotonic)
1441 int manager_startup(Manager *m) {
1446 Inhibitor *inhibitor;
1450 assert(m->epoll_fd <= 0);
1452 cg_shorten_controllers(m->reset_controllers);
1453 cg_shorten_controllers(m->controllers);
1455 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1456 if (m->epoll_fd < 0)
1459 /* Connect to console */
1460 r = manager_connect_console(m);
1464 /* Connect to udev */
1465 r = manager_connect_udev(m);
1469 /* Connect to the bus */
1470 r = manager_connect_bus(m);
1474 /* Instantiate magic seat 0 */
1475 r = manager_add_seat(m, "seat0", &m->vtconsole);
1479 /* Deserialize state */
1480 manager_enumerate_devices(m);
1481 manager_enumerate_seats(m);
1482 manager_enumerate_users(m);
1483 manager_enumerate_sessions(m);
1484 manager_enumerate_inhibitors(m);
1485 manager_enumerate_buttons(m);
1487 /* Remove stale objects before we start them */
1488 manager_gc(m, false);
1490 /* Reserve the special reserved VT */
1491 manager_reserve_vt(m);
1493 /* And start everything */
1494 HASHMAP_FOREACH(seat, m->seats, i)
1497 HASHMAP_FOREACH(user, m->users, i)
1500 HASHMAP_FOREACH(session, m->sessions, i)
1501 session_start(session);
1503 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1504 inhibitor_start(inhibitor);
1509 int manager_run(Manager *m) {
1513 struct epoll_event event;
1517 manager_gc(m, true);
1519 if (manager_dispatch_delayed(m) > 0)
1522 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1525 manager_gc(m, true);
1527 if (m->delayed_unit) {
1530 x = now(CLOCK_MONOTONIC);
1531 y = m->delayed_timestamp + m->inhibit_delay_max;
1533 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1536 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1538 if (errno == EINTR || errno == EAGAIN)
1541 log_error("epoll() failed: %m");
1548 switch (event.data.u32) {
1551 manager_dispatch_seat_udev(m);
1555 manager_dispatch_vcsa_udev(m);
1558 case FD_BUTTON_UDEV:
1559 manager_dispatch_button_udev(m);
1563 manager_dispatch_console(m);
1567 bus_loop_dispatch(m->bus_fd);
1571 if (event.data.u32 >= FD_OTHER_BASE)
1572 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1579 static int manager_parse_config_file(Manager *m) {
1586 fn = "/etc/systemd/logind.conf";
1587 f = fopen(fn, "re");
1589 if (errno == ENOENT)
1592 log_warning("Failed to open configuration file %s: %m", fn);
1596 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1598 log_warning("Failed to parse configuration file: %s", strerror(-r));
1605 int main(int argc, char *argv[]) {
1609 log_set_target(LOG_TARGET_AUTO);
1610 log_set_facility(LOG_AUTH);
1611 log_parse_environment();
1617 log_error("This program takes no arguments.");
1628 manager_parse_config_file(m);
1630 r = manager_startup(m);
1632 log_error("Failed to fully start up daemon: %s", strerror(-r));
1636 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1640 "STATUS=Processing requests...");
1644 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1648 "STATUS=Shutting down...");
1653 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;