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->busnames = 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);
82 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
83 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
84 m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
86 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
87 !m->user_units || !m->session_units ||
88 !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
93 m->kill_exclude_users = strv_new("root", NULL);
94 if (!m->kill_exclude_users) {
108 void manager_free(Manager *m) {
119 while ((session = hashmap_first(m->sessions)))
120 session_free(session);
122 while ((u = hashmap_first(m->users)))
125 while ((d = hashmap_first(m->devices)))
128 while ((s = hashmap_first(m->seats)))
131 while ((i = hashmap_first(m->inhibitors)))
134 while ((b = hashmap_first(m->buttons)))
137 while ((n = hashmap_first(m->busnames)))
138 free(hashmap_remove(m->busnames, n));
140 hashmap_free(m->devices);
141 hashmap_free(m->seats);
142 hashmap_free(m->sessions);
143 hashmap_free(m->users);
144 hashmap_free(m->inhibitors);
145 hashmap_free(m->buttons);
146 hashmap_free(m->busnames);
148 hashmap_free(m->user_units);
149 hashmap_free(m->session_units);
151 hashmap_free(m->session_fds);
152 hashmap_free(m->inhibitor_fds);
153 hashmap_free(m->button_fds);
155 if (m->console_active_fd >= 0)
156 close_nointr_nofail(m->console_active_fd);
158 if (m->udev_seat_monitor)
159 udev_monitor_unref(m->udev_seat_monitor);
160 if (m->udev_device_monitor)
161 udev_monitor_unref(m->udev_device_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, bool master, Device **_device) {
201 d = hashmap_get(m->devices, sysfs);
206 /* we support adding master-flags, but not removing them */
207 d->master = d->master || master;
212 d = device_new(m, sysfs, master);
222 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
228 s = hashmap_get(m->seats, id);
246 int manager_add_session(Manager *m, const char *id, Session **_session) {
252 s = hashmap_get(m->sessions, id);
260 s = session_new(m, id);
270 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
276 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
284 u = user_new(m, uid, gid, name);
294 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
302 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
306 return manager_add_user(m, uid, gid, name, _user);
309 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
317 return errno ? -errno : -ENOENT;
319 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
322 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
328 i = hashmap_get(m->inhibitors, id);
336 i = inhibitor_new(m, id);
346 int manager_add_button(Manager *m, const char *name, Button **_button) {
352 b = hashmap_get(m->buttons, name);
360 b = button_new(m, name);
370 int manager_watch_busname(Manager *m, const char *name) {
377 if (hashmap_get(m->busnames, name))
384 r = hashmap_put(m->busnames, n, n);
393 void manager_drop_busname(Manager *m, const char *name) {
401 if (!hashmap_get(m->busnames, name))
404 /* keep it if the name still owns a controller */
405 HASHMAP_FOREACH(session, m->sessions, i)
406 if (session_is_controller(session, name))
409 key = hashmap_remove(m->busnames, name);
414 int manager_process_seat_device(Manager *m, struct udev_device *d) {
420 if (streq_ptr(udev_device_get_action(d), "remove")) {
422 device = hashmap_get(m->devices, udev_device_get_syspath(d));
426 seat_add_to_gc_queue(device->seat);
434 sn = udev_device_get_property_value(d, "ID_SEAT");
438 if (!seat_name_is_valid(sn)) {
439 log_warning("Device with invalid seat name %s found, ignoring.", sn);
443 /* ignore non-master devices for unknown seats */
444 master = udev_device_has_tag(d, "master-of-seat");
445 if (!master && !(seat = hashmap_get(m->seats, sn)))
448 r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
453 r = manager_add_seat(m, sn, &seat);
462 device_attach(device, seat);
469 int manager_process_button_device(Manager *m, struct udev_device *d) {
476 if (streq_ptr(udev_device_get_action(d), "remove")) {
478 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
487 r = manager_add_button(m, udev_device_get_sysname(d), &b);
491 sn = udev_device_get_property_value(d, "ID_SEAT");
495 button_set_seat(b, sn);
502 int manager_enumerate_devices(Manager *m) {
503 struct udev_list_entry *item = NULL, *first = NULL;
504 struct udev_enumerate *e;
509 /* Loads devices from udev and creates seats for them as
512 e = udev_enumerate_new(m->udev);
518 r = udev_enumerate_add_match_tag(e, "master-of-seat");
522 r = udev_enumerate_scan_devices(e);
526 first = udev_enumerate_get_list_entry(e);
527 udev_list_entry_foreach(item, first) {
528 struct udev_device *d;
531 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
537 k = manager_process_seat_device(m, d);
538 udev_device_unref(d);
546 udev_enumerate_unref(e);
551 int manager_enumerate_buttons(Manager *m) {
552 struct udev_list_entry *item = NULL, *first = NULL;
553 struct udev_enumerate *e;
558 /* Loads buttons from udev */
560 if (m->handle_power_key == HANDLE_IGNORE &&
561 m->handle_suspend_key == HANDLE_IGNORE &&
562 m->handle_hibernate_key == HANDLE_IGNORE &&
563 m->handle_lid_switch == HANDLE_IGNORE)
566 e = udev_enumerate_new(m->udev);
572 r = udev_enumerate_add_match_subsystem(e, "input");
576 r = udev_enumerate_add_match_tag(e, "power-switch");
580 r = udev_enumerate_scan_devices(e);
584 first = udev_enumerate_get_list_entry(e);
585 udev_list_entry_foreach(item, first) {
586 struct udev_device *d;
589 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
595 k = manager_process_button_device(m, d);
596 udev_device_unref(d);
604 udev_enumerate_unref(e);
609 int manager_enumerate_seats(Manager *m) {
610 _cleanup_closedir_ DIR *d = NULL;
616 /* This loads data about seats stored on disk, but does not
617 * actually create any seats. Removes data of seats that no
620 d = opendir("/run/systemd/seats");
625 log_error("Failed to open /run/systemd/seats: %m");
629 FOREACH_DIRENT(de, d, return -errno) {
633 if (!dirent_is_file(de))
636 s = hashmap_get(m->seats, de->d_name);
638 unlinkat(dirfd(d), de->d_name, 0);
650 static int manager_enumerate_linger_users(Manager *m) {
651 _cleanup_closedir_ DIR *d = NULL;
657 d = opendir("/var/lib/systemd/linger");
662 log_error("Failed to open /var/lib/systemd/linger/: %m");
666 FOREACH_DIRENT(de, d, return -errno) {
669 if (!dirent_is_file(de))
672 k = manager_add_user_by_name(m, de->d_name, NULL);
674 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
682 int manager_enumerate_users(Manager *m) {
683 _cleanup_closedir_ DIR *d = NULL;
689 /* Add lingering users */
690 r = manager_enumerate_linger_users(m);
692 /* Read in user data stored on disk */
693 d = opendir("/run/systemd/users");
698 log_error("Failed to open /run/systemd/users: %m");
702 FOREACH_DIRENT(de, d, return -errno) {
705 if (!dirent_is_file(de))
708 k = manager_add_user_by_name(m, de->d_name, &u);
710 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
716 user_add_to_gc_queue(u);
726 int manager_enumerate_sessions(Manager *m) {
727 _cleanup_closedir_ DIR *d = NULL;
733 /* Read in session data stored on disk */
734 d = opendir("/run/systemd/sessions");
739 log_error("Failed to open /run/systemd/sessions: %m");
743 FOREACH_DIRENT(de, d, return -errno) {
747 if (!dirent_is_file(de))
750 if (!session_id_valid(de->d_name)) {
751 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
756 k = manager_add_session(m, de->d_name, &s);
758 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
764 session_add_to_gc_queue(s);
774 int manager_enumerate_inhibitors(Manager *m) {
775 _cleanup_closedir_ DIR *d = NULL;
781 d = opendir("/run/systemd/inhibit");
786 log_error("Failed to open /run/systemd/inhibit: %m");
790 FOREACH_DIRENT(de, d, return -errno) {
794 if (!dirent_is_file(de))
797 k = manager_add_inhibitor(m, de->d_name, &i);
799 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
804 k = inhibitor_load(i);
812 int manager_dispatch_seat_udev(Manager *m) {
813 struct udev_device *d;
818 d = udev_monitor_receive_device(m->udev_seat_monitor);
822 r = manager_process_seat_device(m, d);
823 udev_device_unref(d);
828 static int manager_dispatch_device_udev(Manager *m) {
829 struct udev_device *d;
834 d = udev_monitor_receive_device(m->udev_device_monitor);
838 r = manager_process_seat_device(m, d);
839 udev_device_unref(d);
844 int manager_dispatch_vcsa_udev(Manager *m) {
845 struct udev_device *d;
851 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
855 name = udev_device_get_sysname(d);
857 /* Whenever a VCSA device is removed try to reallocate our
858 * VTs, to make sure our auto VTs never go away. */
860 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
861 r = seat_preallocate_vts(m->seat0);
863 udev_device_unref(d);
868 int manager_dispatch_button_udev(Manager *m) {
869 struct udev_device *d;
874 d = udev_monitor_receive_device(m->udev_button_monitor);
878 r = manager_process_button_device(m, d);
879 udev_device_unref(d);
884 int manager_dispatch_console(Manager *m) {
888 seat_read_active_vt(m->seat0);
893 static int vt_is_busy(int vtnr) {
894 struct vt_stat vt_stat;
899 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
900 * we'd open the latter we'd open the foreground tty which
901 * hence would be unconditionally busy. By opening /dev/tty1
902 * we avoid this. Since tty1 is special and needs to be an
903 * explicitly loaded getty or DM this is safe. */
905 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
909 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
912 r = !!(vt_stat.v_state & (1 << vtnr));
914 close_nointr_nofail(fd);
919 int manager_spawn_autovt(Manager *m, int vtnr) {
922 const char *mode = "fail";
927 if ((unsigned) vtnr > m->n_autovts &&
928 (unsigned) vtnr != m->reserve_vt)
931 if ((unsigned) vtnr != m->reserve_vt) {
932 /* If this is the reserved TTY, we'll start the getty
933 * on it in any case, but otherwise only if it is not
936 r = vt_is_busy(vtnr);
943 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
944 log_error("Could not allocate service name.");
949 r = bus_method_call_with_reply (
951 "org.freedesktop.systemd1",
952 "/org/freedesktop/systemd1",
953 "org.freedesktop.systemd1.Manager",
957 DBUS_TYPE_STRING, &name,
958 DBUS_TYPE_STRING, &mode,
967 static int manager_reserve_vt(Manager *m) {
968 _cleanup_free_ char *p = NULL;
972 if (m->reserve_vt <= 0)
975 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
978 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
979 if (m->reserve_vt_fd < 0) {
981 /* Don't complain on VT-less systems */
983 log_warning("Failed to pin reserved VT: %m");
990 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
991 _cleanup_free_ char *unit = NULL;
1001 r = cg_pid_get_unit(pid, &unit);
1005 s = hashmap_get(m->session_units, unit);
1013 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
1014 _cleanup_free_ char *unit = NULL;
1024 r = cg_pid_get_slice(pid, &unit);
1028 u = hashmap_get(m->user_units, unit);
1036 static void manager_dispatch_other(Manager *m, int fd) {
1044 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1046 assert(s->fifo_fd == fd);
1047 session_remove_fifo(s);
1052 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1054 assert(i->fifo_fd == fd);
1060 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1062 assert(b->fd == fd);
1067 assert_not_reached("Got event for unknown fd");
1070 static int manager_connect_bus(Manager *m) {
1073 struct epoll_event ev = {
1080 assert(m->bus_fd < 0);
1082 dbus_error_init(&error);
1084 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1086 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1091 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1092 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1093 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1094 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1095 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1100 dbus_bus_add_match(m->bus,
1102 "sender='"DBUS_SERVICE_DBUS"',"
1103 "interface='"DBUS_INTERFACE_DBUS"',"
1104 "member='NameOwnerChanged',"
1105 "path='"DBUS_PATH_DBUS"'",
1107 if (dbus_error_is_set(&error)) {
1108 log_error("Failed to add match for NameOwnerChanged: %s", bus_error_message(&error));
1109 dbus_error_free(&error);
1112 dbus_bus_add_match(m->bus,
1114 "sender='org.freedesktop.systemd1',"
1115 "interface='org.freedesktop.systemd1.Manager',"
1116 "member='JobRemoved',"
1117 "path='/org/freedesktop/systemd1'",
1119 if (dbus_error_is_set(&error)) {
1120 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
1121 dbus_error_free(&error);
1124 dbus_bus_add_match(m->bus,
1126 "sender='org.freedesktop.systemd1',"
1127 "interface='org.freedesktop.systemd1.Manager',"
1128 "member='UnitRemoved',"
1129 "path='/org/freedesktop/systemd1'",
1131 if (dbus_error_is_set(&error)) {
1132 log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
1133 dbus_error_free(&error);
1136 dbus_bus_add_match(m->bus,
1138 "sender='org.freedesktop.systemd1',"
1139 "interface='org.freedesktop.DBus.Properties',"
1140 "member='PropertiesChanged'",
1142 if (dbus_error_is_set(&error)) {
1143 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
1144 dbus_error_free(&error);
1147 dbus_bus_add_match(m->bus,
1149 "sender='org.freedesktop.systemd1',"
1150 "interface='org.freedesktop.systemd1.Manager',"
1151 "member='Reloading',"
1152 "path='/org/freedesktop/systemd1'",
1154 if (dbus_error_is_set(&error)) {
1155 log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
1156 dbus_error_free(&error);
1159 r = bus_method_call_with_reply(
1161 "org.freedesktop.systemd1",
1162 "/org/freedesktop/systemd1",
1163 "org.freedesktop.systemd1.Manager",
1169 log_error("Failed to enable subscription: %s", bus_error(&error, r));
1170 dbus_error_free(&error);
1173 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1174 if (dbus_error_is_set(&error)) {
1175 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1180 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1181 log_error("Failed to acquire name.");
1186 m->bus_fd = bus_loop_open(m->bus);
1187 if (m->bus_fd < 0) {
1192 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1198 dbus_error_free(&error);
1203 static int manager_connect_console(Manager *m) {
1204 struct epoll_event ev = {
1206 .data.u32 = FD_CONSOLE,
1210 assert(m->console_active_fd < 0);
1212 /* On certain architectures (S390 and Xen, and containers),
1213 /dev/tty0 does not exist, so don't fail if we can't open
1215 if (access("/dev/tty0", F_OK) < 0) {
1216 m->console_active_fd = -1;
1220 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1221 if (m->console_active_fd < 0) {
1223 /* On some systems the device node /dev/tty0 may exist
1224 * even though /sys/class/tty/tty0 does not. */
1225 if (errno == ENOENT)
1228 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1232 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1238 static int manager_connect_udev(Manager *m) {
1240 struct epoll_event ev = {
1242 .data.u32 = FD_SEAT_UDEV,
1246 assert(!m->udev_seat_monitor);
1247 assert(!m->udev_device_monitor);
1248 assert(!m->udev_vcsa_monitor);
1249 assert(!m->udev_button_monitor);
1251 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1252 if (!m->udev_seat_monitor)
1255 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1259 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1263 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1265 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1268 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1269 if (!m->udev_device_monitor)
1272 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
1276 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
1280 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
1284 r = udev_monitor_enable_receiving(m->udev_device_monitor);
1288 m->udev_device_fd = udev_monitor_get_fd(m->udev_device_monitor);
1290 ev.events = EPOLLIN;
1291 ev.data.u32 = FD_DEVICE_UDEV;
1292 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_device_fd, &ev) < 0)
1295 /* Don't watch keys if nobody cares */
1296 if (m->handle_power_key != HANDLE_IGNORE ||
1297 m->handle_suspend_key != HANDLE_IGNORE ||
1298 m->handle_hibernate_key != HANDLE_IGNORE ||
1299 m->handle_lid_switch != HANDLE_IGNORE) {
1301 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1302 if (!m->udev_button_monitor)
1305 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1309 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1313 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1317 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1320 ev.events = EPOLLIN;
1321 ev.data.u32 = FD_BUTTON_UDEV;
1322 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1326 /* Don't bother watching VCSA devices, if nobody cares */
1327 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1329 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1330 if (!m->udev_vcsa_monitor)
1333 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1337 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1341 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1344 ev.events = EPOLLIN;
1345 ev.data.u32 = FD_VCSA_UDEV;
1346 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1353 void manager_gc(Manager *m, bool drop_not_started) {
1360 while ((seat = m->seat_gc_queue)) {
1361 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1362 seat->in_gc_queue = false;
1364 if (seat_check_gc(seat, drop_not_started) == 0) {
1370 while ((session = m->session_gc_queue)) {
1371 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1372 session->in_gc_queue = false;
1374 if (session_check_gc(session, drop_not_started) == 0) {
1375 session_stop(session);
1376 session_finalize(session);
1377 session_free(session);
1381 while ((user = m->user_gc_queue)) {
1382 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1383 user->in_gc_queue = false;
1385 if (user_check_gc(user, drop_not_started) == 0) {
1387 user_finalize(user);
1393 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1396 dual_timestamp ts = { 0, 0 };
1401 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1403 HASHMAP_FOREACH(s, m->sessions, i) {
1407 ih = session_get_idle_hint(s, &k);
1413 if (k.monotonic < ts.monotonic)
1419 } else if (idle_hint) {
1421 if (k.monotonic > ts.monotonic)
1432 bool manager_shall_kill(Manager *m, const char *user) {
1436 if (!m->kill_user_processes)
1439 if (strv_contains(m->kill_exclude_users, user))
1442 if (strv_isempty(m->kill_only_users))
1445 return strv_contains(m->kill_only_users, user);
1448 int manager_dispatch_idle_action(Manager *m) {
1449 struct dual_timestamp since;
1450 struct itimerspec its = {};
1456 if (m->idle_action == HANDLE_IGNORE ||
1457 m->idle_action_usec <= 0) {
1462 n = now(CLOCK_MONOTONIC);
1464 r = manager_get_idle_hint(m, &since);
1466 /* Not idle. Let's check if after a timeout it might be idle then. */
1467 timespec_store(&its.it_value, n + m->idle_action_usec);
1469 /* Idle! Let's see if it's time to do something, or if
1470 * we shall sleep for longer. */
1472 if (n >= since.monotonic + m->idle_action_usec &&
1473 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1474 log_info("System idle. Taking action.");
1476 manager_handle_action(m, 0, m->idle_action, false, false);
1477 m->idle_action_not_before_usec = n;
1480 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1483 if (m->idle_action_fd < 0) {
1484 struct epoll_event ev = {
1486 .data.u32 = FD_IDLE_ACTION,
1489 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1490 if (m->idle_action_fd < 0) {
1491 log_error("Failed to create idle action timer: %m");
1496 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1497 log_error("Failed to add idle action timer to epoll: %m");
1503 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1504 log_error("Failed to reset timerfd: %m");
1512 if (m->idle_action_fd >= 0) {
1513 close_nointr_nofail(m->idle_action_fd);
1514 m->idle_action_fd = -1;
1519 int manager_startup(Manager *m) {
1524 Inhibitor *inhibitor;
1528 assert(m->epoll_fd <= 0);
1530 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1531 if (m->epoll_fd < 0)
1534 /* Connect to console */
1535 r = manager_connect_console(m);
1539 /* Connect to udev */
1540 r = manager_connect_udev(m);
1544 /* Connect to the bus */
1545 r = manager_connect_bus(m);
1549 /* Instantiate magic seat 0 */
1550 r = manager_add_seat(m, "seat0", &m->seat0);
1554 /* Deserialize state */
1555 r = manager_enumerate_devices(m);
1557 log_warning("Device enumeration failed: %s", strerror(-r));
1559 r = manager_enumerate_seats(m);
1561 log_warning("Seat enumeration failed: %s", strerror(-r));
1563 r = manager_enumerate_users(m);
1565 log_warning("User enumeration failed: %s", strerror(-r));
1567 r = manager_enumerate_sessions(m);
1569 log_warning("Session enumeration failed: %s", strerror(-r));
1571 r = manager_enumerate_inhibitors(m);
1573 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1575 r = manager_enumerate_buttons(m);
1577 log_warning("Button enumeration failed: %s", strerror(-r));
1579 /* Remove stale objects before we start them */
1580 manager_gc(m, false);
1582 /* Reserve the special reserved VT */
1583 manager_reserve_vt(m);
1585 /* And start everything */
1586 HASHMAP_FOREACH(seat, m->seats, i)
1589 HASHMAP_FOREACH(user, m->users, i)
1592 HASHMAP_FOREACH(session, m->sessions, i)
1593 session_start(session);
1595 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1596 inhibitor_start(inhibitor);
1598 manager_dispatch_idle_action(m);
1603 static int manager_recheck_buttons(Manager *m) {
1610 HASHMAP_FOREACH(b, m->buttons, i) {
1613 q = button_recheck(b);
1623 int manager_run(Manager *m) {
1627 struct epoll_event event;
1631 manager_gc(m, true);
1633 if (manager_dispatch_delayed(m) > 0)
1636 if (manager_recheck_buttons(m) > 0)
1639 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1642 manager_gc(m, true);
1644 if (m->action_what != 0 && !m->action_job) {
1647 x = now(CLOCK_MONOTONIC);
1648 y = m->action_timestamp + m->inhibit_delay_max;
1650 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1653 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1655 if (errno == EINTR || errno == EAGAIN)
1658 log_error("epoll() failed: %m");
1665 switch (event.data.u32) {
1668 manager_dispatch_seat_udev(m);
1671 case FD_DEVICE_UDEV:
1672 manager_dispatch_device_udev(m);
1676 manager_dispatch_vcsa_udev(m);
1679 case FD_BUTTON_UDEV:
1680 manager_dispatch_button_udev(m);
1684 manager_dispatch_console(m);
1687 case FD_IDLE_ACTION:
1688 manager_dispatch_idle_action(m);
1692 bus_loop_dispatch(m->bus_fd);
1696 if (event.data.u32 >= FD_OTHER_BASE)
1697 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1704 static int manager_parse_config_file(Manager *m) {
1705 static const char fn[] = "/etc/systemd/logind.conf";
1706 _cleanup_fclose_ FILE *f = NULL;
1711 f = fopen(fn, "re");
1713 if (errno == ENOENT)
1716 log_warning("Failed to open configuration file %s: %m", fn);
1720 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1721 (void*) logind_gperf_lookup, false, false, m);
1723 log_warning("Failed to parse configuration file: %s", strerror(-r));
1728 int main(int argc, char *argv[]) {
1732 log_set_target(LOG_TARGET_AUTO);
1733 log_set_facility(LOG_AUTH);
1734 log_parse_environment();
1740 log_error("This program takes no arguments.");
1745 /* Always create the directories people can create inotify
1746 * watches in. Note that some applications might check for the
1747 * existence of /run/systemd/seats/ to determine whether
1748 * logind is available, so please always make sure this check
1750 mkdir_label("/run/systemd/seats", 0755);
1751 mkdir_label("/run/systemd/users", 0755);
1752 mkdir_label("/run/systemd/sessions", 0755);
1760 manager_parse_config_file(m);
1762 r = manager_startup(m);
1764 log_error("Failed to fully start up daemon: %s", strerror(-r));
1768 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1772 "STATUS=Processing requests...");
1776 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1780 "STATUS=Shutting down...");
1785 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;