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);
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) {
945 DBusMessage *message = NULL, *reply = NULL;
947 const char *mode = "fail";
953 dbus_error_init(&error);
955 if ((unsigned) vtnr > m->n_autovts)
958 r = vt_is_busy(vtnr);
964 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
966 log_error("Could not allocate message.");
971 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
972 log_error("Could not allocate service name.");
977 if (!dbus_message_append_args(message,
978 DBUS_TYPE_STRING, &name,
979 DBUS_TYPE_STRING, &mode,
980 DBUS_TYPE_INVALID)) {
981 log_error("Could not attach target and flag information to message.");
986 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
988 log_error("Failed to start unit: %s", bus_error_message(&error));
998 dbus_message_unref(message);
1001 dbus_message_unref(reply);
1003 dbus_error_free(&error);
1008 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1016 s = hashmap_get(m->session_cgroups, cgroup);
1024 log_error("Out of memory.");
1031 e = strrchr(p, '/');
1040 s = hashmap_get(m->session_cgroups, p);
1049 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1057 u = hashmap_get(m->user_cgroups, cgroup);
1065 log_error("Out of memory.");
1072 e = strrchr(p, '/');
1081 u = hashmap_get(m->user_cgroups, p);
1090 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1098 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1102 r = manager_get_session_by_cgroup(m, p, session);
1108 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1113 r = manager_get_session_by_cgroup(m, cgroup, &s);
1115 session_add_to_gc_queue(s);
1117 r = manager_get_user_by_cgroup(m, cgroup, &u);
1119 user_add_to_gc_queue(u);
1122 static void manager_dispatch_other(Manager *m, int fd) {
1130 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1132 assert(s->fifo_fd == fd);
1133 session_remove_fifo(s);
1138 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1140 assert(i->fifo_fd == fd);
1146 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1148 assert(b->fd == fd);
1153 assert_not_reached("Got event for unknown fd");
1156 static int manager_connect_bus(Manager *m) {
1159 struct epoll_event ev;
1163 assert(m->bus_fd < 0);
1165 dbus_error_init(&error);
1167 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1169 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1174 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1175 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1176 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1177 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1178 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1179 log_error("Not enough memory");
1184 dbus_bus_add_match(m->bus,
1186 "interface='org.freedesktop.systemd1.Agent',"
1187 "member='Released',"
1188 "path='/org/freedesktop/systemd1/agent'",
1191 if (dbus_error_is_set(&error)) {
1192 log_error("Failed to register match: %s", bus_error_message(&error));
1197 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1198 if (dbus_error_is_set(&error)) {
1199 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1204 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1205 log_error("Failed to acquire name.");
1210 m->bus_fd = bus_loop_open(m->bus);
1211 if (m->bus_fd < 0) {
1217 ev.events = EPOLLIN;
1218 ev.data.u32 = FD_BUS;
1220 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1226 dbus_error_free(&error);
1231 static int manager_connect_console(Manager *m) {
1232 struct epoll_event ev;
1235 assert(m->console_active_fd < 0);
1237 /* On certain architectures (S390 and Xen, and containers),
1238 /dev/tty0 does not exist, so don't fail if we can't open
1240 if (access("/dev/tty0", F_OK) < 0) {
1241 m->console_active_fd = -1;
1245 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1246 if (m->console_active_fd < 0) {
1247 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1253 ev.data.u32 = FD_CONSOLE;
1255 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1261 static int manager_connect_udev(Manager *m) {
1262 struct epoll_event ev;
1266 assert(!m->udev_seat_monitor);
1267 assert(!m->udev_vcsa_monitor);
1268 assert(!m->udev_button_monitor);
1270 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1271 if (!m->udev_seat_monitor)
1274 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1278 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1282 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1286 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1289 ev.events = EPOLLIN;
1290 ev.data.u32 = FD_SEAT_UDEV;
1291 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1294 /* Don't watch keys if nobody cares */
1295 if (m->handle_power_key != HANDLE_OFF ||
1296 m->handle_sleep_key != HANDLE_OFF ||
1297 m->handle_lid_switch != HANDLE_OFF) {
1299 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1300 if (!m->udev_button_monitor)
1303 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1307 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1311 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1315 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1318 ev.events = EPOLLIN;
1319 ev.data.u32 = FD_BUTTON_UDEV;
1320 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1324 /* Don't bother watching VCSA devices, if nobody cares */
1325 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1327 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1328 if (!m->udev_vcsa_monitor)
1331 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1335 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1339 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1342 ev.events = EPOLLIN;
1343 ev.data.u32 = FD_VCSA_UDEV;
1344 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1351 void manager_gc(Manager *m, bool drop_not_started) {
1358 while ((seat = m->seat_gc_queue)) {
1359 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1360 seat->in_gc_queue = false;
1362 if (seat_check_gc(seat, drop_not_started) == 0) {
1368 while ((session = m->session_gc_queue)) {
1369 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1370 session->in_gc_queue = false;
1372 if (session_check_gc(session, drop_not_started) == 0) {
1373 session_stop(session);
1374 session_free(session);
1378 while ((user = m->user_gc_queue)) {
1379 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1380 user->in_gc_queue = false;
1382 if (user_check_gc(user, drop_not_started) == 0) {
1389 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1392 dual_timestamp ts = { 0, 0 };
1397 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1399 HASHMAP_FOREACH(s, m->sessions, i) {
1403 ih = session_get_idle_hint(s, &k);
1409 if (k.monotonic < ts.monotonic)
1415 } else if (idle_hint) {
1417 if (k.monotonic > ts.monotonic)
1428 int manager_startup(Manager *m) {
1433 Inhibitor *inhibitor;
1437 assert(m->epoll_fd <= 0);
1439 cg_shorten_controllers(m->reset_controllers);
1440 cg_shorten_controllers(m->controllers);
1442 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1443 if (m->epoll_fd < 0)
1446 /* Connect to console */
1447 r = manager_connect_console(m);
1451 /* Connect to udev */
1452 r = manager_connect_udev(m);
1456 /* Connect to the bus */
1457 r = manager_connect_bus(m);
1461 /* Instantiate magic seat 0 */
1462 r = manager_add_seat(m, "seat0", &m->vtconsole);
1466 /* Deserialize state */
1467 manager_enumerate_devices(m);
1468 manager_enumerate_seats(m);
1469 manager_enumerate_users(m);
1470 manager_enumerate_sessions(m);
1471 manager_enumerate_inhibitors(m);
1472 manager_enumerate_buttons(m);
1474 /* Remove stale objects before we start them */
1475 manager_gc(m, false);
1477 /* And start everything */
1478 HASHMAP_FOREACH(seat, m->seats, i)
1481 HASHMAP_FOREACH(user, m->users, i)
1484 HASHMAP_FOREACH(session, m->sessions, i)
1485 session_start(session);
1487 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1488 inhibitor_start(inhibitor);
1493 int manager_run(Manager *m) {
1497 struct epoll_event event;
1501 manager_gc(m, true);
1503 if (manager_dispatch_delayed(m) > 0)
1506 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1509 manager_gc(m, true);
1511 if (m->delayed_unit) {
1514 x = now(CLOCK_MONOTONIC);
1515 y = m->delayed_timestamp + m->inhibit_delay_max;
1517 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1520 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1522 if (errno == EINTR || errno == EAGAIN)
1525 log_error("epoll() failed: %m");
1532 switch (event.data.u32) {
1535 manager_dispatch_seat_udev(m);
1539 manager_dispatch_vcsa_udev(m);
1542 case FD_BUTTON_UDEV:
1543 manager_dispatch_button_udev(m);
1547 manager_dispatch_console(m);
1551 bus_loop_dispatch(m->bus_fd);
1555 if (event.data.u32 >= FD_OTHER_BASE)
1556 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1563 static int manager_parse_config_file(Manager *m) {
1570 fn = "/etc/systemd/logind.conf";
1571 f = fopen(fn, "re");
1573 if (errno == ENOENT)
1576 log_warning("Failed to open configuration file %s: %m", fn);
1580 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1582 log_warning("Failed to parse configuration file: %s", strerror(-r));
1589 int main(int argc, char *argv[]) {
1593 log_set_target(LOG_TARGET_AUTO);
1594 log_set_facility(LOG_AUTH);
1595 log_parse_environment();
1601 log_error("This program takes no arguments.");
1608 log_error("Out of memory");
1613 manager_parse_config_file(m);
1615 r = manager_startup(m);
1617 log_error("Failed to fully start up daemon: %s", strerror(-r));
1621 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1625 "STATUS=Processing requests...");
1629 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1633 "STATUS=Shutting down...");
1638 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;