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) {
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) {
1248 /* On some systems the device node /dev/tty0 may exist
1249 * even though /sys/class/tty/tty0 does not. */
1250 if (errno == ENOENT)
1253 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1259 ev.data.u32 = FD_CONSOLE;
1261 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1267 static int manager_connect_udev(Manager *m) {
1268 struct epoll_event ev;
1272 assert(!m->udev_seat_monitor);
1273 assert(!m->udev_vcsa_monitor);
1274 assert(!m->udev_button_monitor);
1276 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1277 if (!m->udev_seat_monitor)
1280 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1284 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1288 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1292 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1295 ev.events = EPOLLIN;
1296 ev.data.u32 = FD_SEAT_UDEV;
1297 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1300 /* Don't watch keys if nobody cares */
1301 if (m->handle_power_key != HANDLE_OFF ||
1302 m->handle_sleep_key != HANDLE_OFF ||
1303 m->handle_lid_switch != HANDLE_OFF) {
1305 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1306 if (!m->udev_button_monitor)
1309 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1313 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1317 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1321 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1324 ev.events = EPOLLIN;
1325 ev.data.u32 = FD_BUTTON_UDEV;
1326 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1330 /* Don't bother watching VCSA devices, if nobody cares */
1331 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1333 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1334 if (!m->udev_vcsa_monitor)
1337 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1341 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1345 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1348 ev.events = EPOLLIN;
1349 ev.data.u32 = FD_VCSA_UDEV;
1350 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1357 void manager_gc(Manager *m, bool drop_not_started) {
1364 while ((seat = m->seat_gc_queue)) {
1365 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1366 seat->in_gc_queue = false;
1368 if (seat_check_gc(seat, drop_not_started) == 0) {
1374 while ((session = m->session_gc_queue)) {
1375 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1376 session->in_gc_queue = false;
1378 if (session_check_gc(session, drop_not_started) == 0) {
1379 session_stop(session);
1380 session_free(session);
1384 while ((user = m->user_gc_queue)) {
1385 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1386 user->in_gc_queue = false;
1388 if (user_check_gc(user, drop_not_started) == 0) {
1395 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1398 dual_timestamp ts = { 0, 0 };
1403 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1405 HASHMAP_FOREACH(s, m->sessions, i) {
1409 ih = session_get_idle_hint(s, &k);
1415 if (k.monotonic < ts.monotonic)
1421 } else if (idle_hint) {
1423 if (k.monotonic > ts.monotonic)
1434 int manager_startup(Manager *m) {
1439 Inhibitor *inhibitor;
1443 assert(m->epoll_fd <= 0);
1445 cg_shorten_controllers(m->reset_controllers);
1446 cg_shorten_controllers(m->controllers);
1448 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1449 if (m->epoll_fd < 0)
1452 /* Connect to console */
1453 r = manager_connect_console(m);
1457 /* Connect to udev */
1458 r = manager_connect_udev(m);
1462 /* Connect to the bus */
1463 r = manager_connect_bus(m);
1467 /* Instantiate magic seat 0 */
1468 r = manager_add_seat(m, "seat0", &m->vtconsole);
1472 /* Deserialize state */
1473 manager_enumerate_devices(m);
1474 manager_enumerate_seats(m);
1475 manager_enumerate_users(m);
1476 manager_enumerate_sessions(m);
1477 manager_enumerate_inhibitors(m);
1478 manager_enumerate_buttons(m);
1480 /* Remove stale objects before we start them */
1481 manager_gc(m, false);
1483 /* And start everything */
1484 HASHMAP_FOREACH(seat, m->seats, i)
1487 HASHMAP_FOREACH(user, m->users, i)
1490 HASHMAP_FOREACH(session, m->sessions, i)
1491 session_start(session);
1493 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1494 inhibitor_start(inhibitor);
1499 int manager_run(Manager *m) {
1503 struct epoll_event event;
1507 manager_gc(m, true);
1509 if (manager_dispatch_delayed(m) > 0)
1512 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1515 manager_gc(m, true);
1517 if (m->delayed_unit) {
1520 x = now(CLOCK_MONOTONIC);
1521 y = m->delayed_timestamp + m->inhibit_delay_max;
1523 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1526 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1528 if (errno == EINTR || errno == EAGAIN)
1531 log_error("epoll() failed: %m");
1538 switch (event.data.u32) {
1541 manager_dispatch_seat_udev(m);
1545 manager_dispatch_vcsa_udev(m);
1548 case FD_BUTTON_UDEV:
1549 manager_dispatch_button_udev(m);
1553 manager_dispatch_console(m);
1557 bus_loop_dispatch(m->bus_fd);
1561 if (event.data.u32 >= FD_OTHER_BASE)
1562 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1569 static int manager_parse_config_file(Manager *m) {
1576 fn = "/etc/systemd/logind.conf";
1577 f = fopen(fn, "re");
1579 if (errno == ENOENT)
1582 log_warning("Failed to open configuration file %s: %m", fn);
1586 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1588 log_warning("Failed to parse configuration file: %s", strerror(-r));
1595 int main(int argc, char *argv[]) {
1599 log_set_target(LOG_TARGET_AUTO);
1600 log_set_facility(LOG_AUTH);
1601 log_parse_environment();
1607 log_error("This program takes no arguments.");
1614 log_error("Out of memory");
1619 manager_parse_config_file(m);
1621 r = manager_startup(m);
1623 log_error("Failed to fully start up daemon: %s", strerror(-r));
1627 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1631 "STATUS=Processing requests...");
1635 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1639 "STATUS=Shutting down...");
1644 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;