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 r = manager_enumerate_linger_users(m);
674 /* Read in user data stored on disk */
675 d = opendir("/run/systemd/users");
680 log_error("Failed to open /run/systemd/users: %m");
684 FOREACH_DIRENT(de, d, return -errno) {
687 if (!dirent_is_file(de))
690 k = manager_add_user_by_name(m, de->d_name, &u);
692 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
698 user_add_to_gc_queue(u);
708 int manager_enumerate_sessions(Manager *m) {
709 _cleanup_closedir_ DIR *d = NULL;
715 /* Read in session data stored on disk */
716 d = opendir("/run/systemd/sessions");
721 log_error("Failed to open /run/systemd/sessions: %m");
725 FOREACH_DIRENT(de, d, return -errno) {
729 if (!dirent_is_file(de))
732 k = manager_add_session(m, de->d_name, &s);
734 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
740 session_add_to_gc_queue(s);
750 int manager_enumerate_inhibitors(Manager *m) {
751 _cleanup_closedir_ DIR *d = NULL;
757 d = opendir("/run/systemd/inhibit");
762 log_error("Failed to open /run/systemd/inhibit: %m");
766 FOREACH_DIRENT(de, d, return -errno) {
770 if (!dirent_is_file(de))
773 k = manager_add_inhibitor(m, de->d_name, &i);
775 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
780 k = inhibitor_load(i);
788 int manager_enumerate_machines(Manager *m) {
789 _cleanup_closedir_ DIR *d = NULL;
795 /* Read in machine data stored on disk */
796 d = opendir("/run/systemd/machines");
801 log_error("Failed to open /run/systemd/machines: %m");
805 FOREACH_DIRENT(de, d, return -errno) {
806 struct Machine *machine;
809 if (!dirent_is_file(de))
812 k = manager_add_machine(m, de->d_name, &machine);
814 log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
820 machine_add_to_gc_queue(machine);
822 k = machine_load(machine);
830 int manager_dispatch_seat_udev(Manager *m) {
831 struct udev_device *d;
836 d = udev_monitor_receive_device(m->udev_seat_monitor);
840 r = manager_process_seat_device(m, d);
841 udev_device_unref(d);
846 int manager_dispatch_vcsa_udev(Manager *m) {
847 struct udev_device *d;
853 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
857 name = udev_device_get_sysname(d);
859 /* Whenever a VCSA device is removed try to reallocate our
860 * VTs, to make sure our auto VTs never go away. */
862 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
863 r = seat_preallocate_vts(m->vtconsole);
865 udev_device_unref(d);
870 int manager_dispatch_button_udev(Manager *m) {
871 struct udev_device *d;
876 d = udev_monitor_receive_device(m->udev_button_monitor);
880 r = manager_process_button_device(m, d);
881 udev_device_unref(d);
886 int manager_dispatch_console(Manager *m) {
890 seat_read_active_vt(m->vtconsole);
895 static int vt_is_busy(int vtnr) {
896 struct vt_stat vt_stat;
901 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
902 * we'd open the latter we'd open the foreground tty which
903 * hence would be unconditionally busy. By opening /dev/tty1
904 * we avoid this. Since tty1 is special and needs to be an
905 * explicitly loaded getty or DM this is safe. */
907 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
911 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
914 r = !!(vt_stat.v_state & (1 << vtnr));
916 close_nointr_nofail(fd);
921 int manager_spawn_autovt(Manager *m, int vtnr) {
924 const char *mode = "fail";
929 if ((unsigned) vtnr > m->n_autovts &&
930 (unsigned) vtnr != m->reserve_vt)
933 if ((unsigned) vtnr != m->reserve_vt) {
934 /* If this is the reserved TTY, we'll start the getty
935 * on it in any case, but otherwise only if it is not
938 r = vt_is_busy(vtnr);
945 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
946 log_error("Could not allocate service name.");
951 r = bus_method_call_with_reply (
953 "org.freedesktop.systemd1",
954 "/org/freedesktop/systemd1",
955 "org.freedesktop.systemd1.Manager",
959 DBUS_TYPE_STRING, &name,
960 DBUS_TYPE_STRING, &mode,
969 static int manager_reserve_vt(Manager *m) {
970 _cleanup_free_ char *p = NULL;
974 if (m->reserve_vt <= 0)
977 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
980 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
981 if (m->reserve_vt_fd < 0) {
983 /* Don't complain on VT-less systems */
985 log_warning("Failed to pin reserved VT: %m");
992 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1000 s = hashmap_get(m->session_cgroups, cgroup);
1006 p = strdupa(cgroup);
1011 e = strrchr(p, '/');
1019 s = hashmap_get(m->session_cgroups, p);
1027 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1035 u = hashmap_get(m->user_cgroups, cgroup);
1041 p = strdupa(cgroup);
1048 e = strrchr(p, '/');
1056 u = hashmap_get(m->user_cgroups, p);
1064 int manager_get_machine_by_cgroup(Manager *m, const char *cgroup, Machine **machine) {
1072 u = hashmap_get(m->machine_cgroups, cgroup);
1078 p = strdupa(cgroup);
1085 e = strrchr(p, '/');
1093 u = hashmap_get(m->machine_cgroups, p);
1101 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1102 _cleanup_free_ char *p = NULL;
1109 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1113 return manager_get_session_by_cgroup(m, p, session);
1116 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
1117 _cleanup_free_ char *p = NULL;
1124 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1128 return manager_get_user_by_cgroup(m, p, user);
1131 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1132 _cleanup_free_ char *p = NULL;
1139 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1143 return manager_get_machine_by_cgroup(m, p, machine);
1146 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1152 r = manager_get_session_by_cgroup(m, cgroup, &s);
1154 session_add_to_gc_queue(s);
1156 r = manager_get_user_by_cgroup(m, cgroup, &u);
1158 user_add_to_gc_queue(u);
1160 r = manager_get_machine_by_cgroup(m, cgroup, &machine);
1162 machine_add_to_gc_queue(machine);
1165 static void manager_dispatch_other(Manager *m, int fd) {
1173 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1175 assert(s->fifo_fd == fd);
1176 session_remove_fifo(s);
1181 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1183 assert(i->fifo_fd == fd);
1189 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1191 assert(b->fd == fd);
1196 assert_not_reached("Got event for unknown fd");
1199 static int manager_connect_bus(Manager *m) {
1202 struct epoll_event ev = {
1209 assert(m->bus_fd < 0);
1211 dbus_error_init(&error);
1213 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1215 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1220 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1221 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1222 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1223 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1224 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/machine", &bus_machine_vtable, m) ||
1225 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1230 dbus_bus_add_match(m->bus,
1232 "interface='org.freedesktop.systemd1.Agent',"
1233 "member='Released',"
1234 "path='/org/freedesktop/systemd1/agent'",
1237 if (dbus_error_is_set(&error)) {
1238 log_error("Failed to register match: %s", bus_error_message(&error));
1243 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1244 if (dbus_error_is_set(&error)) {
1245 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1250 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1251 log_error("Failed to acquire name.");
1256 m->bus_fd = bus_loop_open(m->bus);
1257 if (m->bus_fd < 0) {
1262 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1268 dbus_error_free(&error);
1273 static int manager_connect_console(Manager *m) {
1274 struct epoll_event ev = {
1276 .data.u32 = FD_CONSOLE,
1280 assert(m->console_active_fd < 0);
1282 /* On certain architectures (S390 and Xen, and containers),
1283 /dev/tty0 does not exist, so don't fail if we can't open
1285 if (access("/dev/tty0", F_OK) < 0) {
1286 m->console_active_fd = -1;
1290 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1291 if (m->console_active_fd < 0) {
1293 /* On some systems the device node /dev/tty0 may exist
1294 * even though /sys/class/tty/tty0 does not. */
1295 if (errno == ENOENT)
1298 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1302 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1308 static int manager_connect_udev(Manager *m) {
1310 struct epoll_event ev = {
1312 .data.u32 = FD_SEAT_UDEV,
1316 assert(!m->udev_seat_monitor);
1317 assert(!m->udev_vcsa_monitor);
1318 assert(!m->udev_button_monitor);
1320 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1321 if (!m->udev_seat_monitor)
1324 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1328 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1332 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1334 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1337 /* Don't watch keys if nobody cares */
1338 if (m->handle_power_key != HANDLE_IGNORE ||
1339 m->handle_suspend_key != HANDLE_IGNORE ||
1340 m->handle_hibernate_key != HANDLE_IGNORE ||
1341 m->handle_lid_switch != HANDLE_IGNORE) {
1343 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1344 if (!m->udev_button_monitor)
1347 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1351 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1355 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1359 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1362 ev.events = EPOLLIN;
1363 ev.data.u32 = FD_BUTTON_UDEV;
1364 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1368 /* Don't bother watching VCSA devices, if nobody cares */
1369 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1371 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1372 if (!m->udev_vcsa_monitor)
1375 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1379 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1383 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1386 ev.events = EPOLLIN;
1387 ev.data.u32 = FD_VCSA_UDEV;
1388 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1395 void manager_gc(Manager *m, bool drop_not_started) {
1403 while ((seat = m->seat_gc_queue)) {
1404 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1405 seat->in_gc_queue = false;
1407 if (seat_check_gc(seat, drop_not_started) == 0) {
1413 while ((session = m->session_gc_queue)) {
1414 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1415 session->in_gc_queue = false;
1417 if (session_check_gc(session, drop_not_started) == 0) {
1418 session_stop(session);
1419 session_free(session);
1423 while ((user = m->user_gc_queue)) {
1424 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1425 user->in_gc_queue = false;
1427 if (user_check_gc(user, drop_not_started) == 0) {
1433 while ((machine = m->machine_gc_queue)) {
1434 LIST_REMOVE(Machine, gc_queue, m->machine_gc_queue, machine);
1435 machine->in_gc_queue = false;
1437 if (machine_check_gc(machine, drop_not_started) == 0) {
1438 machine_stop(machine);
1439 machine_free(machine);
1444 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1447 dual_timestamp ts = { 0, 0 };
1452 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1454 HASHMAP_FOREACH(s, m->sessions, i) {
1458 ih = session_get_idle_hint(s, &k);
1464 if (k.monotonic < ts.monotonic)
1470 } else if (idle_hint) {
1472 if (k.monotonic > ts.monotonic)
1483 int manager_dispatch_idle_action(Manager *m) {
1484 struct dual_timestamp since;
1485 struct itimerspec its = {};
1491 if (m->idle_action == HANDLE_IGNORE ||
1492 m->idle_action_usec <= 0) {
1497 n = now(CLOCK_MONOTONIC);
1499 r = manager_get_idle_hint(m, &since);
1501 /* Not idle. Let's check if after a timeout it might be idle then. */
1502 timespec_store(&its.it_value, n + m->idle_action_usec);
1504 /* Idle! Let's see if it's time to do something, or if
1505 * we shall sleep for longer. */
1507 if (n >= since.monotonic + m->idle_action_usec &&
1508 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1509 log_info("System idle. Taking action.");
1511 manager_handle_action(m, 0, m->idle_action, false, false);
1512 m->idle_action_not_before_usec = n;
1515 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1518 if (m->idle_action_fd < 0) {
1519 struct epoll_event ev = {
1521 .data.u32 = FD_IDLE_ACTION,
1524 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1525 if (m->idle_action_fd < 0) {
1526 log_error("Failed to create idle action timer: %m");
1531 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1532 log_error("Failed to add idle action timer to epoll: %m");
1538 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1539 log_error("Failed to reset timerfd: %m");
1547 if (m->idle_action_fd >= 0) {
1548 close_nointr_nofail(m->idle_action_fd);
1549 m->idle_action_fd = -1;
1554 int manager_startup(Manager *m) {
1559 Inhibitor *inhibitor;
1564 assert(m->epoll_fd <= 0);
1566 cg_shorten_controllers(m->reset_controllers);
1567 cg_shorten_controllers(m->controllers);
1569 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1570 if (m->epoll_fd < 0)
1573 /* Connect to console */
1574 r = manager_connect_console(m);
1578 /* Connect to udev */
1579 r = manager_connect_udev(m);
1583 /* Connect to the bus */
1584 r = manager_connect_bus(m);
1588 /* Instantiate magic seat 0 */
1589 r = manager_add_seat(m, "seat0", &m->vtconsole);
1593 /* Deserialize state */
1594 manager_enumerate_devices(m);
1595 manager_enumerate_seats(m);
1596 manager_enumerate_users(m);
1597 manager_enumerate_sessions(m);
1598 manager_enumerate_inhibitors(m);
1599 manager_enumerate_buttons(m);
1600 manager_enumerate_machines(m);
1602 /* Remove stale objects before we start them */
1603 manager_gc(m, false);
1605 /* Reserve the special reserved VT */
1606 manager_reserve_vt(m);
1608 /* And start everything */
1609 HASHMAP_FOREACH(seat, m->seats, i)
1612 HASHMAP_FOREACH(user, m->users, i)
1615 HASHMAP_FOREACH(session, m->sessions, i)
1616 session_start(session);
1618 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1619 inhibitor_start(inhibitor);
1621 HASHMAP_FOREACH(machine, m->machines, i)
1622 machine_start(machine);
1624 manager_dispatch_idle_action(m);
1629 static int manager_recheck_buttons(Manager *m) {
1636 HASHMAP_FOREACH(b, m->buttons, i) {
1639 q = button_recheck(b);
1649 int manager_run(Manager *m) {
1653 struct epoll_event event;
1657 manager_gc(m, true);
1659 if (manager_dispatch_delayed(m) > 0)
1662 if (manager_recheck_buttons(m) > 0)
1665 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1668 manager_gc(m, true);
1670 if (m->action_what != 0 && !m->action_job) {
1673 x = now(CLOCK_MONOTONIC);
1674 y = m->action_timestamp + m->inhibit_delay_max;
1676 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1679 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1681 if (errno == EINTR || errno == EAGAIN)
1684 log_error("epoll() failed: %m");
1691 switch (event.data.u32) {
1694 manager_dispatch_seat_udev(m);
1698 manager_dispatch_vcsa_udev(m);
1701 case FD_BUTTON_UDEV:
1702 manager_dispatch_button_udev(m);
1706 manager_dispatch_console(m);
1709 case FD_IDLE_ACTION:
1710 manager_dispatch_idle_action(m);
1714 bus_loop_dispatch(m->bus_fd);
1718 if (event.data.u32 >= FD_OTHER_BASE)
1719 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1726 static int manager_parse_config_file(Manager *m) {
1727 static const char fn[] = "/etc/systemd/logind.conf";
1728 _cleanup_fclose_ FILE *f = NULL;
1733 f = fopen(fn, "re");
1735 if (errno == ENOENT)
1738 log_warning("Failed to open configuration file %s: %m", fn);
1742 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1743 (void*) logind_gperf_lookup, false, false, m);
1745 log_warning("Failed to parse configuration file: %s", strerror(-r));
1750 int main(int argc, char *argv[]) {
1754 log_set_target(LOG_TARGET_AUTO);
1755 log_set_facility(LOG_AUTH);
1756 log_parse_environment();
1762 log_error("This program takes no arguments.");
1767 /* Always create the directories people can create inotify
1768 * watches in. Note that some applications might check for the
1769 * existence of /run/systemd/seats/ to determine whether
1770 * logind is available, so please always make sure this check
1772 mkdir_label("/run/systemd/seats", 0755);
1773 mkdir_label("/run/systemd/users", 0755);
1774 mkdir_label("/run/systemd/sessions", 0755);
1775 mkdir_label("/run/systemd/machines", 0755);
1783 manager_parse_config_file(m);
1785 r = manager_startup(m);
1787 log_error("Failed to fully start up daemon: %s", strerror(-r));
1791 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1795 "STATUS=Processing requests...");
1799 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1803 "STATUS=Shutting down...");
1808 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;