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);
1029 e = strrchr(p, '/');
1038 s = hashmap_get(m->session_cgroups, p);
1047 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1055 u = hashmap_get(m->user_cgroups, cgroup);
1068 e = strrchr(p, '/');
1077 u = hashmap_get(m->user_cgroups, p);
1086 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1094 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1098 r = manager_get_session_by_cgroup(m, p, session);
1104 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1109 r = manager_get_session_by_cgroup(m, cgroup, &s);
1111 session_add_to_gc_queue(s);
1113 r = manager_get_user_by_cgroup(m, cgroup, &u);
1115 user_add_to_gc_queue(u);
1118 static void manager_dispatch_other(Manager *m, int fd) {
1126 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1128 assert(s->fifo_fd == fd);
1129 session_remove_fifo(s);
1134 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1136 assert(i->fifo_fd == fd);
1142 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1144 assert(b->fd == fd);
1149 assert_not_reached("Got event for unknown fd");
1152 static int manager_connect_bus(Manager *m) {
1155 struct epoll_event ev;
1159 assert(m->bus_fd < 0);
1161 dbus_error_init(&error);
1163 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1165 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1170 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1171 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1172 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1173 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1174 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1179 dbus_bus_add_match(m->bus,
1181 "interface='org.freedesktop.systemd1.Agent',"
1182 "member='Released',"
1183 "path='/org/freedesktop/systemd1/agent'",
1186 if (dbus_error_is_set(&error)) {
1187 log_error("Failed to register match: %s", bus_error_message(&error));
1192 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1193 if (dbus_error_is_set(&error)) {
1194 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1199 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1200 log_error("Failed to acquire name.");
1205 m->bus_fd = bus_loop_open(m->bus);
1206 if (m->bus_fd < 0) {
1212 ev.events = EPOLLIN;
1213 ev.data.u32 = FD_BUS;
1215 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1221 dbus_error_free(&error);
1226 static int manager_connect_console(Manager *m) {
1227 struct epoll_event ev;
1230 assert(m->console_active_fd < 0);
1232 /* On certain architectures (S390 and Xen, and containers),
1233 /dev/tty0 does not exist, so don't fail if we can't open
1235 if (access("/dev/tty0", F_OK) < 0) {
1236 m->console_active_fd = -1;
1240 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1241 if (m->console_active_fd < 0) {
1243 /* On some systems the device node /dev/tty0 may exist
1244 * even though /sys/class/tty/tty0 does not. */
1245 if (errno == ENOENT)
1248 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1254 ev.data.u32 = FD_CONSOLE;
1256 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1262 static int manager_connect_udev(Manager *m) {
1263 struct epoll_event ev;
1267 assert(!m->udev_seat_monitor);
1268 assert(!m->udev_vcsa_monitor);
1269 assert(!m->udev_button_monitor);
1271 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1272 if (!m->udev_seat_monitor)
1275 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1279 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1283 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1287 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1290 ev.events = EPOLLIN;
1291 ev.data.u32 = FD_SEAT_UDEV;
1292 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1295 /* Don't watch keys if nobody cares */
1296 if (m->handle_power_key != HANDLE_OFF ||
1297 m->handle_sleep_key != HANDLE_OFF ||
1298 m->handle_lid_switch != HANDLE_OFF) {
1300 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1301 if (!m->udev_button_monitor)
1304 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1308 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1312 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1316 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1319 ev.events = EPOLLIN;
1320 ev.data.u32 = FD_BUTTON_UDEV;
1321 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1325 /* Don't bother watching VCSA devices, if nobody cares */
1326 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1328 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1329 if (!m->udev_vcsa_monitor)
1332 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1336 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1340 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1343 ev.events = EPOLLIN;
1344 ev.data.u32 = FD_VCSA_UDEV;
1345 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1352 void manager_gc(Manager *m, bool drop_not_started) {
1359 while ((seat = m->seat_gc_queue)) {
1360 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1361 seat->in_gc_queue = false;
1363 if (seat_check_gc(seat, drop_not_started) == 0) {
1369 while ((session = m->session_gc_queue)) {
1370 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1371 session->in_gc_queue = false;
1373 if (session_check_gc(session, drop_not_started) == 0) {
1374 session_stop(session);
1375 session_free(session);
1379 while ((user = m->user_gc_queue)) {
1380 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1381 user->in_gc_queue = false;
1383 if (user_check_gc(user, drop_not_started) == 0) {
1390 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1393 dual_timestamp ts = { 0, 0 };
1398 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1400 HASHMAP_FOREACH(s, m->sessions, i) {
1404 ih = session_get_idle_hint(s, &k);
1410 if (k.monotonic < ts.monotonic)
1416 } else if (idle_hint) {
1418 if (k.monotonic > ts.monotonic)
1429 int manager_startup(Manager *m) {
1434 Inhibitor *inhibitor;
1438 assert(m->epoll_fd <= 0);
1440 cg_shorten_controllers(m->reset_controllers);
1441 cg_shorten_controllers(m->controllers);
1443 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1444 if (m->epoll_fd < 0)
1447 /* Connect to console */
1448 r = manager_connect_console(m);
1452 /* Connect to udev */
1453 r = manager_connect_udev(m);
1457 /* Connect to the bus */
1458 r = manager_connect_bus(m);
1462 /* Instantiate magic seat 0 */
1463 r = manager_add_seat(m, "seat0", &m->vtconsole);
1467 /* Deserialize state */
1468 manager_enumerate_devices(m);
1469 manager_enumerate_seats(m);
1470 manager_enumerate_users(m);
1471 manager_enumerate_sessions(m);
1472 manager_enumerate_inhibitors(m);
1473 manager_enumerate_buttons(m);
1475 /* Remove stale objects before we start them */
1476 manager_gc(m, false);
1478 /* And start everything */
1479 HASHMAP_FOREACH(seat, m->seats, i)
1482 HASHMAP_FOREACH(user, m->users, i)
1485 HASHMAP_FOREACH(session, m->sessions, i)
1486 session_start(session);
1488 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1489 inhibitor_start(inhibitor);
1494 int manager_run(Manager *m) {
1498 struct epoll_event event;
1502 manager_gc(m, true);
1504 if (manager_dispatch_delayed(m) > 0)
1507 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1510 manager_gc(m, true);
1512 if (m->delayed_unit) {
1515 x = now(CLOCK_MONOTONIC);
1516 y = m->delayed_timestamp + m->inhibit_delay_max;
1518 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1521 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1523 if (errno == EINTR || errno == EAGAIN)
1526 log_error("epoll() failed: %m");
1533 switch (event.data.u32) {
1536 manager_dispatch_seat_udev(m);
1540 manager_dispatch_vcsa_udev(m);
1543 case FD_BUTTON_UDEV:
1544 manager_dispatch_button_udev(m);
1548 manager_dispatch_console(m);
1552 bus_loop_dispatch(m->bus_fd);
1556 if (event.data.u32 >= FD_OTHER_BASE)
1557 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1564 static int manager_parse_config_file(Manager *m) {
1571 fn = "/etc/systemd/logind.conf";
1572 f = fopen(fn, "re");
1574 if (errno == ENOENT)
1577 log_warning("Failed to open configuration file %s: %m", fn);
1581 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1583 log_warning("Failed to parse configuration file: %s", strerror(-r));
1590 int main(int argc, char *argv[]) {
1594 log_set_target(LOG_TARGET_AUTO);
1595 log_set_facility(LOG_AUTH);
1596 log_parse_environment();
1602 log_error("This program takes no arguments.");
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;