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_YES;
57 m->handle_sleep_key = HANDLE_YES;
58 m->handle_lid_switch = HANDLE_NO;
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->cgroups = hashmap_new(string_hash_func, string_compare_func);
68 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
69 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
70 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
72 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
73 !m->cgroups || !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
78 m->reset_controllers = strv_new("cpu", NULL);
79 m->kill_exclude_users = strv_new("root", NULL);
80 if (!m->reset_controllers || !m->kill_exclude_users) {
91 if (cg_get_user_path(&m->cgroup_path) < 0) {
99 void manager_free(Manager *m) {
109 while ((session = hashmap_first(m->sessions)))
110 session_free(session);
112 while ((u = hashmap_first(m->users)))
115 while ((d = hashmap_first(m->devices)))
118 while ((s = hashmap_first(m->seats)))
121 while ((i = hashmap_first(m->inhibitors)))
124 while ((b = hashmap_first(m->buttons)))
127 hashmap_free(m->devices);
128 hashmap_free(m->seats);
129 hashmap_free(m->sessions);
130 hashmap_free(m->users);
131 hashmap_free(m->inhibitors);
132 hashmap_free(m->buttons);
134 hashmap_free(m->cgroups);
135 hashmap_free(m->session_fds);
136 hashmap_free(m->inhibitor_fds);
137 hashmap_free(m->button_fds);
139 if (m->console_active_fd >= 0)
140 close_nointr_nofail(m->console_active_fd);
142 if (m->udev_seat_monitor)
143 udev_monitor_unref(m->udev_seat_monitor);
144 if (m->udev_vcsa_monitor)
145 udev_monitor_unref(m->udev_vcsa_monitor);
146 if (m->udev_button_monitor)
147 udev_monitor_unref(m->udev_button_monitor);
153 dbus_connection_flush(m->bus);
154 dbus_connection_close(m->bus);
155 dbus_connection_unref(m->bus);
159 close_nointr_nofail(m->bus_fd);
161 if (m->epoll_fd >= 0)
162 close_nointr_nofail(m->epoll_fd);
164 strv_free(m->controllers);
165 strv_free(m->reset_controllers);
166 strv_free(m->kill_only_users);
167 strv_free(m->kill_exclude_users);
169 free(m->cgroup_path);
173 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
179 d = hashmap_get(m->devices, sysfs);
187 d = device_new(m, sysfs);
197 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
203 s = hashmap_get(m->seats, id);
221 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
227 s = hashmap_get(m->sessions, id);
235 s = session_new(m, u, id);
245 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
251 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
259 u = user_new(m, uid, gid, name);
269 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
277 r = get_user_creds(&name, &uid, &gid, NULL);
281 return manager_add_user(m, uid, gid, name, _user);
284 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
292 return errno ? -errno : -ENOENT;
294 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
297 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
303 i = hashmap_get(m->inhibitors, id);
311 i = inhibitor_new(m, id);
321 int manager_add_button(Manager *m, const char *name, Button **_button) {
327 b = hashmap_get(m->buttons, name);
335 b = button_new(m, name);
345 int manager_process_seat_device(Manager *m, struct udev_device *d) {
351 if (streq_ptr(udev_device_get_action(d), "remove")) {
353 device = hashmap_get(m->devices, udev_device_get_syspath(d));
357 seat_add_to_gc_queue(device->seat);
364 sn = udev_device_get_property_value(d, "ID_SEAT");
368 if (!seat_name_is_valid(sn)) {
369 log_warning("Device with invalid seat name %s found, ignoring.", sn);
373 r = manager_add_device(m, udev_device_get_syspath(d), &device);
377 r = manager_add_seat(m, sn, &seat);
385 device_attach(device, seat);
392 int manager_process_button_device(Manager *m, struct udev_device *d) {
399 if (streq_ptr(udev_device_get_action(d), "remove")) {
401 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
410 r = manager_add_button(m, udev_device_get_sysname(d), &b);
414 sn = udev_device_get_property_value(d, "ID_SEAT");
418 button_set_seat(b, sn);
425 int manager_enumerate_devices(Manager *m) {
426 struct udev_list_entry *item = NULL, *first = NULL;
427 struct udev_enumerate *e;
432 /* Loads devices from udev and creates seats for them as
435 e = udev_enumerate_new(m->udev);
441 r = udev_enumerate_add_match_subsystem(e, "graphics");
445 r = udev_enumerate_add_match_tag(e, "seat");
449 r = udev_enumerate_scan_devices(e);
453 first = udev_enumerate_get_list_entry(e);
454 udev_list_entry_foreach(item, first) {
455 struct udev_device *d;
458 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
464 k = manager_process_seat_device(m, d);
465 udev_device_unref(d);
473 udev_enumerate_unref(e);
478 int manager_enumerate_buttons(Manager *m) {
479 struct udev_list_entry *item = NULL, *first = NULL;
480 struct udev_enumerate *e;
485 /* Loads buttons from udev */
487 e = udev_enumerate_new(m->udev);
493 r = udev_enumerate_add_match_subsystem(e, "input");
497 r = udev_enumerate_add_match_tag(e, "power-switch");
501 r = udev_enumerate_scan_devices(e);
505 first = udev_enumerate_get_list_entry(e);
506 udev_list_entry_foreach(item, first) {
507 struct udev_device *d;
510 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
516 k = manager_process_button_device(m, d);
517 udev_device_unref(d);
525 udev_enumerate_unref(e);
530 int manager_enumerate_seats(Manager *m) {
537 /* This loads data about seats stored on disk, but does not
538 * actually create any seats. Removes data of seats that no
541 d = opendir("/run/systemd/seats");
546 log_error("Failed to open /run/systemd/seats: %m");
550 while ((de = readdir(d))) {
554 if (!dirent_is_file(de))
557 s = hashmap_get(m->seats, de->d_name);
559 unlinkat(dirfd(d), de->d_name, 0);
573 static int manager_enumerate_users_from_cgroup(Manager *m) {
578 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
583 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
587 while ((k = cg_read_subgroup(d, &name)) > 0) {
590 k = manager_add_user_by_name(m, name, &user);
597 user_add_to_gc_queue(user);
599 if (!user->cgroup_path)
600 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
617 static int manager_enumerate_linger_users(Manager *m) {
622 d = opendir("/var/lib/systemd/linger");
627 log_error("Failed to open /var/lib/systemd/linger/: %m");
631 while ((de = readdir(d))) {
634 if (!dirent_is_file(de))
637 k = manager_add_user_by_name(m, de->d_name, NULL);
639 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
649 int manager_enumerate_users(Manager *m) {
656 /* First, enumerate user cgroups */
657 r = manager_enumerate_users_from_cgroup(m);
659 /* Second, add lingering users on top */
660 k = manager_enumerate_linger_users(m);
664 /* Third, read in user data stored on disk */
665 d = opendir("/run/systemd/users");
670 log_error("Failed to open /run/systemd/users: %m");
674 while ((de = readdir(d))) {
678 if (!dirent_is_file(de))
681 k = parse_uid(de->d_name, &uid);
683 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
687 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
689 unlinkat(dirfd(d), de->d_name, 0);
703 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
708 HASHMAP_FOREACH(u, m->users, i) {
716 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
721 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
726 while ((k = cg_read_subgroup(d, &name)) > 0) {
729 if (streq(name, "shared"))
732 k = manager_add_session(m, u, name, &session);
738 session_add_to_gc_queue(session);
740 if (!session->cgroup_path)
741 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
759 int manager_enumerate_sessions(Manager *m) {
766 /* First enumerate session cgroups */
767 r = manager_enumerate_sessions_from_cgroup(m);
769 /* Second, read in session data stored on disk */
770 d = opendir("/run/systemd/sessions");
775 log_error("Failed to open /run/systemd/sessions: %m");
779 while ((de = readdir(d))) {
783 if (!dirent_is_file(de))
786 s = hashmap_get(m->sessions, de->d_name);
788 unlinkat(dirfd(d), de->d_name, 0);
802 int manager_enumerate_inhibitors(Manager *m) {
809 d = opendir("/run/systemd/inhibit");
814 log_error("Failed to open /run/systemd/inhibit: %m");
818 while ((de = readdir(d))) {
822 if (!dirent_is_file(de))
825 k = manager_add_inhibitor(m, de->d_name, &i);
827 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
832 k = inhibitor_load(i);
842 int manager_dispatch_seat_udev(Manager *m) {
843 struct udev_device *d;
848 d = udev_monitor_receive_device(m->udev_seat_monitor);
852 r = manager_process_seat_device(m, d);
853 udev_device_unref(d);
858 int manager_dispatch_vcsa_udev(Manager *m) {
859 struct udev_device *d;
865 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
869 name = udev_device_get_sysname(d);
871 /* Whenever a VCSA device is removed try to reallocate our
872 * VTs, to make sure our auto VTs never go away. */
874 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
875 r = seat_preallocate_vts(m->vtconsole);
877 udev_device_unref(d);
882 int manager_dispatch_button_udev(Manager *m) {
883 struct udev_device *d;
888 d = udev_monitor_receive_device(m->udev_button_monitor);
892 r = manager_process_button_device(m, d);
893 udev_device_unref(d);
898 int manager_dispatch_console(Manager *m) {
902 seat_read_active_vt(m->vtconsole);
907 static int vt_is_busy(int vtnr) {
908 struct vt_stat vt_stat;
913 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
914 * we'd open the latter we'd open the foreground tty which
915 * hence would be unconditionally busy. By opening /dev/tty1
916 * we avoid this. Since tty1 is special and needs to be an
917 * explicitly loaded getty or DM this is safe. */
919 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
923 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
926 r = !!(vt_stat.v_state & (1 << vtnr));
928 close_nointr_nofail(fd);
933 int manager_spawn_autovt(Manager *m, int vtnr) {
935 DBusMessage *message = NULL, *reply = NULL;
937 const char *mode = "fail";
943 dbus_error_init(&error);
945 if ((unsigned) vtnr > m->n_autovts)
948 r = vt_is_busy(vtnr);
954 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
956 log_error("Could not allocate message.");
961 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
962 log_error("Could not allocate service name.");
967 if (!dbus_message_append_args(message,
968 DBUS_TYPE_STRING, &name,
969 DBUS_TYPE_STRING, &mode,
970 DBUS_TYPE_INVALID)) {
971 log_error("Could not attach target and flag information to message.");
976 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
978 log_error("Failed to start unit: %s", bus_error_message(&error));
988 dbus_message_unref(message);
991 dbus_message_unref(reply);
993 dbus_error_free(&error);
998 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1006 s = hashmap_get(m->cgroups, cgroup);
1014 log_error("Out of memory.");
1021 e = strrchr(p, '/');
1030 s = hashmap_get(m->cgroups, p);
1039 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1047 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1051 r = manager_get_session_by_cgroup(m, p, session);
1057 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1061 r = manager_get_session_by_cgroup(m, cgroup, &s);
1065 session_add_to_gc_queue(s);
1068 static void manager_dispatch_other(Manager *m, int fd) {
1076 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1078 assert(s->fifo_fd == fd);
1079 session_remove_fifo(s);
1084 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1086 assert(i->fifo_fd == fd);
1092 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1094 assert(b->fd == fd);
1099 assert_not_reached("Got event for unknown fd");
1102 static int manager_connect_bus(Manager *m) {
1105 struct epoll_event ev;
1109 assert(m->bus_fd < 0);
1111 dbus_error_init(&error);
1113 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1115 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1120 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1121 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1122 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1123 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1124 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1125 log_error("Not enough memory");
1130 dbus_bus_add_match(m->bus,
1132 "interface='org.freedesktop.systemd1.Agent',"
1133 "member='Released',"
1134 "path='/org/freedesktop/systemd1/agent'",
1137 if (dbus_error_is_set(&error)) {
1138 log_error("Failed to register match: %s", bus_error_message(&error));
1143 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1144 if (dbus_error_is_set(&error)) {
1145 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1150 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1151 log_error("Failed to acquire name.");
1156 m->bus_fd = bus_loop_open(m->bus);
1157 if (m->bus_fd < 0) {
1163 ev.events = EPOLLIN;
1164 ev.data.u32 = FD_BUS;
1166 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1172 dbus_error_free(&error);
1177 static int manager_connect_console(Manager *m) {
1178 struct epoll_event ev;
1181 assert(m->console_active_fd < 0);
1183 /* On certain architectures (S390 and Xen, and containers),
1184 /dev/tty0 does not exist, so don't fail if we can't open
1186 if (access("/dev/tty0", F_OK) < 0) {
1187 m->console_active_fd = -1;
1191 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1192 if (m->console_active_fd < 0) {
1193 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1199 ev.data.u32 = FD_CONSOLE;
1201 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1207 static int manager_connect_udev(Manager *m) {
1208 struct epoll_event ev;
1212 assert(!m->udev_seat_monitor);
1213 assert(!m->udev_vcsa_monitor);
1214 assert(!m->udev_button_monitor);
1216 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1217 if (!m->udev_seat_monitor)
1220 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1224 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1228 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1232 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1235 ev.events = EPOLLIN;
1236 ev.data.u32 = FD_SEAT_UDEV;
1238 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1241 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1242 if (!m->udev_button_monitor)
1245 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1249 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1253 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1257 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1260 ev.events = EPOLLIN;
1261 ev.data.u32 = FD_BUTTON_UDEV;
1263 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1266 /* Don't bother watching VCSA devices, if nobody cares */
1267 if (m->n_autovts <= 0 || m->console_active_fd < 0)
1270 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1271 if (!m->udev_vcsa_monitor)
1274 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1278 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1282 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1285 ev.events = EPOLLIN;
1286 ev.data.u32 = FD_VCSA_UDEV;
1288 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1294 void manager_gc(Manager *m, bool drop_not_started) {
1301 while ((seat = m->seat_gc_queue)) {
1302 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1303 seat->in_gc_queue = false;
1305 if (seat_check_gc(seat, drop_not_started) == 0) {
1311 while ((session = m->session_gc_queue)) {
1312 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1313 session->in_gc_queue = false;
1315 if (session_check_gc(session, drop_not_started) == 0) {
1316 session_stop(session);
1317 session_free(session);
1321 while ((user = m->user_gc_queue)) {
1322 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1323 user->in_gc_queue = false;
1325 if (user_check_gc(user, drop_not_started) == 0) {
1332 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1335 dual_timestamp ts = { 0, 0 };
1340 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1342 HASHMAP_FOREACH(s, m->sessions, i) {
1346 ih = session_get_idle_hint(s, &k);
1352 if (k.monotonic < ts.monotonic)
1358 } else if (idle_hint) {
1360 if (k.monotonic > ts.monotonic)
1371 int manager_startup(Manager *m) {
1376 Inhibitor *inhibitor;
1380 assert(m->epoll_fd <= 0);
1382 cg_shorten_controllers(m->reset_controllers);
1383 cg_shorten_controllers(m->controllers);
1385 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1386 if (m->epoll_fd < 0)
1389 /* Connect to console */
1390 r = manager_connect_console(m);
1394 /* Connect to udev */
1395 r = manager_connect_udev(m);
1399 /* Connect to the bus */
1400 r = manager_connect_bus(m);
1404 /* Instantiate magic seat 0 */
1405 r = manager_add_seat(m, "seat0", &m->vtconsole);
1409 /* Deserialize state */
1410 manager_enumerate_devices(m);
1411 manager_enumerate_seats(m);
1412 manager_enumerate_users(m);
1413 manager_enumerate_sessions(m);
1414 manager_enumerate_inhibitors(m);
1415 manager_enumerate_buttons(m);
1417 /* Remove stale objects before we start them */
1418 manager_gc(m, false);
1420 /* And start everything */
1421 HASHMAP_FOREACH(seat, m->seats, i)
1424 HASHMAP_FOREACH(user, m->users, i)
1427 HASHMAP_FOREACH(session, m->sessions, i)
1428 session_start(session);
1430 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1431 inhibitor_start(inhibitor);
1436 int manager_run(Manager *m) {
1440 struct epoll_event event;
1444 manager_gc(m, true);
1446 if (manager_dispatch_delayed(m) > 0)
1449 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1452 manager_gc(m, true);
1454 if (m->delayed_unit) {
1457 x = now(CLOCK_MONOTONIC);
1458 y = m->delayed_timestamp + m->inhibit_delay_max;
1460 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1463 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1465 if (errno == EINTR || errno == EAGAIN)
1468 log_error("epoll() failed: %m");
1475 switch (event.data.u32) {
1478 manager_dispatch_seat_udev(m);
1482 manager_dispatch_vcsa_udev(m);
1485 case FD_BUTTON_UDEV:
1486 manager_dispatch_button_udev(m);
1490 manager_dispatch_console(m);
1494 bus_loop_dispatch(m->bus_fd);
1498 if (event.data.u32 >= FD_OTHER_BASE)
1499 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1506 static int manager_parse_config_file(Manager *m) {
1513 fn = "/etc/systemd/logind.conf";
1514 f = fopen(fn, "re");
1516 if (errno == ENOENT)
1519 log_warning("Failed to open configuration file %s: %m", fn);
1523 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1525 log_warning("Failed to parse configuration file: %s", strerror(-r));
1532 int main(int argc, char *argv[]) {
1536 log_set_target(LOG_TARGET_AUTO);
1537 log_set_facility(LOG_AUTH);
1538 log_parse_environment();
1544 log_error("This program takes no arguments.");
1551 log_error("Out of memory");
1556 manager_parse_config_file(m);
1558 r = manager_startup(m);
1560 log_error("Failed to fully start up daemon: %s", strerror(-r));
1564 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1568 "STATUS=Processing requests...");
1572 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1576 "STATUS=Shutting down...");
1581 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;