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_cgroups = hashmap_new(string_hash_func, string_compare_func);
80 m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
81 m->machine_cgroups = 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_cgroups || !m->session_cgroups || !m->machine_cgroups ||
89 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
94 m->reset_controllers = strv_new("cpu", NULL);
95 m->kill_exclude_users = strv_new("root", NULL);
96 if (!m->reset_controllers || !m->kill_exclude_users) {
101 m->udev = udev_new();
107 if (cg_get_root_path(&m->cgroup_root) < 0) {
112 if (streq(m->cgroup_root, "/"))
113 m->cgroup_root[0] = 0;
118 void manager_free(Manager *m) {
129 while ((session = hashmap_first(m->sessions)))
130 session_free(session);
132 while ((u = hashmap_first(m->users)))
135 while ((d = hashmap_first(m->devices)))
138 while ((s = hashmap_first(m->seats)))
141 while ((i = hashmap_first(m->inhibitors)))
144 while ((b = hashmap_first(m->buttons)))
147 while ((machine = hashmap_first(m->machines)))
148 machine_free(machine);
150 hashmap_free(m->devices);
151 hashmap_free(m->seats);
152 hashmap_free(m->sessions);
153 hashmap_free(m->users);
154 hashmap_free(m->inhibitors);
155 hashmap_free(m->buttons);
156 hashmap_free(m->machines);
158 hashmap_free(m->user_cgroups);
159 hashmap_free(m->session_cgroups);
160 hashmap_free(m->machine_cgroups);
162 hashmap_free(m->session_fds);
163 hashmap_free(m->inhibitor_fds);
164 hashmap_free(m->button_fds);
166 if (m->console_active_fd >= 0)
167 close_nointr_nofail(m->console_active_fd);
169 if (m->udev_seat_monitor)
170 udev_monitor_unref(m->udev_seat_monitor);
171 if (m->udev_vcsa_monitor)
172 udev_monitor_unref(m->udev_vcsa_monitor);
173 if (m->udev_button_monitor)
174 udev_monitor_unref(m->udev_button_monitor);
180 dbus_connection_flush(m->bus);
181 dbus_connection_close(m->bus);
182 dbus_connection_unref(m->bus);
186 close_nointr_nofail(m->bus_fd);
188 if (m->epoll_fd >= 0)
189 close_nointr_nofail(m->epoll_fd);
191 if (m->reserve_vt_fd >= 0)
192 close_nointr_nofail(m->reserve_vt_fd);
194 if (m->idle_action_fd >= 0)
195 close_nointr_nofail(m->idle_action_fd);
197 strv_free(m->controllers);
198 strv_free(m->reset_controllers);
199 strv_free(m->kill_only_users);
200 strv_free(m->kill_exclude_users);
204 free(m->cgroup_root);
208 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
214 d = hashmap_get(m->devices, sysfs);
222 d = device_new(m, sysfs);
232 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
238 s = hashmap_get(m->seats, id);
256 int manager_add_session(Manager *m, const char *id, Session **_session) {
262 s = hashmap_get(m->sessions, id);
270 s = session_new(m, id);
280 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
286 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
294 u = user_new(m, uid, gid, name);
304 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
312 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
316 return manager_add_user(m, uid, gid, name, _user);
319 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
327 return errno ? -errno : -ENOENT;
329 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
332 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
338 i = hashmap_get(m->inhibitors, id);
346 i = inhibitor_new(m, id);
356 int manager_add_button(Manager *m, const char *name, Button **_button) {
362 b = hashmap_get(m->buttons, name);
370 b = button_new(m, name);
380 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
386 machine = hashmap_get(m->machines, name);
394 machine = machine_new(m, name);
404 int manager_process_seat_device(Manager *m, struct udev_device *d) {
410 if (streq_ptr(udev_device_get_action(d), "remove")) {
412 device = hashmap_get(m->devices, udev_device_get_syspath(d));
416 seat_add_to_gc_queue(device->seat);
423 sn = udev_device_get_property_value(d, "ID_SEAT");
427 if (!seat_name_is_valid(sn)) {
428 log_warning("Device with invalid seat name %s found, ignoring.", sn);
432 r = manager_add_device(m, udev_device_get_syspath(d), &device);
436 r = manager_add_seat(m, sn, &seat);
444 device_attach(device, seat);
451 int manager_process_button_device(Manager *m, struct udev_device *d) {
458 if (streq_ptr(udev_device_get_action(d), "remove")) {
460 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
469 r = manager_add_button(m, udev_device_get_sysname(d), &b);
473 sn = udev_device_get_property_value(d, "ID_SEAT");
477 button_set_seat(b, sn);
484 int manager_enumerate_devices(Manager *m) {
485 struct udev_list_entry *item = NULL, *first = NULL;
486 struct udev_enumerate *e;
491 /* Loads devices from udev and creates seats for them as
494 e = udev_enumerate_new(m->udev);
500 r = udev_enumerate_add_match_tag(e, "master-of-seat");
504 r = udev_enumerate_scan_devices(e);
508 first = udev_enumerate_get_list_entry(e);
509 udev_list_entry_foreach(item, first) {
510 struct udev_device *d;
513 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
519 k = manager_process_seat_device(m, d);
520 udev_device_unref(d);
528 udev_enumerate_unref(e);
533 int manager_enumerate_buttons(Manager *m) {
534 struct udev_list_entry *item = NULL, *first = NULL;
535 struct udev_enumerate *e;
540 /* Loads buttons from udev */
542 if (m->handle_power_key == HANDLE_IGNORE &&
543 m->handle_suspend_key == HANDLE_IGNORE &&
544 m->handle_hibernate_key == HANDLE_IGNORE &&
545 m->handle_lid_switch == HANDLE_IGNORE)
548 e = udev_enumerate_new(m->udev);
554 r = udev_enumerate_add_match_subsystem(e, "input");
558 r = udev_enumerate_add_match_tag(e, "power-switch");
562 r = udev_enumerate_scan_devices(e);
566 first = udev_enumerate_get_list_entry(e);
567 udev_list_entry_foreach(item, first) {
568 struct udev_device *d;
571 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
577 k = manager_process_button_device(m, d);
578 udev_device_unref(d);
586 udev_enumerate_unref(e);
591 int manager_enumerate_seats(Manager *m) {
592 _cleanup_closedir_ DIR *d = NULL;
598 /* This loads data about seats stored on disk, but does not
599 * actually create any seats. Removes data of seats that no
602 d = opendir("/run/systemd/seats");
607 log_error("Failed to open /run/systemd/seats: %m");
611 FOREACH_DIRENT(de, d, return -errno) {
615 if (!dirent_is_file(de))
618 s = hashmap_get(m->seats, de->d_name);
620 unlinkat(dirfd(d), de->d_name, 0);
632 static int manager_enumerate_linger_users(Manager *m) {
633 _cleanup_closedir_ DIR *d = NULL;
639 d = opendir("/var/lib/systemd/linger");
644 log_error("Failed to open /var/lib/systemd/linger/: %m");
648 FOREACH_DIRENT(de, d, return -errno) {
651 if (!dirent_is_file(de))
654 k = manager_add_user_by_name(m, de->d_name, NULL);
656 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
664 int manager_enumerate_users(Manager *m) {
665 _cleanup_closedir_ DIR *d = NULL;
671 /* Add lingering users */
672 k = manager_enumerate_linger_users(m);
676 /* Read in user data stored on disk */
677 d = opendir("/run/systemd/users");
682 log_error("Failed to open /run/systemd/users: %m");
686 FOREACH_DIRENT(de, d, return -errno) {
689 if (!dirent_is_file(de))
692 k = manager_add_user_by_name(m, de->d_name, &u);
694 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
700 user_add_to_gc_queue(u);
710 int manager_enumerate_sessions(Manager *m) {
711 _cleanup_closedir_ DIR *d = NULL;
717 /* Read in session data stored on disk */
718 d = opendir("/run/systemd/sessions");
723 log_error("Failed to open /run/systemd/sessions: %m");
727 FOREACH_DIRENT(de, d, return -errno) {
731 if (!dirent_is_file(de))
734 k = manager_add_session(m, de->d_name, &s);
736 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
742 session_add_to_gc_queue(s);
752 int manager_enumerate_inhibitors(Manager *m) {
753 _cleanup_closedir_ DIR *d = NULL;
759 d = opendir("/run/systemd/inhibit");
764 log_error("Failed to open /run/systemd/inhibit: %m");
768 FOREACH_DIRENT(de, d, return -errno) {
772 if (!dirent_is_file(de))
775 k = manager_add_inhibitor(m, de->d_name, &i);
777 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
782 k = inhibitor_load(i);
790 int manager_enumerate_machines(Manager *m) {
791 _cleanup_closedir_ DIR *d = NULL;
797 /* Read in machine data stored on disk */
798 d = opendir("/run/systemd/machines");
803 log_error("Failed to open /run/systemd/machines: %m");
807 FOREACH_DIRENT(de, d, return -errno) {
808 struct Machine *machine;
811 if (!dirent_is_file(de))
814 k = manager_add_machine(m, de->d_name, &machine);
816 log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
822 machine_add_to_gc_queue(machine);
824 k = machine_load(machine);
832 int manager_dispatch_seat_udev(Manager *m) {
833 struct udev_device *d;
838 d = udev_monitor_receive_device(m->udev_seat_monitor);
842 r = manager_process_seat_device(m, d);
843 udev_device_unref(d);
848 int manager_dispatch_vcsa_udev(Manager *m) {
849 struct udev_device *d;
855 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
859 name = udev_device_get_sysname(d);
861 /* Whenever a VCSA device is removed try to reallocate our
862 * VTs, to make sure our auto VTs never go away. */
864 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
865 r = seat_preallocate_vts(m->vtconsole);
867 udev_device_unref(d);
872 int manager_dispatch_button_udev(Manager *m) {
873 struct udev_device *d;
878 d = udev_monitor_receive_device(m->udev_button_monitor);
882 r = manager_process_button_device(m, d);
883 udev_device_unref(d);
888 int manager_dispatch_console(Manager *m) {
892 seat_read_active_vt(m->vtconsole);
897 static int vt_is_busy(int vtnr) {
898 struct vt_stat vt_stat;
903 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
904 * we'd open the latter we'd open the foreground tty which
905 * hence would be unconditionally busy. By opening /dev/tty1
906 * we avoid this. Since tty1 is special and needs to be an
907 * explicitly loaded getty or DM this is safe. */
909 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
913 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
916 r = !!(vt_stat.v_state & (1 << vtnr));
918 close_nointr_nofail(fd);
923 int manager_spawn_autovt(Manager *m, int vtnr) {
926 const char *mode = "fail";
931 if ((unsigned) vtnr > m->n_autovts &&
932 (unsigned) vtnr != m->reserve_vt)
935 if ((unsigned) vtnr != m->reserve_vt) {
936 /* If this is the reserved TTY, we'll start the getty
937 * on it in any case, but otherwise only if it is not
940 r = vt_is_busy(vtnr);
947 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
948 log_error("Could not allocate service name.");
953 r = bus_method_call_with_reply (
955 "org.freedesktop.systemd1",
956 "/org/freedesktop/systemd1",
957 "org.freedesktop.systemd1.Manager",
961 DBUS_TYPE_STRING, &name,
962 DBUS_TYPE_STRING, &mode,
971 static int manager_reserve_vt(Manager *m) {
972 _cleanup_free_ char *p = NULL;
976 if (m->reserve_vt <= 0)
979 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
982 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
983 if (m->reserve_vt_fd < 0) {
985 /* Don't complain on VT-less systems */
987 log_warning("Failed to pin reserved VT: %m");
994 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1002 s = hashmap_get(m->session_cgroups, cgroup);
1008 p = strdupa(cgroup);
1013 e = strrchr(p, '/');
1021 s = hashmap_get(m->session_cgroups, p);
1029 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1037 u = hashmap_get(m->user_cgroups, cgroup);
1043 p = strdupa(cgroup);
1050 e = strrchr(p, '/');
1058 u = hashmap_get(m->user_cgroups, p);
1066 int manager_get_machine_by_cgroup(Manager *m, const char *cgroup, Machine **machine) {
1074 u = hashmap_get(m->machine_cgroups, cgroup);
1080 p = strdupa(cgroup);
1087 e = strrchr(p, '/');
1095 u = hashmap_get(m->machine_cgroups, p);
1103 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1104 _cleanup_free_ char *p = NULL;
1111 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1115 return manager_get_session_by_cgroup(m, p, session);
1118 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
1119 _cleanup_free_ char *p = NULL;
1126 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1130 return manager_get_user_by_cgroup(m, p, user);
1133 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1134 _cleanup_free_ char *p = NULL;
1141 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1145 return manager_get_machine_by_cgroup(m, p, machine);
1148 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1154 r = manager_get_session_by_cgroup(m, cgroup, &s);
1156 session_add_to_gc_queue(s);
1158 r = manager_get_user_by_cgroup(m, cgroup, &u);
1160 user_add_to_gc_queue(u);
1162 r = manager_get_machine_by_cgroup(m, cgroup, &machine);
1164 machine_add_to_gc_queue(machine);
1167 static void manager_dispatch_other(Manager *m, int fd) {
1175 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1177 assert(s->fifo_fd == fd);
1178 session_remove_fifo(s);
1183 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1185 assert(i->fifo_fd == fd);
1191 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1193 assert(b->fd == fd);
1198 assert_not_reached("Got event for unknown fd");
1201 static int manager_connect_bus(Manager *m) {
1204 struct epoll_event ev = {
1211 assert(m->bus_fd < 0);
1213 dbus_error_init(&error);
1215 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1217 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1222 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1223 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1224 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1225 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1226 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/machine", &bus_machine_vtable, m) ||
1227 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1232 dbus_bus_add_match(m->bus,
1234 "interface='org.freedesktop.systemd1.Agent',"
1235 "member='Released',"
1236 "path='/org/freedesktop/systemd1/agent'",
1239 if (dbus_error_is_set(&error)) {
1240 log_error("Failed to register match: %s", bus_error_message(&error));
1245 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1246 if (dbus_error_is_set(&error)) {
1247 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1252 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1253 log_error("Failed to acquire name.");
1258 m->bus_fd = bus_loop_open(m->bus);
1259 if (m->bus_fd < 0) {
1264 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1270 dbus_error_free(&error);
1275 static int manager_connect_console(Manager *m) {
1276 struct epoll_event ev = {
1278 .data.u32 = FD_CONSOLE,
1282 assert(m->console_active_fd < 0);
1284 /* On certain architectures (S390 and Xen, and containers),
1285 /dev/tty0 does not exist, so don't fail if we can't open
1287 if (access("/dev/tty0", F_OK) < 0) {
1288 m->console_active_fd = -1;
1292 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1293 if (m->console_active_fd < 0) {
1295 /* On some systems the device node /dev/tty0 may exist
1296 * even though /sys/class/tty/tty0 does not. */
1297 if (errno == ENOENT)
1300 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1304 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1310 static int manager_connect_udev(Manager *m) {
1312 struct epoll_event ev = {
1314 .data.u32 = FD_SEAT_UDEV,
1318 assert(!m->udev_seat_monitor);
1319 assert(!m->udev_vcsa_monitor);
1320 assert(!m->udev_button_monitor);
1322 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1323 if (!m->udev_seat_monitor)
1326 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1330 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1334 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1336 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1339 /* Don't watch keys if nobody cares */
1340 if (m->handle_power_key != HANDLE_IGNORE ||
1341 m->handle_suspend_key != HANDLE_IGNORE ||
1342 m->handle_hibernate_key != HANDLE_IGNORE ||
1343 m->handle_lid_switch != HANDLE_IGNORE) {
1345 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1346 if (!m->udev_button_monitor)
1349 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1353 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1357 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1361 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1364 ev.events = EPOLLIN;
1365 ev.data.u32 = FD_BUTTON_UDEV;
1366 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1370 /* Don't bother watching VCSA devices, if nobody cares */
1371 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1373 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1374 if (!m->udev_vcsa_monitor)
1377 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1381 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1385 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1388 ev.events = EPOLLIN;
1389 ev.data.u32 = FD_VCSA_UDEV;
1390 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1397 void manager_gc(Manager *m, bool drop_not_started) {
1405 while ((seat = m->seat_gc_queue)) {
1406 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1407 seat->in_gc_queue = false;
1409 if (seat_check_gc(seat, drop_not_started) == 0) {
1415 while ((session = m->session_gc_queue)) {
1416 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1417 session->in_gc_queue = false;
1419 if (session_check_gc(session, drop_not_started) == 0) {
1420 session_stop(session);
1421 session_free(session);
1425 while ((user = m->user_gc_queue)) {
1426 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1427 user->in_gc_queue = false;
1429 if (user_check_gc(user, drop_not_started) == 0) {
1435 while ((machine = m->machine_gc_queue)) {
1436 LIST_REMOVE(Machine, gc_queue, m->machine_gc_queue, machine);
1437 machine->in_gc_queue = false;
1439 if (machine_check_gc(machine, drop_not_started) == 0) {
1440 machine_stop(machine);
1441 machine_free(machine);
1446 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1449 dual_timestamp ts = { 0, 0 };
1454 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1456 HASHMAP_FOREACH(s, m->sessions, i) {
1460 ih = session_get_idle_hint(s, &k);
1466 if (k.monotonic < ts.monotonic)
1472 } else if (idle_hint) {
1474 if (k.monotonic > ts.monotonic)
1485 int manager_dispatch_idle_action(Manager *m) {
1486 struct dual_timestamp since;
1487 struct itimerspec its = {};
1493 if (m->idle_action == HANDLE_IGNORE ||
1494 m->idle_action_usec <= 0) {
1499 n = now(CLOCK_MONOTONIC);
1501 r = manager_get_idle_hint(m, &since);
1503 /* Not idle. Let's check if after a timeout it might be idle then. */
1504 timespec_store(&its.it_value, n + m->idle_action_usec);
1506 /* Idle! Let's see if it's time to do something, or if
1507 * we shall sleep for longer. */
1509 if (n >= since.monotonic + m->idle_action_usec &&
1510 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1511 log_info("System idle. Taking action.");
1513 manager_handle_action(m, 0, m->idle_action, false, false);
1514 m->idle_action_not_before_usec = n;
1517 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1520 if (m->idle_action_fd < 0) {
1521 struct epoll_event ev = {
1523 .data.u32 = FD_IDLE_ACTION,
1526 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1527 if (m->idle_action_fd < 0) {
1528 log_error("Failed to create idle action timer: %m");
1533 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1534 log_error("Failed to add idle action timer to epoll: %m");
1540 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1541 log_error("Failed to reset timerfd: %m");
1549 if (m->idle_action_fd >= 0) {
1550 close_nointr_nofail(m->idle_action_fd);
1551 m->idle_action_fd = -1;
1556 int manager_startup(Manager *m) {
1561 Inhibitor *inhibitor;
1566 assert(m->epoll_fd <= 0);
1568 cg_shorten_controllers(m->reset_controllers);
1569 cg_shorten_controllers(m->controllers);
1571 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1572 if (m->epoll_fd < 0)
1575 /* Connect to console */
1576 r = manager_connect_console(m);
1580 /* Connect to udev */
1581 r = manager_connect_udev(m);
1585 /* Connect to the bus */
1586 r = manager_connect_bus(m);
1590 /* Instantiate magic seat 0 */
1591 r = manager_add_seat(m, "seat0", &m->vtconsole);
1595 /* Deserialize state */
1596 manager_enumerate_devices(m);
1597 manager_enumerate_seats(m);
1598 manager_enumerate_users(m);
1599 manager_enumerate_sessions(m);
1600 manager_enumerate_inhibitors(m);
1601 manager_enumerate_buttons(m);
1602 manager_enumerate_machines(m);
1604 /* Remove stale objects before we start them */
1605 manager_gc(m, false);
1607 /* Reserve the special reserved VT */
1608 manager_reserve_vt(m);
1610 /* And start everything */
1611 HASHMAP_FOREACH(seat, m->seats, i)
1614 HASHMAP_FOREACH(user, m->users, i)
1617 HASHMAP_FOREACH(session, m->sessions, i)
1618 session_start(session);
1620 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1621 inhibitor_start(inhibitor);
1623 HASHMAP_FOREACH(machine, m->machines, i)
1624 machine_start(machine);
1626 manager_dispatch_idle_action(m);
1631 static int manager_recheck_buttons(Manager *m) {
1638 HASHMAP_FOREACH(b, m->buttons, i) {
1641 q = button_recheck(b);
1651 int manager_run(Manager *m) {
1655 struct epoll_event event;
1659 manager_gc(m, true);
1661 if (manager_dispatch_delayed(m) > 0)
1664 if (manager_recheck_buttons(m) > 0)
1667 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1670 manager_gc(m, true);
1672 if (m->action_what != 0 && !m->action_job) {
1675 x = now(CLOCK_MONOTONIC);
1676 y = m->action_timestamp + m->inhibit_delay_max;
1678 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1681 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1683 if (errno == EINTR || errno == EAGAIN)
1686 log_error("epoll() failed: %m");
1693 switch (event.data.u32) {
1696 manager_dispatch_seat_udev(m);
1700 manager_dispatch_vcsa_udev(m);
1703 case FD_BUTTON_UDEV:
1704 manager_dispatch_button_udev(m);
1708 manager_dispatch_console(m);
1711 case FD_IDLE_ACTION:
1712 manager_dispatch_idle_action(m);
1716 bus_loop_dispatch(m->bus_fd);
1720 if (event.data.u32 >= FD_OTHER_BASE)
1721 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1728 static int manager_parse_config_file(Manager *m) {
1729 static const char fn[] = "/etc/systemd/logind.conf";
1730 _cleanup_fclose_ FILE *f = NULL;
1735 f = fopen(fn, "re");
1737 if (errno == ENOENT)
1740 log_warning("Failed to open configuration file %s: %m", fn);
1744 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1745 (void*) logind_gperf_lookup, false, false, m);
1747 log_warning("Failed to parse configuration file: %s", strerror(-r));
1752 int main(int argc, char *argv[]) {
1756 log_set_target(LOG_TARGET_AUTO);
1757 log_set_facility(LOG_AUTH);
1758 log_parse_environment();
1764 log_error("This program takes no arguments.");
1769 /* Always create the directories people can create inotify
1770 * watches in. Note that some applications might check for the
1771 * existence of /run/systemd/seats/ to determine whether
1772 * logind is available, so please always make sure this check
1774 mkdir_label("/run/systemd/seats", 0755);
1775 mkdir_label("/run/systemd/users", 0755);
1776 mkdir_label("/run/systemd/sessions", 0755);
1777 mkdir_label("/run/systemd/machines", 0755);
1785 manager_parse_config_file(m);
1787 r = manager_startup(m);
1789 log_error("Failed to fully start up daemon: %s", strerror(-r));
1793 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1797 "STATUS=Processing requests...");
1801 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1805 "STATUS=Shutting down...");
1810 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;