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;
999 r = cg_pid_get_unit(pid, &unit);
1003 s = hashmap_get(m->session_units, unit);
1011 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
1012 _cleanup_free_ char *unit = NULL;
1020 r = cg_pid_get_slice(pid, &unit);
1024 u = hashmap_get(m->user_units, unit);
1032 static void manager_dispatch_other(Manager *m, int fd) {
1040 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1042 assert(s->fifo_fd == fd);
1043 session_remove_fifo(s);
1048 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1050 assert(i->fifo_fd == fd);
1056 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1058 assert(b->fd == fd);
1063 assert_not_reached("Got event for unknown fd");
1066 static int manager_connect_bus(Manager *m) {
1069 struct epoll_event ev = {
1076 assert(m->bus_fd < 0);
1078 dbus_error_init(&error);
1080 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1082 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1087 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1088 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1089 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1090 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1091 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1096 dbus_bus_add_match(m->bus,
1098 "sender='"DBUS_SERVICE_DBUS"',"
1099 "interface='"DBUS_INTERFACE_DBUS"',"
1100 "member='NameOwnerChanged',"
1101 "path='"DBUS_PATH_DBUS"'",
1103 if (dbus_error_is_set(&error)) {
1104 log_error("Failed to add match for NameOwnerChanged: %s", bus_error_message(&error));
1105 dbus_error_free(&error);
1108 dbus_bus_add_match(m->bus,
1110 "sender='org.freedesktop.systemd1',"
1111 "interface='org.freedesktop.systemd1.Manager',"
1112 "member='JobRemoved',"
1113 "path='/org/freedesktop/systemd1'",
1115 if (dbus_error_is_set(&error)) {
1116 log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
1117 dbus_error_free(&error);
1120 dbus_bus_add_match(m->bus,
1122 "sender='org.freedesktop.systemd1',"
1123 "interface='org.freedesktop.systemd1.Manager',"
1124 "member='UnitRemoved',"
1125 "path='/org/freedesktop/systemd1'",
1127 if (dbus_error_is_set(&error)) {
1128 log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
1129 dbus_error_free(&error);
1132 dbus_bus_add_match(m->bus,
1134 "sender='org.freedesktop.systemd1',"
1135 "interface='org.freedesktop.DBus.Properties',"
1136 "member='PropertiesChanged'",
1138 if (dbus_error_is_set(&error)) {
1139 log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
1140 dbus_error_free(&error);
1143 dbus_bus_add_match(m->bus,
1145 "sender='org.freedesktop.systemd1',"
1146 "interface='org.freedesktop.systemd1.Manager',"
1147 "member='Reloading',"
1148 "path='/org/freedesktop/systemd1'",
1150 if (dbus_error_is_set(&error)) {
1151 log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
1152 dbus_error_free(&error);
1155 r = bus_method_call_with_reply(
1157 "org.freedesktop.systemd1",
1158 "/org/freedesktop/systemd1",
1159 "org.freedesktop.systemd1.Manager",
1165 log_error("Failed to enable subscription: %s", bus_error(&error, r));
1166 dbus_error_free(&error);
1169 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1170 if (dbus_error_is_set(&error)) {
1171 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1176 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1177 log_error("Failed to acquire name.");
1182 m->bus_fd = bus_loop_open(m->bus);
1183 if (m->bus_fd < 0) {
1188 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1194 dbus_error_free(&error);
1199 static int manager_connect_console(Manager *m) {
1200 struct epoll_event ev = {
1202 .data.u32 = FD_CONSOLE,
1206 assert(m->console_active_fd < 0);
1208 /* On certain architectures (S390 and Xen, and containers),
1209 /dev/tty0 does not exist, so don't fail if we can't open
1211 if (access("/dev/tty0", F_OK) < 0) {
1212 m->console_active_fd = -1;
1216 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1217 if (m->console_active_fd < 0) {
1219 /* On some systems the device node /dev/tty0 may exist
1220 * even though /sys/class/tty/tty0 does not. */
1221 if (errno == ENOENT)
1224 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1228 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1234 static int manager_connect_udev(Manager *m) {
1236 struct epoll_event ev = {
1238 .data.u32 = FD_SEAT_UDEV,
1242 assert(!m->udev_seat_monitor);
1243 assert(!m->udev_device_monitor);
1244 assert(!m->udev_vcsa_monitor);
1245 assert(!m->udev_button_monitor);
1247 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1248 if (!m->udev_seat_monitor)
1251 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
1255 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1259 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1261 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1264 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1265 if (!m->udev_device_monitor)
1268 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
1272 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
1276 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
1280 r = udev_monitor_enable_receiving(m->udev_device_monitor);
1284 m->udev_device_fd = udev_monitor_get_fd(m->udev_device_monitor);
1286 ev.events = EPOLLIN;
1287 ev.data.u32 = FD_DEVICE_UDEV;
1288 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_device_fd, &ev) < 0)
1291 /* Don't watch keys if nobody cares */
1292 if (m->handle_power_key != HANDLE_IGNORE ||
1293 m->handle_suspend_key != HANDLE_IGNORE ||
1294 m->handle_hibernate_key != HANDLE_IGNORE ||
1295 m->handle_lid_switch != HANDLE_IGNORE) {
1297 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1298 if (!m->udev_button_monitor)
1301 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1305 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1309 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1313 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1316 ev.events = EPOLLIN;
1317 ev.data.u32 = FD_BUTTON_UDEV;
1318 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1322 /* Don't bother watching VCSA devices, if nobody cares */
1323 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1325 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1326 if (!m->udev_vcsa_monitor)
1329 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1333 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1337 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1340 ev.events = EPOLLIN;
1341 ev.data.u32 = FD_VCSA_UDEV;
1342 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1349 void manager_gc(Manager *m, bool drop_not_started) {
1356 while ((seat = m->seat_gc_queue)) {
1357 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1358 seat->in_gc_queue = false;
1360 if (seat_check_gc(seat, drop_not_started) == 0) {
1366 while ((session = m->session_gc_queue)) {
1367 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1368 session->in_gc_queue = false;
1370 if (session_check_gc(session, drop_not_started) == 0) {
1371 session_stop(session);
1372 session_finalize(session);
1373 session_free(session);
1377 while ((user = m->user_gc_queue)) {
1378 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1379 user->in_gc_queue = false;
1381 if (user_check_gc(user, drop_not_started) == 0) {
1383 user_finalize(user);
1389 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1392 dual_timestamp ts = { 0, 0 };
1397 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1399 HASHMAP_FOREACH(s, m->sessions, i) {
1403 ih = session_get_idle_hint(s, &k);
1409 if (k.monotonic < ts.monotonic)
1415 } else if (idle_hint) {
1417 if (k.monotonic > ts.monotonic)
1428 bool manager_shall_kill(Manager *m, const char *user) {
1432 if (!m->kill_user_processes)
1435 if (strv_contains(m->kill_exclude_users, user))
1438 if (strv_isempty(m->kill_only_users))
1441 return strv_contains(m->kill_only_users, user);
1444 int manager_dispatch_idle_action(Manager *m) {
1445 struct dual_timestamp since;
1446 struct itimerspec its = {};
1452 if (m->idle_action == HANDLE_IGNORE ||
1453 m->idle_action_usec <= 0) {
1458 n = now(CLOCK_MONOTONIC);
1460 r = manager_get_idle_hint(m, &since);
1462 /* Not idle. Let's check if after a timeout it might be idle then. */
1463 timespec_store(&its.it_value, n + m->idle_action_usec);
1465 /* Idle! Let's see if it's time to do something, or if
1466 * we shall sleep for longer. */
1468 if (n >= since.monotonic + m->idle_action_usec &&
1469 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1470 log_info("System idle. Taking action.");
1472 manager_handle_action(m, 0, m->idle_action, false, false);
1473 m->idle_action_not_before_usec = n;
1476 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1479 if (m->idle_action_fd < 0) {
1480 struct epoll_event ev = {
1482 .data.u32 = FD_IDLE_ACTION,
1485 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1486 if (m->idle_action_fd < 0) {
1487 log_error("Failed to create idle action timer: %m");
1492 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1493 log_error("Failed to add idle action timer to epoll: %m");
1499 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1500 log_error("Failed to reset timerfd: %m");
1508 if (m->idle_action_fd >= 0) {
1509 close_nointr_nofail(m->idle_action_fd);
1510 m->idle_action_fd = -1;
1515 int manager_startup(Manager *m) {
1520 Inhibitor *inhibitor;
1524 assert(m->epoll_fd <= 0);
1526 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1527 if (m->epoll_fd < 0)
1530 /* Connect to console */
1531 r = manager_connect_console(m);
1535 /* Connect to udev */
1536 r = manager_connect_udev(m);
1540 /* Connect to the bus */
1541 r = manager_connect_bus(m);
1545 /* Instantiate magic seat 0 */
1546 r = manager_add_seat(m, "seat0", &m->seat0);
1550 /* Deserialize state */
1551 r = manager_enumerate_devices(m);
1553 log_warning("Device enumeration failed: %s", strerror(-r));
1555 r = manager_enumerate_seats(m);
1557 log_warning("Seat enumeration failed: %s", strerror(-r));
1559 r = manager_enumerate_users(m);
1561 log_warning("User enumeration failed: %s", strerror(-r));
1563 r = manager_enumerate_sessions(m);
1565 log_warning("Session enumeration failed: %s", strerror(-r));
1567 r = manager_enumerate_inhibitors(m);
1569 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1571 r = manager_enumerate_buttons(m);
1573 log_warning("Button enumeration failed: %s", strerror(-r));
1575 /* Remove stale objects before we start them */
1576 manager_gc(m, false);
1578 /* Reserve the special reserved VT */
1579 manager_reserve_vt(m);
1581 /* And start everything */
1582 HASHMAP_FOREACH(seat, m->seats, i)
1585 HASHMAP_FOREACH(user, m->users, i)
1588 HASHMAP_FOREACH(session, m->sessions, i)
1589 session_start(session);
1591 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1592 inhibitor_start(inhibitor);
1594 manager_dispatch_idle_action(m);
1599 static int manager_recheck_buttons(Manager *m) {
1606 HASHMAP_FOREACH(b, m->buttons, i) {
1609 q = button_recheck(b);
1619 int manager_run(Manager *m) {
1623 struct epoll_event event;
1627 manager_gc(m, true);
1629 if (manager_dispatch_delayed(m) > 0)
1632 if (manager_recheck_buttons(m) > 0)
1635 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1638 manager_gc(m, true);
1640 if (m->action_what != 0 && !m->action_job) {
1643 x = now(CLOCK_MONOTONIC);
1644 y = m->action_timestamp + m->inhibit_delay_max;
1646 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1649 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1651 if (errno == EINTR || errno == EAGAIN)
1654 log_error("epoll() failed: %m");
1661 switch (event.data.u32) {
1664 manager_dispatch_seat_udev(m);
1667 case FD_DEVICE_UDEV:
1668 manager_dispatch_device_udev(m);
1672 manager_dispatch_vcsa_udev(m);
1675 case FD_BUTTON_UDEV:
1676 manager_dispatch_button_udev(m);
1680 manager_dispatch_console(m);
1683 case FD_IDLE_ACTION:
1684 manager_dispatch_idle_action(m);
1688 bus_loop_dispatch(m->bus_fd);
1692 if (event.data.u32 >= FD_OTHER_BASE)
1693 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1700 static int manager_parse_config_file(Manager *m) {
1701 static const char fn[] = "/etc/systemd/logind.conf";
1702 _cleanup_fclose_ FILE *f = NULL;
1707 f = fopen(fn, "re");
1709 if (errno == ENOENT)
1712 log_warning("Failed to open configuration file %s: %m", fn);
1716 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1717 (void*) logind_gperf_lookup, false, false, m);
1719 log_warning("Failed to parse configuration file: %s", strerror(-r));
1724 int main(int argc, char *argv[]) {
1728 log_set_target(LOG_TARGET_AUTO);
1729 log_set_facility(LOG_AUTH);
1730 log_parse_environment();
1736 log_error("This program takes no arguments.");
1741 /* Always create the directories people can create inotify
1742 * watches in. Note that some applications might check for the
1743 * existence of /run/systemd/seats/ to determine whether
1744 * logind is available, so please always make sure this check
1746 mkdir_label("/run/systemd/seats", 0755);
1747 mkdir_label("/run/systemd/users", 0755);
1748 mkdir_label("/run/systemd/sessions", 0755);
1756 manager_parse_config_file(m);
1758 r = manager_startup(m);
1760 log_error("Failed to fully start up daemon: %s", strerror(-r));
1764 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1768 "STATUS=Processing requests...");
1772 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1776 "STATUS=Shutting down...");
1781 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;