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);
77 m->machines = hashmap_new(string_hash_func, string_compare_func);
79 m->user_units = hashmap_new(string_hash_func, string_compare_func);
80 m->session_units = hashmap_new(string_hash_func, string_compare_func);
81 m->machine_units = hashmap_new(string_hash_func, string_compare_func);
83 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
84 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
85 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
87 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->machines ||
88 !m->user_units || !m->session_units || !m->machine_units ||
89 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
94 m->kill_exclude_users = strv_new("root", NULL);
95 if (!m->kill_exclude_users) {
100 m->udev = udev_new();
109 void manager_free(Manager *m) {
120 while ((session = hashmap_first(m->sessions)))
121 session_free(session);
123 while ((u = hashmap_first(m->users)))
126 while ((d = hashmap_first(m->devices)))
129 while ((s = hashmap_first(m->seats)))
132 while ((i = hashmap_first(m->inhibitors)))
135 while ((b = hashmap_first(m->buttons)))
138 while ((machine = hashmap_first(m->machines)))
139 machine_free(machine);
141 hashmap_free(m->devices);
142 hashmap_free(m->seats);
143 hashmap_free(m->sessions);
144 hashmap_free(m->users);
145 hashmap_free(m->inhibitors);
146 hashmap_free(m->buttons);
147 hashmap_free(m->machines);
149 hashmap_free(m->user_units);
150 hashmap_free(m->session_units);
151 hashmap_free(m->machine_units);
153 hashmap_free(m->session_fds);
154 hashmap_free(m->inhibitor_fds);
155 hashmap_free(m->button_fds);
157 if (m->console_active_fd >= 0)
158 close_nointr_nofail(m->console_active_fd);
160 if (m->udev_seat_monitor)
161 udev_monitor_unref(m->udev_seat_monitor);
162 if (m->udev_vcsa_monitor)
163 udev_monitor_unref(m->udev_vcsa_monitor);
164 if (m->udev_button_monitor)
165 udev_monitor_unref(m->udev_button_monitor);
171 dbus_connection_flush(m->bus);
172 dbus_connection_close(m->bus);
173 dbus_connection_unref(m->bus);
177 close_nointr_nofail(m->bus_fd);
179 if (m->epoll_fd >= 0)
180 close_nointr_nofail(m->epoll_fd);
182 if (m->reserve_vt_fd >= 0)
183 close_nointr_nofail(m->reserve_vt_fd);
185 if (m->idle_action_fd >= 0)
186 close_nointr_nofail(m->idle_action_fd);
188 strv_free(m->kill_only_users);
189 strv_free(m->kill_exclude_users);
195 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
201 d = hashmap_get(m->devices, sysfs);
209 d = device_new(m, sysfs);
219 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
225 s = hashmap_get(m->seats, id);
243 int manager_add_session(Manager *m, const char *id, Session **_session) {
249 s = hashmap_get(m->sessions, id);
257 s = session_new(m, id);
267 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
273 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
281 u = user_new(m, uid, gid, name);
291 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
299 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
303 return manager_add_user(m, uid, gid, name, _user);
306 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
314 return errno ? -errno : -ENOENT;
316 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
319 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
325 i = hashmap_get(m->inhibitors, id);
333 i = inhibitor_new(m, id);
343 int manager_add_button(Manager *m, const char *name, Button **_button) {
349 b = hashmap_get(m->buttons, name);
357 b = button_new(m, name);
367 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
373 machine = hashmap_get(m->machines, name);
381 machine = machine_new(m, name);
391 int manager_process_seat_device(Manager *m, struct udev_device *d) {
397 if (streq_ptr(udev_device_get_action(d), "remove")) {
399 device = hashmap_get(m->devices, udev_device_get_syspath(d));
403 seat_add_to_gc_queue(device->seat);
410 sn = udev_device_get_property_value(d, "ID_SEAT");
414 if (!seat_name_is_valid(sn)) {
415 log_warning("Device with invalid seat name %s found, ignoring.", sn);
419 r = manager_add_device(m, udev_device_get_syspath(d), &device);
423 r = manager_add_seat(m, sn, &seat);
431 device_attach(device, seat);
438 int manager_process_button_device(Manager *m, struct udev_device *d) {
445 if (streq_ptr(udev_device_get_action(d), "remove")) {
447 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
456 r = manager_add_button(m, udev_device_get_sysname(d), &b);
460 sn = udev_device_get_property_value(d, "ID_SEAT");
464 button_set_seat(b, sn);
471 int manager_enumerate_devices(Manager *m) {
472 struct udev_list_entry *item = NULL, *first = NULL;
473 struct udev_enumerate *e;
478 /* Loads devices from udev and creates seats for them as
481 e = udev_enumerate_new(m->udev);
487 r = udev_enumerate_add_match_tag(e, "master-of-seat");
491 r = udev_enumerate_scan_devices(e);
495 first = udev_enumerate_get_list_entry(e);
496 udev_list_entry_foreach(item, first) {
497 struct udev_device *d;
500 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
506 k = manager_process_seat_device(m, d);
507 udev_device_unref(d);
515 udev_enumerate_unref(e);
520 int manager_enumerate_buttons(Manager *m) {
521 struct udev_list_entry *item = NULL, *first = NULL;
522 struct udev_enumerate *e;
527 /* Loads buttons from udev */
529 if (m->handle_power_key == HANDLE_IGNORE &&
530 m->handle_suspend_key == HANDLE_IGNORE &&
531 m->handle_hibernate_key == HANDLE_IGNORE &&
532 m->handle_lid_switch == HANDLE_IGNORE)
535 e = udev_enumerate_new(m->udev);
541 r = udev_enumerate_add_match_subsystem(e, "input");
545 r = udev_enumerate_add_match_tag(e, "power-switch");
549 r = udev_enumerate_scan_devices(e);
553 first = udev_enumerate_get_list_entry(e);
554 udev_list_entry_foreach(item, first) {
555 struct udev_device *d;
558 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
564 k = manager_process_button_device(m, d);
565 udev_device_unref(d);
573 udev_enumerate_unref(e);
578 int manager_enumerate_seats(Manager *m) {
579 _cleanup_closedir_ DIR *d = NULL;
585 /* This loads data about seats stored on disk, but does not
586 * actually create any seats. Removes data of seats that no
589 d = opendir("/run/systemd/seats");
594 log_error("Failed to open /run/systemd/seats: %m");
598 FOREACH_DIRENT(de, d, return -errno) {
602 if (!dirent_is_file(de))
605 s = hashmap_get(m->seats, de->d_name);
607 unlinkat(dirfd(d), de->d_name, 0);
619 static int manager_enumerate_linger_users(Manager *m) {
620 _cleanup_closedir_ DIR *d = NULL;
626 d = opendir("/var/lib/systemd/linger");
631 log_error("Failed to open /var/lib/systemd/linger/: %m");
635 FOREACH_DIRENT(de, d, return -errno) {
638 if (!dirent_is_file(de))
641 k = manager_add_user_by_name(m, de->d_name, NULL);
643 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
651 int manager_enumerate_users(Manager *m) {
652 _cleanup_closedir_ DIR *d = NULL;
658 /* Add lingering users */
659 r = manager_enumerate_linger_users(m);
661 /* Read in user data stored on disk */
662 d = opendir("/run/systemd/users");
667 log_error("Failed to open /run/systemd/users: %m");
671 FOREACH_DIRENT(de, d, return -errno) {
674 if (!dirent_is_file(de))
677 k = manager_add_user_by_name(m, de->d_name, &u);
679 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
685 user_add_to_gc_queue(u);
695 int manager_enumerate_sessions(Manager *m) {
696 _cleanup_closedir_ DIR *d = NULL;
702 /* Read in session data stored on disk */
703 d = opendir("/run/systemd/sessions");
708 log_error("Failed to open /run/systemd/sessions: %m");
712 FOREACH_DIRENT(de, d, return -errno) {
716 if (!dirent_is_file(de))
719 k = manager_add_session(m, de->d_name, &s);
721 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
727 session_add_to_gc_queue(s);
737 int manager_enumerate_inhibitors(Manager *m) {
738 _cleanup_closedir_ DIR *d = NULL;
744 d = opendir("/run/systemd/inhibit");
749 log_error("Failed to open /run/systemd/inhibit: %m");
753 FOREACH_DIRENT(de, d, return -errno) {
757 if (!dirent_is_file(de))
760 k = manager_add_inhibitor(m, de->d_name, &i);
762 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
767 k = inhibitor_load(i);
775 int manager_enumerate_machines(Manager *m) {
776 _cleanup_closedir_ DIR *d = NULL;
782 /* Read in machine data stored on disk */
783 d = opendir("/run/systemd/machines");
788 log_error("Failed to open /run/systemd/machines: %m");
792 FOREACH_DIRENT(de, d, return -errno) {
793 struct Machine *machine;
796 if (!dirent_is_file(de))
799 k = manager_add_machine(m, de->d_name, &machine);
801 log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
807 machine_add_to_gc_queue(machine);
809 k = machine_load(machine);
817 int manager_dispatch_seat_udev(Manager *m) {
818 struct udev_device *d;
823 d = udev_monitor_receive_device(m->udev_seat_monitor);
827 r = manager_process_seat_device(m, d);
828 udev_device_unref(d);
833 int manager_dispatch_vcsa_udev(Manager *m) {
834 struct udev_device *d;
840 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
844 name = udev_device_get_sysname(d);
846 /* Whenever a VCSA device is removed try to reallocate our
847 * VTs, to make sure our auto VTs never go away. */
849 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
850 r = seat_preallocate_vts(m->vtconsole);
852 udev_device_unref(d);
857 int manager_dispatch_button_udev(Manager *m) {
858 struct udev_device *d;
863 d = udev_monitor_receive_device(m->udev_button_monitor);
867 r = manager_process_button_device(m, d);
868 udev_device_unref(d);
873 int manager_dispatch_console(Manager *m) {
877 seat_read_active_vt(m->vtconsole);
882 static int vt_is_busy(int vtnr) {
883 struct vt_stat vt_stat;
888 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
889 * we'd open the latter we'd open the foreground tty which
890 * hence would be unconditionally busy. By opening /dev/tty1
891 * we avoid this. Since tty1 is special and needs to be an
892 * explicitly loaded getty or DM this is safe. */
894 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
898 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
901 r = !!(vt_stat.v_state & (1 << vtnr));
903 close_nointr_nofail(fd);
908 int manager_spawn_autovt(Manager *m, int vtnr) {
911 const char *mode = "fail";
916 if ((unsigned) vtnr > m->n_autovts &&
917 (unsigned) vtnr != m->reserve_vt)
920 if ((unsigned) vtnr != m->reserve_vt) {
921 /* If this is the reserved TTY, we'll start the getty
922 * on it in any case, but otherwise only if it is not
925 r = vt_is_busy(vtnr);
932 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
933 log_error("Could not allocate service name.");
938 r = bus_method_call_with_reply (
940 "org.freedesktop.systemd1",
941 "/org/freedesktop/systemd1",
942 "org.freedesktop.systemd1.Manager",
946 DBUS_TYPE_STRING, &name,
947 DBUS_TYPE_STRING, &mode,
956 static int manager_reserve_vt(Manager *m) {
957 _cleanup_free_ char *p = NULL;
961 if (m->reserve_vt <= 0)
964 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
967 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
968 if (m->reserve_vt_fd < 0) {
970 /* Don't complain on VT-less systems */
972 log_warning("Failed to pin reserved VT: %m");
979 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
980 _cleanup_free_ char *unit = NULL;
988 r = cg_pid_get_unit(pid, &unit);
992 s = hashmap_get(m->session_units, unit);
1000 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
1001 _cleanup_free_ char *unit = NULL;
1009 r = cg_pid_get_slice(pid, &unit);
1013 u = hashmap_get(m->user_units, unit);
1021 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1022 _cleanup_free_ char *unit = NULL;
1030 r = cg_pid_get_unit(pid, &unit);
1034 mm = hashmap_get(m->machine_units, unit);
1042 static void manager_dispatch_other(Manager *m, int fd) {
1050 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1052 assert(s->fifo_fd == fd);
1053 session_remove_fifo(s);
1058 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1060 assert(i->fifo_fd == fd);
1066 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1068 assert(b->fd == fd);
1073 assert_not_reached("Got event for unknown fd");
1076 static int manager_connect_bus(Manager *m) {
1079 struct epoll_event ev = {
1086 assert(m->bus_fd < 0);
1088 dbus_error_init(&error);
1090 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1092 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1097 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1098 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1099 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1100 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1101 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/machine", &bus_machine_vtable, m) ||
1102 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1107 dbus_bus_add_match(m->bus,
1109 "sender='org.freedesktop.systemd1',"
1110 "interface='org.freedesktop.systemd1.Manager',"
1111 "member='JobRemoved',"
1112 "path='/org/freedesktop/systemd1'",
1114 if (dbus_error_is_set(&error)) {
1115 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
1116 dbus_error_free(&error);
1119 dbus_bus_add_match(m->bus,
1121 "sender='org.freedesktop.systemd1',"
1122 "interface='org.freedesktop.DBus.Properties',"
1123 "member='PropertiesChanged'",
1126 if (dbus_error_is_set(&error)) {
1127 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
1128 dbus_error_free(&error);
1131 r = bus_method_call_with_reply(
1133 "org.freedesktop.systemd1",
1134 "/org/freedesktop/systemd1",
1135 "org.freedesktop.systemd1.Manager",
1141 log_error("Failed to enable subscription: %s", bus_error(&error, r));
1142 dbus_error_free(&error);
1145 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1146 if (dbus_error_is_set(&error)) {
1147 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1152 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1153 log_error("Failed to acquire name.");
1158 m->bus_fd = bus_loop_open(m->bus);
1159 if (m->bus_fd < 0) {
1164 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1170 dbus_error_free(&error);
1175 static int manager_connect_console(Manager *m) {
1176 struct epoll_event ev = {
1178 .data.u32 = FD_CONSOLE,
1182 assert(m->console_active_fd < 0);
1184 /* On certain architectures (S390 and Xen, and containers),
1185 /dev/tty0 does not exist, so don't fail if we can't open
1187 if (access("/dev/tty0", F_OK) < 0) {
1188 m->console_active_fd = -1;
1192 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1193 if (m->console_active_fd < 0) {
1195 /* On some systems the device node /dev/tty0 may exist
1196 * even though /sys/class/tty/tty0 does not. */
1197 if (errno == ENOENT)
1200 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1204 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1210 static int manager_connect_udev(Manager *m) {
1212 struct epoll_event ev = {
1214 .data.u32 = FD_SEAT_UDEV,
1218 assert(!m->udev_seat_monitor);
1219 assert(!m->udev_vcsa_monitor);
1220 assert(!m->udev_button_monitor);
1222 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1223 if (!m->udev_seat_monitor)
1226 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1230 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1234 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1236 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1239 /* Don't watch keys if nobody cares */
1240 if (m->handle_power_key != HANDLE_IGNORE ||
1241 m->handle_suspend_key != HANDLE_IGNORE ||
1242 m->handle_hibernate_key != HANDLE_IGNORE ||
1243 m->handle_lid_switch != HANDLE_IGNORE) {
1245 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1246 if (!m->udev_button_monitor)
1249 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1253 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1257 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1261 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1264 ev.events = EPOLLIN;
1265 ev.data.u32 = FD_BUTTON_UDEV;
1266 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1270 /* Don't bother watching VCSA devices, if nobody cares */
1271 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1273 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1274 if (!m->udev_vcsa_monitor)
1277 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1281 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1285 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1288 ev.events = EPOLLIN;
1289 ev.data.u32 = FD_VCSA_UDEV;
1290 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1297 void manager_gc(Manager *m, bool drop_not_started) {
1305 while ((seat = m->seat_gc_queue)) {
1306 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1307 seat->in_gc_queue = false;
1309 if (seat_check_gc(seat, drop_not_started) == 0) {
1315 while ((session = m->session_gc_queue)) {
1316 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1317 session->in_gc_queue = false;
1319 if (session_check_gc(session, drop_not_started) == 0) {
1320 session_stop(session);
1321 session_free(session);
1325 while ((user = m->user_gc_queue)) {
1326 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1327 user->in_gc_queue = false;
1329 if (user_check_gc(user, drop_not_started) == 0) {
1335 while ((machine = m->machine_gc_queue)) {
1336 LIST_REMOVE(Machine, gc_queue, m->machine_gc_queue, machine);
1337 machine->in_gc_queue = false;
1339 if (machine_check_gc(machine, drop_not_started) == 0) {
1340 machine_stop(machine);
1341 machine_free(machine);
1346 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1349 dual_timestamp ts = { 0, 0 };
1354 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1356 HASHMAP_FOREACH(s, m->sessions, i) {
1360 ih = session_get_idle_hint(s, &k);
1366 if (k.monotonic < ts.monotonic)
1372 } else if (idle_hint) {
1374 if (k.monotonic > ts.monotonic)
1385 int manager_dispatch_idle_action(Manager *m) {
1386 struct dual_timestamp since;
1387 struct itimerspec its = {};
1393 if (m->idle_action == HANDLE_IGNORE ||
1394 m->idle_action_usec <= 0) {
1399 n = now(CLOCK_MONOTONIC);
1401 r = manager_get_idle_hint(m, &since);
1403 /* Not idle. Let's check if after a timeout it might be idle then. */
1404 timespec_store(&its.it_value, n + m->idle_action_usec);
1406 /* Idle! Let's see if it's time to do something, or if
1407 * we shall sleep for longer. */
1409 if (n >= since.monotonic + m->idle_action_usec &&
1410 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1411 log_info("System idle. Taking action.");
1413 manager_handle_action(m, 0, m->idle_action, false, false);
1414 m->idle_action_not_before_usec = n;
1417 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1420 if (m->idle_action_fd < 0) {
1421 struct epoll_event ev = {
1423 .data.u32 = FD_IDLE_ACTION,
1426 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1427 if (m->idle_action_fd < 0) {
1428 log_error("Failed to create idle action timer: %m");
1433 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1434 log_error("Failed to add idle action timer to epoll: %m");
1440 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1441 log_error("Failed to reset timerfd: %m");
1449 if (m->idle_action_fd >= 0) {
1450 close_nointr_nofail(m->idle_action_fd);
1451 m->idle_action_fd = -1;
1456 int manager_startup(Manager *m) {
1461 Inhibitor *inhibitor;
1466 assert(m->epoll_fd <= 0);
1468 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1469 if (m->epoll_fd < 0)
1472 /* Connect to console */
1473 r = manager_connect_console(m);
1477 /* Connect to udev */
1478 r = manager_connect_udev(m);
1482 /* Connect to the bus */
1483 r = manager_connect_bus(m);
1487 /* Instantiate magic seat 0 */
1488 r = manager_add_seat(m, "seat0", &m->vtconsole);
1492 /* Deserialize state */
1493 manager_enumerate_devices(m);
1494 manager_enumerate_seats(m);
1495 manager_enumerate_users(m);
1496 manager_enumerate_sessions(m);
1497 manager_enumerate_inhibitors(m);
1498 manager_enumerate_buttons(m);
1499 manager_enumerate_machines(m);
1501 /* Remove stale objects before we start them */
1502 manager_gc(m, false);
1504 /* Reserve the special reserved VT */
1505 manager_reserve_vt(m);
1507 /* And start everything */
1508 HASHMAP_FOREACH(seat, m->seats, i)
1511 HASHMAP_FOREACH(user, m->users, i)
1514 HASHMAP_FOREACH(session, m->sessions, i)
1515 session_start(session);
1517 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1518 inhibitor_start(inhibitor);
1520 HASHMAP_FOREACH(machine, m->machines, i)
1521 machine_start(machine);
1523 manager_dispatch_idle_action(m);
1528 static int manager_recheck_buttons(Manager *m) {
1535 HASHMAP_FOREACH(b, m->buttons, i) {
1538 q = button_recheck(b);
1548 int manager_run(Manager *m) {
1552 struct epoll_event event;
1556 manager_gc(m, true);
1558 if (manager_dispatch_delayed(m) > 0)
1561 if (manager_recheck_buttons(m) > 0)
1564 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1567 manager_gc(m, true);
1569 if (m->action_what != 0 && !m->action_job) {
1572 x = now(CLOCK_MONOTONIC);
1573 y = m->action_timestamp + m->inhibit_delay_max;
1575 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1578 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1580 if (errno == EINTR || errno == EAGAIN)
1583 log_error("epoll() failed: %m");
1590 switch (event.data.u32) {
1593 manager_dispatch_seat_udev(m);
1597 manager_dispatch_vcsa_udev(m);
1600 case FD_BUTTON_UDEV:
1601 manager_dispatch_button_udev(m);
1605 manager_dispatch_console(m);
1608 case FD_IDLE_ACTION:
1609 manager_dispatch_idle_action(m);
1613 bus_loop_dispatch(m->bus_fd);
1617 if (event.data.u32 >= FD_OTHER_BASE)
1618 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1625 static int manager_parse_config_file(Manager *m) {
1626 static const char fn[] = "/etc/systemd/logind.conf";
1627 _cleanup_fclose_ FILE *f = NULL;
1632 f = fopen(fn, "re");
1634 if (errno == ENOENT)
1637 log_warning("Failed to open configuration file %s: %m", fn);
1641 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1642 (void*) logind_gperf_lookup, false, false, m);
1644 log_warning("Failed to parse configuration file: %s", strerror(-r));
1649 int main(int argc, char *argv[]) {
1653 log_set_target(LOG_TARGET_AUTO);
1654 log_set_facility(LOG_AUTH);
1655 log_parse_environment();
1661 log_error("This program takes no arguments.");
1666 /* Always create the directories people can create inotify
1667 * watches in. Note that some applications might check for the
1668 * existence of /run/systemd/seats/ to determine whether
1669 * logind is available, so please always make sure this check
1671 mkdir_label("/run/systemd/seats", 0755);
1672 mkdir_label("/run/systemd/users", 0755);
1673 mkdir_label("/run/systemd/sessions", 0755);
1674 mkdir_label("/run/systemd/machines", 0755);
1682 manager_parse_config_file(m);
1684 r = manager_startup(m);
1686 log_error("Failed to fully start up daemon: %s", strerror(-r));
1690 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1694 "STATUS=Processing requests...");
1698 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1702 "STATUS=Shutting down...");
1707 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;