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;
55 m->inhibit_delay_max = 5 * USEC_PER_SEC;
56 m->handle_power_key = HANDLE_NO_SESSION;
57 m->handle_sleep_key = HANDLE_TTY_SESSION;
58 m->handle_lid_switch = HANDLE_OFF;
60 m->devices = hashmap_new(string_hash_func, string_compare_func);
61 m->seats = hashmap_new(string_hash_func, string_compare_func);
62 m->sessions = hashmap_new(string_hash_func, string_compare_func);
63 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
64 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
65 m->buttons = hashmap_new(string_hash_func, string_compare_func);
67 m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
68 m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
70 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
71 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
72 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
74 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
75 !m->user_cgroups || !m->session_cgroups ||
76 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
81 m->reset_controllers = strv_new("cpu", NULL);
82 m->kill_exclude_users = strv_new("root", NULL);
83 if (!m->reset_controllers || !m->kill_exclude_users) {
94 if (cg_get_user_path(&m->cgroup_path) < 0) {
102 void manager_free(Manager *m) {
112 while ((session = hashmap_first(m->sessions)))
113 session_free(session);
115 while ((u = hashmap_first(m->users)))
118 while ((d = hashmap_first(m->devices)))
121 while ((s = hashmap_first(m->seats)))
124 while ((i = hashmap_first(m->inhibitors)))
127 while ((b = hashmap_first(m->buttons)))
130 hashmap_free(m->devices);
131 hashmap_free(m->seats);
132 hashmap_free(m->sessions);
133 hashmap_free(m->users);
134 hashmap_free(m->inhibitors);
135 hashmap_free(m->buttons);
137 hashmap_free(m->user_cgroups);
138 hashmap_free(m->session_cgroups);
140 hashmap_free(m->session_fds);
141 hashmap_free(m->inhibitor_fds);
142 hashmap_free(m->button_fds);
144 if (m->console_active_fd >= 0)
145 close_nointr_nofail(m->console_active_fd);
147 if (m->udev_seat_monitor)
148 udev_monitor_unref(m->udev_seat_monitor);
149 if (m->udev_vcsa_monitor)
150 udev_monitor_unref(m->udev_vcsa_monitor);
151 if (m->udev_button_monitor)
152 udev_monitor_unref(m->udev_button_monitor);
158 dbus_connection_flush(m->bus);
159 dbus_connection_close(m->bus);
160 dbus_connection_unref(m->bus);
164 close_nointr_nofail(m->bus_fd);
166 if (m->epoll_fd >= 0)
167 close_nointr_nofail(m->epoll_fd);
169 strv_free(m->controllers);
170 strv_free(m->reset_controllers);
171 strv_free(m->kill_only_users);
172 strv_free(m->kill_exclude_users);
174 free(m->cgroup_path);
178 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
184 d = hashmap_get(m->devices, sysfs);
192 d = device_new(m, sysfs);
202 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
208 s = hashmap_get(m->seats, id);
226 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
232 s = hashmap_get(m->sessions, id);
240 s = session_new(m, u, id);
250 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
256 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
264 u = user_new(m, uid, gid, name);
274 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
282 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
286 return manager_add_user(m, uid, gid, name, _user);
289 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
297 return errno ? -errno : -ENOENT;
299 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
302 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
308 i = hashmap_get(m->inhibitors, id);
316 i = inhibitor_new(m, id);
326 int manager_add_button(Manager *m, const char *name, Button **_button) {
332 b = hashmap_get(m->buttons, name);
340 b = button_new(m, name);
350 int manager_process_seat_device(Manager *m, struct udev_device *d) {
356 if (streq_ptr(udev_device_get_action(d), "remove")) {
358 device = hashmap_get(m->devices, udev_device_get_syspath(d));
362 seat_add_to_gc_queue(device->seat);
369 sn = udev_device_get_property_value(d, "ID_SEAT");
373 if (!seat_name_is_valid(sn)) {
374 log_warning("Device with invalid seat name %s found, ignoring.", sn);
378 r = manager_add_device(m, udev_device_get_syspath(d), &device);
382 r = manager_add_seat(m, sn, &seat);
390 device_attach(device, seat);
397 int manager_process_button_device(Manager *m, struct udev_device *d) {
404 if (streq_ptr(udev_device_get_action(d), "remove")) {
406 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
415 r = manager_add_button(m, udev_device_get_sysname(d), &b);
419 sn = udev_device_get_property_value(d, "ID_SEAT");
423 button_set_seat(b, sn);
430 int manager_enumerate_devices(Manager *m) {
431 struct udev_list_entry *item = NULL, *first = NULL;
432 struct udev_enumerate *e;
437 /* Loads devices from udev and creates seats for them as
440 e = udev_enumerate_new(m->udev);
446 r = udev_enumerate_add_match_subsystem(e, "graphics");
450 r = udev_enumerate_add_match_tag(e, "seat");
454 r = udev_enumerate_scan_devices(e);
458 first = udev_enumerate_get_list_entry(e);
459 udev_list_entry_foreach(item, first) {
460 struct udev_device *d;
463 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
469 k = manager_process_seat_device(m, d);
470 udev_device_unref(d);
478 udev_enumerate_unref(e);
483 int manager_enumerate_buttons(Manager *m) {
484 struct udev_list_entry *item = NULL, *first = NULL;
485 struct udev_enumerate *e;
490 /* Loads buttons from udev */
492 if (m->handle_power_key == HANDLE_OFF &&
493 m->handle_sleep_key == HANDLE_OFF &&
494 m->handle_lid_switch == HANDLE_OFF)
497 e = udev_enumerate_new(m->udev);
503 r = udev_enumerate_add_match_subsystem(e, "input");
507 r = udev_enumerate_add_match_tag(e, "power-switch");
511 r = udev_enumerate_scan_devices(e);
515 first = udev_enumerate_get_list_entry(e);
516 udev_list_entry_foreach(item, first) {
517 struct udev_device *d;
520 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
526 k = manager_process_button_device(m, d);
527 udev_device_unref(d);
535 udev_enumerate_unref(e);
540 int manager_enumerate_seats(Manager *m) {
547 /* This loads data about seats stored on disk, but does not
548 * actually create any seats. Removes data of seats that no
551 d = opendir("/run/systemd/seats");
556 log_error("Failed to open /run/systemd/seats: %m");
560 while ((de = readdir(d))) {
564 if (!dirent_is_file(de))
567 s = hashmap_get(m->seats, de->d_name);
569 unlinkat(dirfd(d), de->d_name, 0);
583 static int manager_enumerate_users_from_cgroup(Manager *m) {
588 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
593 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
597 while ((k = cg_read_subgroup(d, &name)) > 0) {
600 k = manager_add_user_by_name(m, name, &user);
607 user_add_to_gc_queue(user);
609 if (!user->cgroup_path)
610 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
627 static int manager_enumerate_linger_users(Manager *m) {
632 d = opendir("/var/lib/systemd/linger");
637 log_error("Failed to open /var/lib/systemd/linger/: %m");
641 while ((de = readdir(d))) {
644 if (!dirent_is_file(de))
647 k = manager_add_user_by_name(m, de->d_name, NULL);
649 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
659 int manager_enumerate_users(Manager *m) {
666 /* First, enumerate user cgroups */
667 r = manager_enumerate_users_from_cgroup(m);
669 /* Second, add lingering users on top */
670 k = manager_enumerate_linger_users(m);
674 /* Third, read in user data stored on disk */
675 d = opendir("/run/systemd/users");
680 log_error("Failed to open /run/systemd/users: %m");
684 while ((de = readdir(d))) {
688 if (!dirent_is_file(de))
691 k = parse_uid(de->d_name, &uid);
693 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
697 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
699 unlinkat(dirfd(d), de->d_name, 0);
713 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
718 HASHMAP_FOREACH(u, m->users, i) {
726 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
731 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
736 while ((k = cg_read_subgroup(d, &name)) > 0) {
739 if (streq(name, "shared"))
742 k = manager_add_session(m, u, name, &session);
748 session_add_to_gc_queue(session);
750 if (!session->cgroup_path)
751 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
769 int manager_enumerate_sessions(Manager *m) {
776 /* First enumerate session cgroups */
777 r = manager_enumerate_sessions_from_cgroup(m);
779 /* Second, read in session data stored on disk */
780 d = opendir("/run/systemd/sessions");
785 log_error("Failed to open /run/systemd/sessions: %m");
789 while ((de = readdir(d))) {
793 if (!dirent_is_file(de))
796 s = hashmap_get(m->sessions, de->d_name);
798 unlinkat(dirfd(d), de->d_name, 0);
812 int manager_enumerate_inhibitors(Manager *m) {
819 d = opendir("/run/systemd/inhibit");
824 log_error("Failed to open /run/systemd/inhibit: %m");
828 while ((de = readdir(d))) {
832 if (!dirent_is_file(de))
835 k = manager_add_inhibitor(m, de->d_name, &i);
837 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
842 k = inhibitor_load(i);
852 int manager_dispatch_seat_udev(Manager *m) {
853 struct udev_device *d;
858 d = udev_monitor_receive_device(m->udev_seat_monitor);
862 r = manager_process_seat_device(m, d);
863 udev_device_unref(d);
868 int manager_dispatch_vcsa_udev(Manager *m) {
869 struct udev_device *d;
875 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
879 name = udev_device_get_sysname(d);
881 /* Whenever a VCSA device is removed try to reallocate our
882 * VTs, to make sure our auto VTs never go away. */
884 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
885 r = seat_preallocate_vts(m->vtconsole);
887 udev_device_unref(d);
892 int manager_dispatch_button_udev(Manager *m) {
893 struct udev_device *d;
898 d = udev_monitor_receive_device(m->udev_button_monitor);
902 r = manager_process_button_device(m, d);
903 udev_device_unref(d);
908 int manager_dispatch_console(Manager *m) {
912 seat_read_active_vt(m->vtconsole);
917 static int vt_is_busy(int vtnr) {
918 struct vt_stat vt_stat;
923 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
924 * we'd open the latter we'd open the foreground tty which
925 * hence would be unconditionally busy. By opening /dev/tty1
926 * we avoid this. Since tty1 is special and needs to be an
927 * explicitly loaded getty or DM this is safe. */
929 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
933 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
936 r = !!(vt_stat.v_state & (1 << vtnr));
938 close_nointr_nofail(fd);
943 int manager_spawn_autovt(Manager *m, int vtnr) {
946 const char *mode = "fail";
951 if ((unsigned) vtnr > m->n_autovts)
954 r = vt_is_busy(vtnr);
960 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
961 log_error("Could not allocate service name.");
965 r = bus_method_call_with_reply (
967 "org.freedesktop.systemd1",
968 "/org/freedesktop/systemd1",
969 "org.freedesktop.systemd1.Manager",
973 DBUS_TYPE_STRING, &name,
974 DBUS_TYPE_STRING, &mode,
983 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
991 s = hashmap_get(m->session_cgroups, cgroup);
1004 e = strrchr(p, '/');
1013 s = hashmap_get(m->session_cgroups, p);
1022 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1030 u = hashmap_get(m->user_cgroups, cgroup);
1043 e = strrchr(p, '/');
1052 u = hashmap_get(m->user_cgroups, p);
1061 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1069 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1073 r = manager_get_session_by_cgroup(m, p, session);
1079 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1084 r = manager_get_session_by_cgroup(m, cgroup, &s);
1086 session_add_to_gc_queue(s);
1088 r = manager_get_user_by_cgroup(m, cgroup, &u);
1090 user_add_to_gc_queue(u);
1093 static void manager_dispatch_other(Manager *m, int fd) {
1101 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1103 assert(s->fifo_fd == fd);
1104 session_remove_fifo(s);
1109 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1111 assert(i->fifo_fd == fd);
1117 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1119 assert(b->fd == fd);
1124 assert_not_reached("Got event for unknown fd");
1127 static int manager_connect_bus(Manager *m) {
1130 struct epoll_event ev;
1134 assert(m->bus_fd < 0);
1136 dbus_error_init(&error);
1138 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1140 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1145 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1146 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1147 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1148 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1149 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1154 dbus_bus_add_match(m->bus,
1156 "interface='org.freedesktop.systemd1.Agent',"
1157 "member='Released',"
1158 "path='/org/freedesktop/systemd1/agent'",
1161 if (dbus_error_is_set(&error)) {
1162 log_error("Failed to register match: %s", bus_error_message(&error));
1167 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1168 if (dbus_error_is_set(&error)) {
1169 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1174 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1175 log_error("Failed to acquire name.");
1180 m->bus_fd = bus_loop_open(m->bus);
1181 if (m->bus_fd < 0) {
1187 ev.events = EPOLLIN;
1188 ev.data.u32 = FD_BUS;
1190 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1196 dbus_error_free(&error);
1201 static int manager_connect_console(Manager *m) {
1202 struct epoll_event ev;
1205 assert(m->console_active_fd < 0);
1207 /* On certain architectures (S390 and Xen, and containers),
1208 /dev/tty0 does not exist, so don't fail if we can't open
1210 if (access("/dev/tty0", F_OK) < 0) {
1211 m->console_active_fd = -1;
1215 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1216 if (m->console_active_fd < 0) {
1218 /* On some systems the device node /dev/tty0 may exist
1219 * even though /sys/class/tty/tty0 does not. */
1220 if (errno == ENOENT)
1223 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1229 ev.data.u32 = FD_CONSOLE;
1231 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1237 static int manager_connect_udev(Manager *m) {
1238 struct epoll_event ev;
1242 assert(!m->udev_seat_monitor);
1243 assert(!m->udev_vcsa_monitor);
1244 assert(!m->udev_button_monitor);
1246 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1247 if (!m->udev_seat_monitor)
1250 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1254 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1258 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1262 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1265 ev.events = EPOLLIN;
1266 ev.data.u32 = FD_SEAT_UDEV;
1267 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1270 /* Don't watch keys if nobody cares */
1271 if (m->handle_power_key != HANDLE_OFF ||
1272 m->handle_sleep_key != HANDLE_OFF ||
1273 m->handle_lid_switch != HANDLE_OFF) {
1275 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1276 if (!m->udev_button_monitor)
1279 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1283 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1287 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1291 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1294 ev.events = EPOLLIN;
1295 ev.data.u32 = FD_BUTTON_UDEV;
1296 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1300 /* Don't bother watching VCSA devices, if nobody cares */
1301 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1303 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1304 if (!m->udev_vcsa_monitor)
1307 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1311 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1315 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1318 ev.events = EPOLLIN;
1319 ev.data.u32 = FD_VCSA_UDEV;
1320 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1327 void manager_gc(Manager *m, bool drop_not_started) {
1334 while ((seat = m->seat_gc_queue)) {
1335 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1336 seat->in_gc_queue = false;
1338 if (seat_check_gc(seat, drop_not_started) == 0) {
1344 while ((session = m->session_gc_queue)) {
1345 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1346 session->in_gc_queue = false;
1348 if (session_check_gc(session, drop_not_started) == 0) {
1349 session_stop(session);
1350 session_free(session);
1354 while ((user = m->user_gc_queue)) {
1355 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1356 user->in_gc_queue = false;
1358 if (user_check_gc(user, drop_not_started) == 0) {
1365 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1368 dual_timestamp ts = { 0, 0 };
1373 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1375 HASHMAP_FOREACH(s, m->sessions, i) {
1379 ih = session_get_idle_hint(s, &k);
1385 if (k.monotonic < ts.monotonic)
1391 } else if (idle_hint) {
1393 if (k.monotonic > ts.monotonic)
1404 int manager_startup(Manager *m) {
1409 Inhibitor *inhibitor;
1413 assert(m->epoll_fd <= 0);
1415 cg_shorten_controllers(m->reset_controllers);
1416 cg_shorten_controllers(m->controllers);
1418 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1419 if (m->epoll_fd < 0)
1422 /* Connect to console */
1423 r = manager_connect_console(m);
1427 /* Connect to udev */
1428 r = manager_connect_udev(m);
1432 /* Connect to the bus */
1433 r = manager_connect_bus(m);
1437 /* Instantiate magic seat 0 */
1438 r = manager_add_seat(m, "seat0", &m->vtconsole);
1442 /* Deserialize state */
1443 manager_enumerate_devices(m);
1444 manager_enumerate_seats(m);
1445 manager_enumerate_users(m);
1446 manager_enumerate_sessions(m);
1447 manager_enumerate_inhibitors(m);
1448 manager_enumerate_buttons(m);
1450 /* Remove stale objects before we start them */
1451 manager_gc(m, false);
1453 /* And start everything */
1454 HASHMAP_FOREACH(seat, m->seats, i)
1457 HASHMAP_FOREACH(user, m->users, i)
1460 HASHMAP_FOREACH(session, m->sessions, i)
1461 session_start(session);
1463 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1464 inhibitor_start(inhibitor);
1469 int manager_run(Manager *m) {
1473 struct epoll_event event;
1477 manager_gc(m, true);
1479 if (manager_dispatch_delayed(m) > 0)
1482 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1485 manager_gc(m, true);
1487 if (m->delayed_unit) {
1490 x = now(CLOCK_MONOTONIC);
1491 y = m->delayed_timestamp + m->inhibit_delay_max;
1493 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1496 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1498 if (errno == EINTR || errno == EAGAIN)
1501 log_error("epoll() failed: %m");
1508 switch (event.data.u32) {
1511 manager_dispatch_seat_udev(m);
1515 manager_dispatch_vcsa_udev(m);
1518 case FD_BUTTON_UDEV:
1519 manager_dispatch_button_udev(m);
1523 manager_dispatch_console(m);
1527 bus_loop_dispatch(m->bus_fd);
1531 if (event.data.u32 >= FD_OTHER_BASE)
1532 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1539 static int manager_parse_config_file(Manager *m) {
1546 fn = "/etc/systemd/logind.conf";
1547 f = fopen(fn, "re");
1549 if (errno == ENOENT)
1552 log_warning("Failed to open configuration file %s: %m", fn);
1556 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1558 log_warning("Failed to parse configuration file: %s", strerror(-r));
1565 int main(int argc, char *argv[]) {
1569 log_set_target(LOG_TARGET_AUTO);
1570 log_set_facility(LOG_AUTH);
1571 log_parse_environment();
1577 log_error("This program takes no arguments.");
1588 manager_parse_config_file(m);
1590 r = manager_startup(m);
1592 log_error("Failed to fully start up daemon: %s", strerror(-r));
1596 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1600 "STATUS=Processing requests...");
1604 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1608 "STATUS=Shutting down...");
1613 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;