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->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 if (m->handle_power_key == HANDLE_OFF &&
488 m->handle_sleep_key == HANDLE_OFF &&
489 m->handle_lid_switch == HANDLE_OFF)
492 e = udev_enumerate_new(m->udev);
498 r = udev_enumerate_add_match_subsystem(e, "input");
502 r = udev_enumerate_add_match_tag(e, "power-switch");
506 r = udev_enumerate_scan_devices(e);
510 first = udev_enumerate_get_list_entry(e);
511 udev_list_entry_foreach(item, first) {
512 struct udev_device *d;
515 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
521 k = manager_process_button_device(m, d);
522 udev_device_unref(d);
530 udev_enumerate_unref(e);
535 int manager_enumerate_seats(Manager *m) {
542 /* This loads data about seats stored on disk, but does not
543 * actually create any seats. Removes data of seats that no
546 d = opendir("/run/systemd/seats");
551 log_error("Failed to open /run/systemd/seats: %m");
555 while ((de = readdir(d))) {
559 if (!dirent_is_file(de))
562 s = hashmap_get(m->seats, de->d_name);
564 unlinkat(dirfd(d), de->d_name, 0);
578 static int manager_enumerate_users_from_cgroup(Manager *m) {
583 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
588 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
592 while ((k = cg_read_subgroup(d, &name)) > 0) {
595 k = manager_add_user_by_name(m, name, &user);
602 user_add_to_gc_queue(user);
604 if (!user->cgroup_path)
605 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
622 static int manager_enumerate_linger_users(Manager *m) {
627 d = opendir("/var/lib/systemd/linger");
632 log_error("Failed to open /var/lib/systemd/linger/: %m");
636 while ((de = readdir(d))) {
639 if (!dirent_is_file(de))
642 k = manager_add_user_by_name(m, de->d_name, NULL);
644 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
654 int manager_enumerate_users(Manager *m) {
661 /* First, enumerate user cgroups */
662 r = manager_enumerate_users_from_cgroup(m);
664 /* Second, add lingering users on top */
665 k = manager_enumerate_linger_users(m);
669 /* Third, read in user data stored on disk */
670 d = opendir("/run/systemd/users");
675 log_error("Failed to open /run/systemd/users: %m");
679 while ((de = readdir(d))) {
683 if (!dirent_is_file(de))
686 k = parse_uid(de->d_name, &uid);
688 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
692 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
694 unlinkat(dirfd(d), de->d_name, 0);
708 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
713 HASHMAP_FOREACH(u, m->users, i) {
721 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
726 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
731 while ((k = cg_read_subgroup(d, &name)) > 0) {
734 if (streq(name, "shared"))
737 k = manager_add_session(m, u, name, &session);
743 session_add_to_gc_queue(session);
745 if (!session->cgroup_path)
746 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
764 int manager_enumerate_sessions(Manager *m) {
771 /* First enumerate session cgroups */
772 r = manager_enumerate_sessions_from_cgroup(m);
774 /* Second, read in session data stored on disk */
775 d = opendir("/run/systemd/sessions");
780 log_error("Failed to open /run/systemd/sessions: %m");
784 while ((de = readdir(d))) {
788 if (!dirent_is_file(de))
791 s = hashmap_get(m->sessions, de->d_name);
793 unlinkat(dirfd(d), de->d_name, 0);
807 int manager_enumerate_inhibitors(Manager *m) {
814 d = opendir("/run/systemd/inhibit");
819 log_error("Failed to open /run/systemd/inhibit: %m");
823 while ((de = readdir(d))) {
827 if (!dirent_is_file(de))
830 k = manager_add_inhibitor(m, de->d_name, &i);
832 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
837 k = inhibitor_load(i);
847 int manager_dispatch_seat_udev(Manager *m) {
848 struct udev_device *d;
853 d = udev_monitor_receive_device(m->udev_seat_monitor);
857 r = manager_process_seat_device(m, d);
858 udev_device_unref(d);
863 int manager_dispatch_vcsa_udev(Manager *m) {
864 struct udev_device *d;
870 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
874 name = udev_device_get_sysname(d);
876 /* Whenever a VCSA device is removed try to reallocate our
877 * VTs, to make sure our auto VTs never go away. */
879 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
880 r = seat_preallocate_vts(m->vtconsole);
882 udev_device_unref(d);
887 int manager_dispatch_button_udev(Manager *m) {
888 struct udev_device *d;
893 d = udev_monitor_receive_device(m->udev_button_monitor);
897 r = manager_process_button_device(m, d);
898 udev_device_unref(d);
903 int manager_dispatch_console(Manager *m) {
907 seat_read_active_vt(m->vtconsole);
912 static int vt_is_busy(int vtnr) {
913 struct vt_stat vt_stat;
918 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
919 * we'd open the latter we'd open the foreground tty which
920 * hence would be unconditionally busy. By opening /dev/tty1
921 * we avoid this. Since tty1 is special and needs to be an
922 * explicitly loaded getty or DM this is safe. */
924 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
928 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
931 r = !!(vt_stat.v_state & (1 << vtnr));
933 close_nointr_nofail(fd);
938 int manager_spawn_autovt(Manager *m, int vtnr) {
940 DBusMessage *message = NULL, *reply = NULL;
942 const char *mode = "fail";
948 dbus_error_init(&error);
950 if ((unsigned) vtnr > m->n_autovts)
953 r = vt_is_busy(vtnr);
959 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
961 log_error("Could not allocate message.");
966 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
967 log_error("Could not allocate service name.");
972 if (!dbus_message_append_args(message,
973 DBUS_TYPE_STRING, &name,
974 DBUS_TYPE_STRING, &mode,
975 DBUS_TYPE_INVALID)) {
976 log_error("Could not attach target and flag information to message.");
981 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
983 log_error("Failed to start unit: %s", bus_error_message(&error));
993 dbus_message_unref(message);
996 dbus_message_unref(reply);
998 dbus_error_free(&error);
1003 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1011 s = hashmap_get(m->cgroups, cgroup);
1019 log_error("Out of memory.");
1026 e = strrchr(p, '/');
1035 s = hashmap_get(m->cgroups, p);
1044 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1052 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1056 r = manager_get_session_by_cgroup(m, p, session);
1062 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1066 r = manager_get_session_by_cgroup(m, cgroup, &s);
1070 session_add_to_gc_queue(s);
1073 static void manager_dispatch_other(Manager *m, int fd) {
1081 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1083 assert(s->fifo_fd == fd);
1084 session_remove_fifo(s);
1089 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1091 assert(i->fifo_fd == fd);
1097 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1099 assert(b->fd == fd);
1104 assert_not_reached("Got event for unknown fd");
1107 static int manager_connect_bus(Manager *m) {
1110 struct epoll_event ev;
1114 assert(m->bus_fd < 0);
1116 dbus_error_init(&error);
1118 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1120 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1125 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1126 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1127 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1128 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1129 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1130 log_error("Not enough memory");
1135 dbus_bus_add_match(m->bus,
1137 "interface='org.freedesktop.systemd1.Agent',"
1138 "member='Released',"
1139 "path='/org/freedesktop/systemd1/agent'",
1142 if (dbus_error_is_set(&error)) {
1143 log_error("Failed to register match: %s", bus_error_message(&error));
1148 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1149 if (dbus_error_is_set(&error)) {
1150 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1155 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1156 log_error("Failed to acquire name.");
1161 m->bus_fd = bus_loop_open(m->bus);
1162 if (m->bus_fd < 0) {
1168 ev.events = EPOLLIN;
1169 ev.data.u32 = FD_BUS;
1171 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1177 dbus_error_free(&error);
1182 static int manager_connect_console(Manager *m) {
1183 struct epoll_event ev;
1186 assert(m->console_active_fd < 0);
1188 /* On certain architectures (S390 and Xen, and containers),
1189 /dev/tty0 does not exist, so don't fail if we can't open
1191 if (access("/dev/tty0", F_OK) < 0) {
1192 m->console_active_fd = -1;
1196 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1197 if (m->console_active_fd < 0) {
1198 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1204 ev.data.u32 = FD_CONSOLE;
1206 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1212 static int manager_connect_udev(Manager *m) {
1213 struct epoll_event ev;
1217 assert(!m->udev_seat_monitor);
1218 assert(!m->udev_vcsa_monitor);
1219 assert(!m->udev_button_monitor);
1221 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1222 if (!m->udev_seat_monitor)
1225 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1229 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1233 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1237 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1240 ev.events = EPOLLIN;
1241 ev.data.u32 = FD_SEAT_UDEV;
1242 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1245 /* Don't watch keys if nobody cares */
1246 if (m->handle_power_key != HANDLE_OFF ||
1247 m->handle_sleep_key != HANDLE_OFF ||
1248 m->handle_lid_switch != HANDLE_OFF) {
1250 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1251 if (!m->udev_button_monitor)
1254 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1258 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1262 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1266 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1269 ev.events = EPOLLIN;
1270 ev.data.u32 = FD_BUTTON_UDEV;
1271 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1275 /* Don't bother watching VCSA devices, if nobody cares */
1276 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1278 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1279 if (!m->udev_vcsa_monitor)
1282 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1286 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1290 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1293 ev.events = EPOLLIN;
1294 ev.data.u32 = FD_VCSA_UDEV;
1295 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1302 void manager_gc(Manager *m, bool drop_not_started) {
1309 while ((seat = m->seat_gc_queue)) {
1310 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1311 seat->in_gc_queue = false;
1313 if (seat_check_gc(seat, drop_not_started) == 0) {
1319 while ((session = m->session_gc_queue)) {
1320 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1321 session->in_gc_queue = false;
1323 if (session_check_gc(session, drop_not_started) == 0) {
1324 session_stop(session);
1325 session_free(session);
1329 while ((user = m->user_gc_queue)) {
1330 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1331 user->in_gc_queue = false;
1333 if (user_check_gc(user, drop_not_started) == 0) {
1340 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1343 dual_timestamp ts = { 0, 0 };
1348 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1350 HASHMAP_FOREACH(s, m->sessions, i) {
1354 ih = session_get_idle_hint(s, &k);
1360 if (k.monotonic < ts.monotonic)
1366 } else if (idle_hint) {
1368 if (k.monotonic > ts.monotonic)
1379 int manager_startup(Manager *m) {
1384 Inhibitor *inhibitor;
1388 assert(m->epoll_fd <= 0);
1390 cg_shorten_controllers(m->reset_controllers);
1391 cg_shorten_controllers(m->controllers);
1393 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1394 if (m->epoll_fd < 0)
1397 /* Connect to console */
1398 r = manager_connect_console(m);
1402 /* Connect to udev */
1403 r = manager_connect_udev(m);
1407 /* Connect to the bus */
1408 r = manager_connect_bus(m);
1412 /* Instantiate magic seat 0 */
1413 r = manager_add_seat(m, "seat0", &m->vtconsole);
1417 /* Deserialize state */
1418 manager_enumerate_devices(m);
1419 manager_enumerate_seats(m);
1420 manager_enumerate_users(m);
1421 manager_enumerate_sessions(m);
1422 manager_enumerate_inhibitors(m);
1423 manager_enumerate_buttons(m);
1425 /* Remove stale objects before we start them */
1426 manager_gc(m, false);
1428 /* And start everything */
1429 HASHMAP_FOREACH(seat, m->seats, i)
1432 HASHMAP_FOREACH(user, m->users, i)
1435 HASHMAP_FOREACH(session, m->sessions, i)
1436 session_start(session);
1438 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1439 inhibitor_start(inhibitor);
1444 int manager_run(Manager *m) {
1448 struct epoll_event event;
1452 manager_gc(m, true);
1454 if (manager_dispatch_delayed(m) > 0)
1457 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1460 manager_gc(m, true);
1462 if (m->delayed_unit) {
1465 x = now(CLOCK_MONOTONIC);
1466 y = m->delayed_timestamp + m->inhibit_delay_max;
1468 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1471 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1473 if (errno == EINTR || errno == EAGAIN)
1476 log_error("epoll() failed: %m");
1483 switch (event.data.u32) {
1486 manager_dispatch_seat_udev(m);
1490 manager_dispatch_vcsa_udev(m);
1493 case FD_BUTTON_UDEV:
1494 manager_dispatch_button_udev(m);
1498 manager_dispatch_console(m);
1502 bus_loop_dispatch(m->bus_fd);
1506 if (event.data.u32 >= FD_OTHER_BASE)
1507 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1514 static int manager_parse_config_file(Manager *m) {
1521 fn = "/etc/systemd/logind.conf";
1522 f = fopen(fn, "re");
1524 if (errno == ENOENT)
1527 log_warning("Failed to open configuration file %s: %m", fn);
1531 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1533 log_warning("Failed to parse configuration file: %s", strerror(-r));
1540 int main(int argc, char *argv[]) {
1544 log_set_target(LOG_TARGET_AUTO);
1545 log_set_facility(LOG_AUTH);
1546 log_parse_environment();
1552 log_error("This program takes no arguments.");
1559 log_error("Out of memory");
1564 manager_parse_config_file(m);
1566 r = manager_startup(m);
1568 log_error("Failed to fully start up daemon: %s", strerror(-r));
1572 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1576 "STATUS=Processing requests...");
1580 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1584 "STATUS=Shutting down...");
1589 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;