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>
31 #include <sys/timerfd.h>
33 #include <systemd/sd-daemon.h>
36 #include "dbus-common.h"
37 #include "dbus-loop.h"
39 #include "conf-parser.h"
42 Manager *manager_new(void) {
49 m->console_active_fd = -1;
53 m->udev_button_fd = -1;
55 m->reserve_vt_fd = -1;
59 m->inhibit_delay_max = 5 * USEC_PER_SEC;
60 m->handle_power_key = HANDLE_POWEROFF;
61 m->handle_suspend_key = HANDLE_SUSPEND;
62 m->handle_hibernate_key = HANDLE_HIBERNATE;
63 m->handle_lid_switch = HANDLE_SUSPEND;
64 m->lid_switch_ignore_inhibited = true;
66 m->idle_action_fd = -1;
67 m->idle_action_usec = 30 * USEC_PER_MINUTE;
68 m->idle_action = HANDLE_IGNORE;
69 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
71 m->devices = hashmap_new(string_hash_func, string_compare_func);
72 m->seats = hashmap_new(string_hash_func, string_compare_func);
73 m->sessions = hashmap_new(string_hash_func, string_compare_func);
74 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
75 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
76 m->buttons = hashmap_new(string_hash_func, string_compare_func);
78 m->user_units = hashmap_new(string_hash_func, string_compare_func);
79 m->session_units = hashmap_new(string_hash_func, string_compare_func);
81 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
82 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
83 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
85 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
86 !m->user_units || !m->session_units ||
87 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
92 m->kill_exclude_users = strv_new("root", NULL);
93 if (!m->kill_exclude_users) {
107 void manager_free(Manager *m) {
117 while ((session = hashmap_first(m->sessions)))
118 session_free(session);
120 while ((u = hashmap_first(m->users)))
123 while ((d = hashmap_first(m->devices)))
126 while ((s = hashmap_first(m->seats)))
129 while ((i = hashmap_first(m->inhibitors)))
132 while ((b = hashmap_first(m->buttons)))
135 hashmap_free(m->devices);
136 hashmap_free(m->seats);
137 hashmap_free(m->sessions);
138 hashmap_free(m->users);
139 hashmap_free(m->inhibitors);
140 hashmap_free(m->buttons);
142 hashmap_free(m->user_units);
143 hashmap_free(m->session_units);
145 hashmap_free(m->session_fds);
146 hashmap_free(m->inhibitor_fds);
147 hashmap_free(m->button_fds);
149 if (m->console_active_fd >= 0)
150 close_nointr_nofail(m->console_active_fd);
152 if (m->udev_seat_monitor)
153 udev_monitor_unref(m->udev_seat_monitor);
154 if (m->udev_vcsa_monitor)
155 udev_monitor_unref(m->udev_vcsa_monitor);
156 if (m->udev_button_monitor)
157 udev_monitor_unref(m->udev_button_monitor);
163 dbus_connection_flush(m->bus);
164 dbus_connection_close(m->bus);
165 dbus_connection_unref(m->bus);
169 close_nointr_nofail(m->bus_fd);
171 if (m->epoll_fd >= 0)
172 close_nointr_nofail(m->epoll_fd);
174 if (m->reserve_vt_fd >= 0)
175 close_nointr_nofail(m->reserve_vt_fd);
177 if (m->idle_action_fd >= 0)
178 close_nointr_nofail(m->idle_action_fd);
180 strv_free(m->kill_only_users);
181 strv_free(m->kill_exclude_users);
187 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
193 d = hashmap_get(m->devices, sysfs);
201 d = device_new(m, sysfs);
211 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
217 s = hashmap_get(m->seats, id);
235 int manager_add_session(Manager *m, const char *id, Session **_session) {
241 s = hashmap_get(m->sessions, id);
249 s = session_new(m, id);
259 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
265 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
273 u = user_new(m, uid, gid, name);
283 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
291 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
295 return manager_add_user(m, uid, gid, name, _user);
298 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
306 return errno ? -errno : -ENOENT;
308 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
311 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
317 i = hashmap_get(m->inhibitors, id);
325 i = inhibitor_new(m, id);
335 int manager_add_button(Manager *m, const char *name, Button **_button) {
341 b = hashmap_get(m->buttons, name);
349 b = button_new(m, name);
359 int manager_process_seat_device(Manager *m, struct udev_device *d) {
365 if (streq_ptr(udev_device_get_action(d), "remove")) {
367 device = hashmap_get(m->devices, udev_device_get_syspath(d));
371 seat_add_to_gc_queue(device->seat);
378 sn = udev_device_get_property_value(d, "ID_SEAT");
382 if (!seat_name_is_valid(sn)) {
383 log_warning("Device with invalid seat name %s found, ignoring.", sn);
387 r = manager_add_device(m, udev_device_get_syspath(d), &device);
391 r = manager_add_seat(m, sn, &seat);
399 device_attach(device, seat);
406 int manager_process_button_device(Manager *m, struct udev_device *d) {
413 if (streq_ptr(udev_device_get_action(d), "remove")) {
415 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
424 r = manager_add_button(m, udev_device_get_sysname(d), &b);
428 sn = udev_device_get_property_value(d, "ID_SEAT");
432 button_set_seat(b, sn);
439 int manager_enumerate_devices(Manager *m) {
440 struct udev_list_entry *item = NULL, *first = NULL;
441 struct udev_enumerate *e;
446 /* Loads devices from udev and creates seats for them as
449 e = udev_enumerate_new(m->udev);
455 r = udev_enumerate_add_match_tag(e, "master-of-seat");
459 r = udev_enumerate_scan_devices(e);
463 first = udev_enumerate_get_list_entry(e);
464 udev_list_entry_foreach(item, first) {
465 struct udev_device *d;
468 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
474 k = manager_process_seat_device(m, d);
475 udev_device_unref(d);
483 udev_enumerate_unref(e);
488 int manager_enumerate_buttons(Manager *m) {
489 struct udev_list_entry *item = NULL, *first = NULL;
490 struct udev_enumerate *e;
495 /* Loads buttons from udev */
497 if (m->handle_power_key == HANDLE_IGNORE &&
498 m->handle_suspend_key == HANDLE_IGNORE &&
499 m->handle_hibernate_key == HANDLE_IGNORE &&
500 m->handle_lid_switch == HANDLE_IGNORE)
503 e = udev_enumerate_new(m->udev);
509 r = udev_enumerate_add_match_subsystem(e, "input");
513 r = udev_enumerate_add_match_tag(e, "power-switch");
517 r = udev_enumerate_scan_devices(e);
521 first = udev_enumerate_get_list_entry(e);
522 udev_list_entry_foreach(item, first) {
523 struct udev_device *d;
526 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
532 k = manager_process_button_device(m, d);
533 udev_device_unref(d);
541 udev_enumerate_unref(e);
546 int manager_enumerate_seats(Manager *m) {
547 _cleanup_closedir_ DIR *d = NULL;
553 /* This loads data about seats stored on disk, but does not
554 * actually create any seats. Removes data of seats that no
557 d = opendir("/run/systemd/seats");
562 log_error("Failed to open /run/systemd/seats: %m");
566 FOREACH_DIRENT(de, d, return -errno) {
570 if (!dirent_is_file(de))
573 s = hashmap_get(m->seats, de->d_name);
575 unlinkat(dirfd(d), de->d_name, 0);
587 static int manager_enumerate_linger_users(Manager *m) {
588 _cleanup_closedir_ DIR *d = NULL;
594 d = opendir("/var/lib/systemd/linger");
599 log_error("Failed to open /var/lib/systemd/linger/: %m");
603 FOREACH_DIRENT(de, d, return -errno) {
606 if (!dirent_is_file(de))
609 k = manager_add_user_by_name(m, de->d_name, NULL);
611 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
619 int manager_enumerate_users(Manager *m) {
620 _cleanup_closedir_ DIR *d = NULL;
626 /* Add lingering users */
627 r = manager_enumerate_linger_users(m);
629 /* Read in user data stored on disk */
630 d = opendir("/run/systemd/users");
635 log_error("Failed to open /run/systemd/users: %m");
639 FOREACH_DIRENT(de, d, return -errno) {
642 if (!dirent_is_file(de))
645 k = manager_add_user_by_name(m, de->d_name, &u);
647 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
653 user_add_to_gc_queue(u);
663 int manager_enumerate_sessions(Manager *m) {
664 _cleanup_closedir_ DIR *d = NULL;
670 /* Read in session data stored on disk */
671 d = opendir("/run/systemd/sessions");
676 log_error("Failed to open /run/systemd/sessions: %m");
680 FOREACH_DIRENT(de, d, return -errno) {
684 if (!dirent_is_file(de))
687 k = manager_add_session(m, de->d_name, &s);
689 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
695 session_add_to_gc_queue(s);
705 int manager_enumerate_inhibitors(Manager *m) {
706 _cleanup_closedir_ DIR *d = NULL;
712 d = opendir("/run/systemd/inhibit");
717 log_error("Failed to open /run/systemd/inhibit: %m");
721 FOREACH_DIRENT(de, d, return -errno) {
725 if (!dirent_is_file(de))
728 k = manager_add_inhibitor(m, de->d_name, &i);
730 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
735 k = inhibitor_load(i);
743 int manager_dispatch_seat_udev(Manager *m) {
744 struct udev_device *d;
749 d = udev_monitor_receive_device(m->udev_seat_monitor);
753 r = manager_process_seat_device(m, d);
754 udev_device_unref(d);
759 int manager_dispatch_vcsa_udev(Manager *m) {
760 struct udev_device *d;
766 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
770 name = udev_device_get_sysname(d);
772 /* Whenever a VCSA device is removed try to reallocate our
773 * VTs, to make sure our auto VTs never go away. */
775 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
776 r = seat_preallocate_vts(m->vtconsole);
778 udev_device_unref(d);
783 int manager_dispatch_button_udev(Manager *m) {
784 struct udev_device *d;
789 d = udev_monitor_receive_device(m->udev_button_monitor);
793 r = manager_process_button_device(m, d);
794 udev_device_unref(d);
799 int manager_dispatch_console(Manager *m) {
803 seat_read_active_vt(m->vtconsole);
808 static int vt_is_busy(int vtnr) {
809 struct vt_stat vt_stat;
814 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
815 * we'd open the latter we'd open the foreground tty which
816 * hence would be unconditionally busy. By opening /dev/tty1
817 * we avoid this. Since tty1 is special and needs to be an
818 * explicitly loaded getty or DM this is safe. */
820 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
824 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
827 r = !!(vt_stat.v_state & (1 << vtnr));
829 close_nointr_nofail(fd);
834 int manager_spawn_autovt(Manager *m, int vtnr) {
837 const char *mode = "fail";
842 if ((unsigned) vtnr > m->n_autovts &&
843 (unsigned) vtnr != m->reserve_vt)
846 if ((unsigned) vtnr != m->reserve_vt) {
847 /* If this is the reserved TTY, we'll start the getty
848 * on it in any case, but otherwise only if it is not
851 r = vt_is_busy(vtnr);
858 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
859 log_error("Could not allocate service name.");
864 r = bus_method_call_with_reply (
866 "org.freedesktop.systemd1",
867 "/org/freedesktop/systemd1",
868 "org.freedesktop.systemd1.Manager",
872 DBUS_TYPE_STRING, &name,
873 DBUS_TYPE_STRING, &mode,
882 static int manager_reserve_vt(Manager *m) {
883 _cleanup_free_ char *p = NULL;
887 if (m->reserve_vt <= 0)
890 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
893 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
894 if (m->reserve_vt_fd < 0) {
896 /* Don't complain on VT-less systems */
898 log_warning("Failed to pin reserved VT: %m");
905 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
906 _cleanup_free_ char *unit = NULL;
914 r = cg_pid_get_unit(pid, &unit);
918 s = hashmap_get(m->session_units, unit);
926 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
927 _cleanup_free_ char *unit = NULL;
935 r = cg_pid_get_slice(pid, &unit);
939 u = hashmap_get(m->user_units, unit);
947 static void manager_dispatch_other(Manager *m, int fd) {
955 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
957 assert(s->fifo_fd == fd);
958 session_remove_fifo(s);
963 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
965 assert(i->fifo_fd == fd);
971 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
978 assert_not_reached("Got event for unknown fd");
981 static int manager_connect_bus(Manager *m) {
984 struct epoll_event ev = {
991 assert(m->bus_fd < 0);
993 dbus_error_init(&error);
995 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
997 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1002 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1003 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1004 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1005 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1006 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1011 dbus_bus_add_match(m->bus,
1013 "sender='org.freedesktop.systemd1',"
1014 "interface='org.freedesktop.systemd1.Manager',"
1015 "member='JobRemoved',"
1016 "path='/org/freedesktop/systemd1'",
1018 if (dbus_error_is_set(&error)) {
1019 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
1020 dbus_error_free(&error);
1023 dbus_bus_add_match(m->bus,
1025 "sender='org.freedesktop.systemd1',"
1026 "interface='org.freedesktop.DBus.Properties',"
1027 "member='PropertiesChanged'",
1030 if (dbus_error_is_set(&error)) {
1031 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
1032 dbus_error_free(&error);
1035 r = bus_method_call_with_reply(
1037 "org.freedesktop.systemd1",
1038 "/org/freedesktop/systemd1",
1039 "org.freedesktop.systemd1.Manager",
1045 log_error("Failed to enable subscription: %s", bus_error(&error, r));
1046 dbus_error_free(&error);
1049 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1050 if (dbus_error_is_set(&error)) {
1051 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1056 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1057 log_error("Failed to acquire name.");
1062 m->bus_fd = bus_loop_open(m->bus);
1063 if (m->bus_fd < 0) {
1068 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1074 dbus_error_free(&error);
1079 static int manager_connect_console(Manager *m) {
1080 struct epoll_event ev = {
1082 .data.u32 = FD_CONSOLE,
1086 assert(m->console_active_fd < 0);
1088 /* On certain architectures (S390 and Xen, and containers),
1089 /dev/tty0 does not exist, so don't fail if we can't open
1091 if (access("/dev/tty0", F_OK) < 0) {
1092 m->console_active_fd = -1;
1096 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1097 if (m->console_active_fd < 0) {
1099 /* On some systems the device node /dev/tty0 may exist
1100 * even though /sys/class/tty/tty0 does not. */
1101 if (errno == ENOENT)
1104 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1108 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1114 static int manager_connect_udev(Manager *m) {
1116 struct epoll_event ev = {
1118 .data.u32 = FD_SEAT_UDEV,
1122 assert(!m->udev_seat_monitor);
1123 assert(!m->udev_vcsa_monitor);
1124 assert(!m->udev_button_monitor);
1126 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1127 if (!m->udev_seat_monitor)
1130 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1134 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1138 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1140 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1143 /* Don't watch keys if nobody cares */
1144 if (m->handle_power_key != HANDLE_IGNORE ||
1145 m->handle_suspend_key != HANDLE_IGNORE ||
1146 m->handle_hibernate_key != HANDLE_IGNORE ||
1147 m->handle_lid_switch != HANDLE_IGNORE) {
1149 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1150 if (!m->udev_button_monitor)
1153 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1157 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1161 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1165 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1168 ev.events = EPOLLIN;
1169 ev.data.u32 = FD_BUTTON_UDEV;
1170 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1174 /* Don't bother watching VCSA devices, if nobody cares */
1175 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1177 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1178 if (!m->udev_vcsa_monitor)
1181 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1185 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1189 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1192 ev.events = EPOLLIN;
1193 ev.data.u32 = FD_VCSA_UDEV;
1194 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1201 void manager_gc(Manager *m, bool drop_not_started) {
1208 while ((seat = m->seat_gc_queue)) {
1209 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1210 seat->in_gc_queue = false;
1212 if (seat_check_gc(seat, drop_not_started) == 0) {
1218 while ((session = m->session_gc_queue)) {
1219 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1220 session->in_gc_queue = false;
1222 if (session_check_gc(session, drop_not_started) == 0) {
1223 session_stop(session);
1224 session_free(session);
1228 while ((user = m->user_gc_queue)) {
1229 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1230 user->in_gc_queue = false;
1232 if (user_check_gc(user, drop_not_started) == 0) {
1239 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1242 dual_timestamp ts = { 0, 0 };
1247 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1249 HASHMAP_FOREACH(s, m->sessions, i) {
1253 ih = session_get_idle_hint(s, &k);
1259 if (k.monotonic < ts.monotonic)
1265 } else if (idle_hint) {
1267 if (k.monotonic > ts.monotonic)
1278 int manager_dispatch_idle_action(Manager *m) {
1279 struct dual_timestamp since;
1280 struct itimerspec its = {};
1286 if (m->idle_action == HANDLE_IGNORE ||
1287 m->idle_action_usec <= 0) {
1292 n = now(CLOCK_MONOTONIC);
1294 r = manager_get_idle_hint(m, &since);
1296 /* Not idle. Let's check if after a timeout it might be idle then. */
1297 timespec_store(&its.it_value, n + m->idle_action_usec);
1299 /* Idle! Let's see if it's time to do something, or if
1300 * we shall sleep for longer. */
1302 if (n >= since.monotonic + m->idle_action_usec &&
1303 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1304 log_info("System idle. Taking action.");
1306 manager_handle_action(m, 0, m->idle_action, false, false);
1307 m->idle_action_not_before_usec = n;
1310 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1313 if (m->idle_action_fd < 0) {
1314 struct epoll_event ev = {
1316 .data.u32 = FD_IDLE_ACTION,
1319 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1320 if (m->idle_action_fd < 0) {
1321 log_error("Failed to create idle action timer: %m");
1326 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1327 log_error("Failed to add idle action timer to epoll: %m");
1333 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1334 log_error("Failed to reset timerfd: %m");
1342 if (m->idle_action_fd >= 0) {
1343 close_nointr_nofail(m->idle_action_fd);
1344 m->idle_action_fd = -1;
1349 int manager_startup(Manager *m) {
1354 Inhibitor *inhibitor;
1358 assert(m->epoll_fd <= 0);
1360 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1361 if (m->epoll_fd < 0)
1364 /* Connect to console */
1365 r = manager_connect_console(m);
1369 /* Connect to udev */
1370 r = manager_connect_udev(m);
1374 /* Connect to the bus */
1375 r = manager_connect_bus(m);
1379 /* Instantiate magic seat 0 */
1380 r = manager_add_seat(m, "seat0", &m->vtconsole);
1384 /* Deserialize state */
1385 manager_enumerate_devices(m);
1386 manager_enumerate_seats(m);
1387 manager_enumerate_users(m);
1388 manager_enumerate_sessions(m);
1389 manager_enumerate_inhibitors(m);
1390 manager_enumerate_buttons(m);
1392 /* Remove stale objects before we start them */
1393 manager_gc(m, false);
1395 /* Reserve the special reserved VT */
1396 manager_reserve_vt(m);
1398 /* And start everything */
1399 HASHMAP_FOREACH(seat, m->seats, i)
1402 HASHMAP_FOREACH(user, m->users, i)
1405 HASHMAP_FOREACH(session, m->sessions, i)
1406 session_start(session);
1408 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1409 inhibitor_start(inhibitor);
1411 manager_dispatch_idle_action(m);
1416 static int manager_recheck_buttons(Manager *m) {
1423 HASHMAP_FOREACH(b, m->buttons, i) {
1426 q = button_recheck(b);
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 (manager_recheck_buttons(m) > 0)
1452 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1455 manager_gc(m, true);
1457 if (m->action_what != 0 && !m->action_job) {
1460 x = now(CLOCK_MONOTONIC);
1461 y = m->action_timestamp + m->inhibit_delay_max;
1463 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1466 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1468 if (errno == EINTR || errno == EAGAIN)
1471 log_error("epoll() failed: %m");
1478 switch (event.data.u32) {
1481 manager_dispatch_seat_udev(m);
1485 manager_dispatch_vcsa_udev(m);
1488 case FD_BUTTON_UDEV:
1489 manager_dispatch_button_udev(m);
1493 manager_dispatch_console(m);
1496 case FD_IDLE_ACTION:
1497 manager_dispatch_idle_action(m);
1501 bus_loop_dispatch(m->bus_fd);
1505 if (event.data.u32 >= FD_OTHER_BASE)
1506 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1513 static int manager_parse_config_file(Manager *m) {
1514 static const char fn[] = "/etc/systemd/logind.conf";
1515 _cleanup_fclose_ FILE *f = NULL;
1520 f = fopen(fn, "re");
1522 if (errno == ENOENT)
1525 log_warning("Failed to open configuration file %s: %m", fn);
1529 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1530 (void*) logind_gperf_lookup, false, false, m);
1532 log_warning("Failed to parse configuration file: %s", strerror(-r));
1537 int main(int argc, char *argv[]) {
1541 log_set_target(LOG_TARGET_AUTO);
1542 log_set_facility(LOG_AUTH);
1543 log_parse_environment();
1549 log_error("This program takes no arguments.");
1554 /* Always create the directories people can create inotify
1555 * watches in. Note that some applications might check for the
1556 * existence of /run/systemd/seats/ to determine whether
1557 * logind is available, so please always make sure this check
1559 mkdir_label("/run/systemd/seats", 0755);
1560 mkdir_label("/run/systemd/users", 0755);
1561 mkdir_label("/run/systemd/sessions", 0755);
1569 manager_parse_config_file(m);
1571 r = manager_startup(m);
1573 log_error("Failed to fully start up daemon: %s", strerror(-r));
1577 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1581 "STATUS=Processing requests...");
1585 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1589 "STATUS=Shutting down...");
1594 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;