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>
32 #include <systemd/sd-daemon.h>
35 #include "dbus-common.h"
36 #include "dbus-loop.h"
38 #include "conf-parser.h"
40 Manager *manager_new(void) {
47 m->console_active_fd = -1;
54 m->devices = hashmap_new(string_hash_func, string_compare_func);
55 m->seats = hashmap_new(string_hash_func, string_compare_func);
56 m->sessions = hashmap_new(string_hash_func, string_compare_func);
57 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
58 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
60 m->cgroups = hashmap_new(string_hash_func, string_compare_func);
61 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
62 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
64 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors ||
65 !m->cgroups || !m->session_fds || !m->inhibitor_fds) {
70 m->reset_controllers = strv_new("cpu", NULL);
71 m->kill_exclude_users = strv_new("root", NULL);
72 if (!m->reset_controllers || !m->kill_exclude_users) {
83 if (cg_get_user_path(&m->cgroup_path) < 0) {
91 void manager_free(Manager *m) {
100 while ((session = hashmap_first(m->sessions)))
101 session_free(session);
103 while ((u = hashmap_first(m->users)))
106 while ((d = hashmap_first(m->devices)))
109 while ((s = hashmap_first(m->seats)))
112 while ((i = hashmap_first(m->inhibitors)))
115 hashmap_free(m->devices);
116 hashmap_free(m->seats);
117 hashmap_free(m->sessions);
118 hashmap_free(m->users);
119 hashmap_free(m->inhibitors);
121 hashmap_free(m->cgroups);
122 hashmap_free(m->session_fds);
123 hashmap_free(m->inhibitor_fds);
125 if (m->console_active_fd >= 0)
126 close_nointr_nofail(m->console_active_fd);
128 if (m->udev_seat_monitor)
129 udev_monitor_unref(m->udev_seat_monitor);
131 if (m->udev_vcsa_monitor)
132 udev_monitor_unref(m->udev_vcsa_monitor);
138 dbus_connection_flush(m->bus);
139 dbus_connection_close(m->bus);
140 dbus_connection_unref(m->bus);
144 close_nointr_nofail(m->bus_fd);
146 if (m->epoll_fd >= 0)
147 close_nointr_nofail(m->epoll_fd);
149 strv_free(m->controllers);
150 strv_free(m->reset_controllers);
151 strv_free(m->kill_only_users);
152 strv_free(m->kill_exclude_users);
154 free(m->cgroup_path);
158 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
164 d = hashmap_get(m->devices, sysfs);
172 d = device_new(m, sysfs);
182 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
188 s = hashmap_get(m->seats, id);
206 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
212 s = hashmap_get(m->sessions, id);
220 s = session_new(m, u, id);
230 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
236 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
244 u = user_new(m, uid, gid, name);
254 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
262 r = get_user_creds(&name, &uid, &gid, NULL);
266 return manager_add_user(m, uid, gid, name, _user);
269 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
277 return errno ? -errno : -ENOENT;
279 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
282 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
288 i = hashmap_get(m->inhibitors, id);
296 i = inhibitor_new(m, id);
306 int manager_process_seat_device(Manager *m, struct udev_device *d) {
312 if (streq_ptr(udev_device_get_action(d), "remove")) {
314 device = hashmap_get(m->devices, udev_device_get_syspath(d));
318 seat_add_to_gc_queue(device->seat);
325 sn = udev_device_get_property_value(d, "ID_SEAT");
329 if (!seat_name_is_valid(sn)) {
330 log_warning("Device with invalid seat name %s found, ignoring.", sn);
334 r = manager_add_device(m, udev_device_get_syspath(d), &device);
338 r = manager_add_seat(m, sn, &seat);
346 device_attach(device, seat);
353 int manager_enumerate_devices(Manager *m) {
354 struct udev_list_entry *item = NULL, *first = NULL;
355 struct udev_enumerate *e;
360 /* Loads devices from udev and creates seats for them as
363 e = udev_enumerate_new(m->udev);
369 r = udev_enumerate_add_match_subsystem(e, "graphics");
373 r = udev_enumerate_add_match_tag(e, "seat");
377 r = udev_enumerate_scan_devices(e);
381 first = udev_enumerate_get_list_entry(e);
382 udev_list_entry_foreach(item, first) {
383 struct udev_device *d;
386 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
392 k = manager_process_seat_device(m, d);
393 udev_device_unref(d);
401 udev_enumerate_unref(e);
406 int manager_enumerate_seats(Manager *m) {
413 /* This loads data about seats stored on disk, but does not
414 * actually create any seats. Removes data of seats that no
417 d = opendir("/run/systemd/seats");
422 log_error("Failed to open /run/systemd/seats: %m");
426 while ((de = readdir(d))) {
430 if (!dirent_is_file(de))
433 s = hashmap_get(m->seats, de->d_name);
435 unlinkat(dirfd(d), de->d_name, 0);
449 static int manager_enumerate_users_from_cgroup(Manager *m) {
454 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
459 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
463 while ((k = cg_read_subgroup(d, &name)) > 0) {
466 k = manager_add_user_by_name(m, name, &user);
473 user_add_to_gc_queue(user);
475 if (!user->cgroup_path)
476 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
493 static int manager_enumerate_linger_users(Manager *m) {
498 d = opendir("/var/lib/systemd/linger");
503 log_error("Failed to open /var/lib/systemd/linger/: %m");
507 while ((de = readdir(d))) {
510 if (!dirent_is_file(de))
513 k = manager_add_user_by_name(m, de->d_name, NULL);
515 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
525 int manager_enumerate_users(Manager *m) {
532 /* First, enumerate user cgroups */
533 r = manager_enumerate_users_from_cgroup(m);
535 /* Second, add lingering users on top */
536 k = manager_enumerate_linger_users(m);
540 /* Third, read in user data stored on disk */
541 d = opendir("/run/systemd/users");
546 log_error("Failed to open /run/systemd/users: %m");
550 while ((de = readdir(d))) {
554 if (!dirent_is_file(de))
557 k = parse_uid(de->d_name, &uid);
559 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
563 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
565 unlinkat(dirfd(d), de->d_name, 0);
579 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
584 HASHMAP_FOREACH(u, m->users, i) {
592 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
597 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
602 while ((k = cg_read_subgroup(d, &name)) > 0) {
605 if (streq(name, "shared"))
608 k = manager_add_session(m, u, name, &session);
614 session_add_to_gc_queue(session);
616 if (!session->cgroup_path)
617 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
635 int manager_enumerate_sessions(Manager *m) {
642 /* First enumerate session cgroups */
643 r = manager_enumerate_sessions_from_cgroup(m);
645 /* Second, read in session data stored on disk */
646 d = opendir("/run/systemd/sessions");
651 log_error("Failed to open /run/systemd/sessions: %m");
655 while ((de = readdir(d))) {
659 if (!dirent_is_file(de))
662 s = hashmap_get(m->sessions, de->d_name);
664 unlinkat(dirfd(d), de->d_name, 0);
678 int manager_enumerate_inhibitors(Manager *m) {
685 d = opendir("/run/systemd/inhibit");
690 log_error("Failed to open /run/systemd/inhibit: %m");
694 while ((de = readdir(d))) {
698 if (!dirent_is_file(de))
701 k = manager_add_inhibitor(m, de->d_name, &i);
703 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
708 k = inhibitor_load(i);
718 int manager_dispatch_seat_udev(Manager *m) {
719 struct udev_device *d;
724 d = udev_monitor_receive_device(m->udev_seat_monitor);
728 r = manager_process_seat_device(m, d);
729 udev_device_unref(d);
734 int manager_dispatch_vcsa_udev(Manager *m) {
735 struct udev_device *d;
741 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
745 name = udev_device_get_sysname(d);
747 /* Whenever a VCSA device is removed try to reallocate our
748 * VTs, to make sure our auto VTs never go away. */
750 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
751 r = seat_preallocate_vts(m->vtconsole);
753 udev_device_unref(d);
758 int manager_dispatch_console(Manager *m) {
762 seat_read_active_vt(m->vtconsole);
767 static int vt_is_busy(int vtnr) {
768 struct vt_stat vt_stat;
773 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
774 * we'd open the latter we'd open the foreground tty which
775 * hence would be unconditionally busy. By opening /dev/tty1
776 * we avoid this. Since tty1 is special and needs to be an
777 * explicitly loaded getty or DM this is safe. */
779 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
783 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
786 r = !!(vt_stat.v_state & (1 << vtnr));
788 close_nointr_nofail(fd);
793 int manager_spawn_autovt(Manager *m, int vtnr) {
795 DBusMessage *message = NULL, *reply = NULL;
797 const char *mode = "fail";
803 dbus_error_init(&error);
805 if ((unsigned) vtnr > m->n_autovts)
808 r = vt_is_busy(vtnr);
814 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
816 log_error("Could not allocate message.");
821 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
822 log_error("Could not allocate service name.");
827 if (!dbus_message_append_args(message,
828 DBUS_TYPE_STRING, &name,
829 DBUS_TYPE_STRING, &mode,
830 DBUS_TYPE_INVALID)) {
831 log_error("Could not attach target and flag information to message.");
836 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
838 log_error("Failed to start unit: %s", bus_error_message(&error));
848 dbus_message_unref(message);
851 dbus_message_unref(reply);
853 dbus_error_free(&error);
858 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
866 s = hashmap_get(m->cgroups, cgroup);
874 log_error("Out of memory.");
890 s = hashmap_get(m->cgroups, p);
899 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
907 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
911 r = manager_get_session_by_cgroup(m, p, session);
917 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
921 r = manager_get_session_by_cgroup(m, cgroup, &s);
925 session_add_to_gc_queue(s);
928 static void manager_pipe_notify_eof(Manager *m, int fd) {
935 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
937 assert(s->fifo_fd == fd);
938 session_remove_fifo(s);
943 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
945 assert(i->fifo_fd == fd);
951 assert_not_reached("Got EOF on unknown pipe");
954 static int manager_connect_bus(Manager *m) {
957 struct epoll_event ev;
961 assert(m->bus_fd < 0);
963 dbus_error_init(&error);
965 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
967 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
972 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
973 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
974 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
975 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
976 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
977 log_error("Not enough memory");
982 dbus_bus_add_match(m->bus,
984 "interface='org.freedesktop.systemd1.Agent',"
986 "path='/org/freedesktop/systemd1/agent'",
989 if (dbus_error_is_set(&error)) {
990 log_error("Failed to register match: %s", bus_error_message(&error));
995 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
996 if (dbus_error_is_set(&error)) {
997 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1002 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1003 log_error("Failed to acquire name.");
1008 m->bus_fd = bus_loop_open(m->bus);
1009 if (m->bus_fd < 0) {
1015 ev.events = EPOLLIN;
1016 ev.data.u32 = FD_BUS;
1018 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1024 dbus_error_free(&error);
1029 static int manager_connect_console(Manager *m) {
1030 struct epoll_event ev;
1033 assert(m->console_active_fd < 0);
1035 /* On certain architectures (S390 and Xen, and containers),
1036 /dev/tty0 does not exist, so don't fail if we can't open
1038 if (access("/dev/tty0", F_OK) < 0) {
1039 m->console_active_fd = -1;
1043 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1044 if (m->console_active_fd < 0) {
1045 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1051 ev.data.u32 = FD_CONSOLE;
1053 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1059 static int manager_connect_udev(Manager *m) {
1060 struct epoll_event ev;
1064 assert(!m->udev_seat_monitor);
1065 assert(!m->udev_vcsa_monitor);
1067 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1068 if (!m->udev_seat_monitor)
1071 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1075 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1079 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1083 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1086 ev.events = EPOLLIN;
1087 ev.data.u32 = FD_SEAT_UDEV;
1089 /* Don't bother watching VCSA devices, if nobody cares */
1090 if (m->n_autovts <= 0 || m->console_active_fd < 0)
1093 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1096 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1097 if (!m->udev_vcsa_monitor)
1100 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1104 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1108 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1111 ev.events = EPOLLIN;
1112 ev.data.u32 = FD_VCSA_UDEV;
1114 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1120 void manager_gc(Manager *m, bool drop_not_started) {
1127 while ((seat = m->seat_gc_queue)) {
1128 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1129 seat->in_gc_queue = false;
1131 if (seat_check_gc(seat, drop_not_started) == 0) {
1137 while ((session = m->session_gc_queue)) {
1138 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1139 session->in_gc_queue = false;
1141 if (session_check_gc(session, drop_not_started) == 0) {
1142 session_stop(session);
1143 session_free(session);
1147 while ((user = m->user_gc_queue)) {
1148 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1149 user->in_gc_queue = false;
1151 if (user_check_gc(user, drop_not_started) == 0) {
1158 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1161 dual_timestamp ts = { 0, 0 };
1166 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, t);
1168 HASHMAP_FOREACH(s, m->sessions, i) {
1172 ih = session_get_idle_hint(s, &k);
1178 if (k.monotonic < ts.monotonic)
1184 } else if (idle_hint) {
1186 if (k.monotonic > ts.monotonic)
1197 int manager_startup(Manager *m) {
1202 Inhibitor *inhibitor;
1206 assert(m->epoll_fd <= 0);
1208 cg_shorten_controllers(m->reset_controllers);
1209 cg_shorten_controllers(m->controllers);
1211 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1212 if (m->epoll_fd < 0)
1215 /* Connect to console */
1216 r = manager_connect_console(m);
1220 /* Connect to udev */
1221 r = manager_connect_udev(m);
1225 /* Connect to the bus */
1226 r = manager_connect_bus(m);
1230 /* Instantiate magic seat 0 */
1231 r = manager_add_seat(m, "seat0", &m->vtconsole);
1235 /* Deserialize state */
1236 manager_enumerate_devices(m);
1237 manager_enumerate_seats(m);
1238 manager_enumerate_users(m);
1239 manager_enumerate_sessions(m);
1240 manager_enumerate_inhibitors(m);
1242 /* Remove stale objects before we start them */
1243 manager_gc(m, false);
1245 /* And start everything */
1246 HASHMAP_FOREACH(seat, m->seats, i)
1249 HASHMAP_FOREACH(user, m->users, i)
1252 HASHMAP_FOREACH(session, m->sessions, i)
1253 session_start(session);
1255 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1256 inhibitor_start(inhibitor);
1261 int manager_run(Manager *m) {
1265 struct epoll_event event;
1268 manager_gc(m, true);
1270 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1273 manager_gc(m, true);
1275 n = epoll_wait(m->epoll_fd, &event, 1, -1);
1277 if (errno == EINTR || errno == EAGAIN)
1280 log_error("epoll() failed: %m");
1284 switch (event.data.u32) {
1287 manager_dispatch_seat_udev(m);
1291 manager_dispatch_vcsa_udev(m);
1295 manager_dispatch_console(m);
1299 bus_loop_dispatch(m->bus_fd);
1303 if (event.data.u32 >= FD_FIFO_BASE)
1304 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1311 static int manager_parse_config_file(Manager *m) {
1318 fn = "/etc/systemd/logind.conf";
1319 f = fopen(fn, "re");
1321 if (errno == ENOENT)
1324 log_warning("Failed to open configuration file %s: %m", fn);
1328 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1330 log_warning("Failed to parse configuration file: %s", strerror(-r));
1337 int main(int argc, char *argv[]) {
1341 log_set_target(LOG_TARGET_AUTO);
1342 log_set_facility(LOG_AUTH);
1343 log_parse_environment();
1349 log_error("This program takes no arguments.");
1356 log_error("Out of memory");
1361 manager_parse_config_file(m);
1363 r = manager_startup(m);
1365 log_error("Failed to fully start up daemon: %s", strerror(-r));
1369 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1373 "STATUS=Processing requests...");
1377 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1381 "STATUS=Shutting down...");
1386 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;