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->cgroups = hashmap_new(string_hash_func, string_compare_func);
59 m->fifo_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
61 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->cgroups || !m->fifo_fds) {
66 m->reset_controllers = strv_new("cpu", NULL);
67 m->kill_exclude_users = strv_new("root", NULL);
68 if (!m->reset_controllers || !m->kill_exclude_users) {
79 if (cg_get_user_path(&m->cgroup_path) < 0) {
87 void manager_free(Manager *m) {
95 while ((session = hashmap_first(m->sessions)))
96 session_free(session);
98 while ((u = hashmap_first(m->users)))
101 while ((d = hashmap_first(m->devices)))
104 while ((s = hashmap_first(m->seats)))
107 hashmap_free(m->sessions);
108 hashmap_free(m->users);
109 hashmap_free(m->devices);
110 hashmap_free(m->seats);
111 hashmap_free(m->cgroups);
112 hashmap_free(m->fifo_fds);
114 if (m->console_active_fd >= 0)
115 close_nointr_nofail(m->console_active_fd);
117 if (m->udev_seat_monitor)
118 udev_monitor_unref(m->udev_seat_monitor);
120 if (m->udev_vcsa_monitor)
121 udev_monitor_unref(m->udev_vcsa_monitor);
127 dbus_connection_flush(m->bus);
128 dbus_connection_close(m->bus);
129 dbus_connection_unref(m->bus);
133 close_nointr_nofail(m->bus_fd);
135 if (m->epoll_fd >= 0)
136 close_nointr_nofail(m->epoll_fd);
138 strv_free(m->controllers);
139 strv_free(m->reset_controllers);
140 strv_free(m->kill_only_users);
141 strv_free(m->kill_exclude_users);
143 free(m->cgroup_path);
147 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
153 d = hashmap_get(m->devices, sysfs);
161 d = device_new(m, sysfs);
171 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
177 s = hashmap_get(m->seats, id);
195 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
201 s = hashmap_get(m->sessions, id);
209 s = session_new(m, u, id);
219 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
225 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
233 u = user_new(m, uid, gid, name);
243 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
251 r = get_user_creds(&name, &uid, &gid, NULL);
255 return manager_add_user(m, uid, gid, name, _user);
258 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
266 return errno ? -errno : -ENOENT;
268 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
271 int manager_process_seat_device(Manager *m, struct udev_device *d) {
277 if (streq_ptr(udev_device_get_action(d), "remove")) {
279 device = hashmap_get(m->devices, udev_device_get_syspath(d));
283 seat_add_to_gc_queue(device->seat);
290 sn = udev_device_get_property_value(d, "ID_SEAT");
294 if (!seat_name_is_valid(sn)) {
295 log_warning("Device with invalid seat name %s found, ignoring.", sn);
299 r = manager_add_device(m, udev_device_get_syspath(d), &device);
303 r = manager_add_seat(m, sn, &seat);
311 device_attach(device, seat);
318 int manager_enumerate_devices(Manager *m) {
319 struct udev_list_entry *item = NULL, *first = NULL;
320 struct udev_enumerate *e;
325 /* Loads devices from udev and creates seats for them as
328 e = udev_enumerate_new(m->udev);
334 r = udev_enumerate_add_match_subsystem(e, "graphics");
338 r = udev_enumerate_add_match_tag(e, "seat");
342 r = udev_enumerate_scan_devices(e);
346 first = udev_enumerate_get_list_entry(e);
347 udev_list_entry_foreach(item, first) {
348 struct udev_device *d;
351 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
357 k = manager_process_seat_device(m, d);
358 udev_device_unref(d);
366 udev_enumerate_unref(e);
371 int manager_enumerate_seats(Manager *m) {
378 /* This loads data about seats stored on disk, but does not
379 * actually create any seats. Removes data of seats that no
382 d = opendir("/run/systemd/seats");
387 log_error("Failed to open /run/systemd/seats: %m");
391 while ((de = readdir(d))) {
395 if (!dirent_is_file(de))
398 s = hashmap_get(m->seats, de->d_name);
400 unlinkat(dirfd(d), de->d_name, 0);
414 static int manager_enumerate_users_from_cgroup(Manager *m) {
420 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
425 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
429 while ((k = cg_read_subgroup(d, &name)) > 0) {
432 k = manager_add_user_by_name(m, name, &user);
439 user_add_to_gc_queue(user);
441 if (!user->cgroup_path)
442 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
459 static int manager_enumerate_linger_users(Manager *m) {
464 d = opendir("/var/lib/systemd/linger");
469 log_error("Failed to open /var/lib/systemd/linger/: %m");
473 while ((de = readdir(d))) {
476 if (!dirent_is_file(de))
479 k = manager_add_user_by_name(m, de->d_name, NULL);
481 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
491 int manager_enumerate_users(Manager *m) {
498 /* First, enumerate user cgroups */
499 r = manager_enumerate_users_from_cgroup(m);
501 /* Second, add lingering users on top */
502 k = manager_enumerate_linger_users(m);
506 /* Third, read in user data stored on disk */
507 d = opendir("/run/systemd/users");
512 log_error("Failed to open /run/systemd/users: %m");
516 while ((de = readdir(d))) {
520 if (!dirent_is_file(de))
523 k = parse_uid(de->d_name, &uid);
525 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
529 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
531 unlinkat(dirfd(d), de->d_name, 0);
545 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
550 HASHMAP_FOREACH(u, m->users, i) {
558 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
563 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
568 while ((k = cg_read_subgroup(d, &name)) > 0) {
571 if (streq(name, "shared"))
574 k = manager_add_session(m, u, name, &session);
580 session_add_to_gc_queue(session);
582 if (!session->cgroup_path)
583 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
601 int manager_enumerate_sessions(Manager *m) {
608 /* First enumerate session cgroups */
609 r = manager_enumerate_sessions_from_cgroup(m);
611 /* Second, read in session data stored on disk */
612 d = opendir("/run/systemd/sessions");
617 log_error("Failed to open /run/systemd/sessions: %m");
621 while ((de = readdir(d))) {
625 if (!dirent_is_file(de))
628 s = hashmap_get(m->sessions, de->d_name);
630 unlinkat(dirfd(d), de->d_name, 0);
644 int manager_dispatch_seat_udev(Manager *m) {
645 struct udev_device *d;
650 d = udev_monitor_receive_device(m->udev_seat_monitor);
654 r = manager_process_seat_device(m, d);
655 udev_device_unref(d);
660 int manager_dispatch_vcsa_udev(Manager *m) {
661 struct udev_device *d;
667 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
671 name = udev_device_get_sysname(d);
673 /* Whenever a VCSA device is removed try to reallocate our
674 * VTs, to make sure our auto VTs never go away. */
676 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
677 r = seat_preallocate_vts(m->vtconsole);
679 udev_device_unref(d);
684 int manager_dispatch_console(Manager *m) {
688 seat_read_active_vt(m->vtconsole);
693 static int vt_is_busy(int vtnr) {
694 struct vt_stat vt_stat;
699 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
700 * we'd open the latter we'd open the foreground tty which
701 * hence would be unconditionally busy. By opening /dev/tty1
702 * we avoid this. Since tty1 is special and needs to be an
703 * explicitly loaded getty or DM this is safe. */
705 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
709 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
712 r = !!(vt_stat.v_state & (1 << vtnr));
714 close_nointr_nofail(fd);
719 int manager_spawn_autovt(Manager *m, int vtnr) {
721 DBusMessage *message = NULL, *reply = NULL;
723 const char *mode = "fail";
729 dbus_error_init(&error);
731 if ((unsigned) vtnr > m->n_autovts)
734 r = vt_is_busy(vtnr);
740 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
742 log_error("Could not allocate message.");
747 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
748 log_error("Could not allocate service name.");
753 if (!dbus_message_append_args(message,
754 DBUS_TYPE_STRING, &name,
755 DBUS_TYPE_STRING, &mode,
756 DBUS_TYPE_INVALID)) {
757 log_error("Could not attach target and flag information to message.");
762 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
764 log_error("Failed to start unit: %s", bus_error_message(&error));
774 dbus_message_unref(message);
777 dbus_message_unref(reply);
779 dbus_error_free(&error);
784 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
792 s = hashmap_get(m->cgroups, cgroup);
800 log_error("Out of memory.");
816 s = hashmap_get(m->cgroups, p);
825 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
833 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
837 r = manager_get_session_by_cgroup(m, p, session);
843 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
847 r = manager_get_session_by_cgroup(m, cgroup, &s);
851 session_add_to_gc_queue(s);
854 static void manager_pipe_notify_eof(Manager *m, int fd) {
860 assert_se(s = hashmap_get(m->fifo_fds, INT_TO_PTR(fd + 1)));
861 assert(s->fifo_fd == fd);
862 session_remove_fifo(s);
867 static int manager_connect_bus(Manager *m) {
870 struct epoll_event ev;
874 assert(m->bus_fd < 0);
876 dbus_error_init(&error);
878 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
880 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
885 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
886 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
887 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
888 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
889 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
890 log_error("Not enough memory");
895 dbus_bus_add_match(m->bus,
897 "interface='org.freedesktop.systemd1.Agent',"
899 "path='/org/freedesktop/systemd1/agent'",
902 if (dbus_error_is_set(&error)) {
903 log_error("Failed to register match: %s", bus_error_message(&error));
908 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
909 if (dbus_error_is_set(&error)) {
910 log_error("Failed to register name on bus: %s", bus_error_message(&error));
915 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
916 log_error("Failed to acquire name.");
921 m->bus_fd = bus_loop_open(m->bus);
929 ev.data.u32 = FD_BUS;
931 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
937 dbus_error_free(&error);
942 static int manager_connect_console(Manager *m) {
943 struct epoll_event ev;
946 assert(m->console_active_fd < 0);
948 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
949 if (m->console_active_fd < 0) {
951 /* On certain architectures (S390 and Xen), /dev/tty0
952 does not exist, so don't fail if we can't open it.*/
956 log_error("Failed to open /sys/class/tty/tty0/active: %m");
962 ev.data.u32 = FD_CONSOLE;
964 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
970 static int manager_connect_udev(Manager *m) {
971 struct epoll_event ev;
975 assert(!m->udev_seat_monitor);
976 assert(!m->udev_vcsa_monitor);
978 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
979 if (!m->udev_seat_monitor)
982 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
986 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
990 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
994 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
998 ev.data.u32 = FD_SEAT_UDEV;
1000 /* Don't bother watching VCSA devices, if nobody cares */
1001 if (m->n_autovts <= 0 || m->console_active_fd < 0)
1004 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1007 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1008 if (!m->udev_vcsa_monitor)
1011 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1015 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1019 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1022 ev.events = EPOLLIN;
1023 ev.data.u32 = FD_VCSA_UDEV;
1025 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1031 void manager_gc(Manager *m, bool drop_not_started) {
1038 while ((seat = m->seat_gc_queue)) {
1039 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1040 seat->in_gc_queue = false;
1042 if (seat_check_gc(seat, drop_not_started) == 0) {
1048 while ((session = m->session_gc_queue)) {
1049 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1050 session->in_gc_queue = false;
1052 if (session_check_gc(session, drop_not_started) == 0) {
1053 session_stop(session);
1054 session_free(session);
1058 while ((user = m->user_gc_queue)) {
1059 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1060 user->in_gc_queue = false;
1062 if (user_check_gc(user, drop_not_started) == 0) {
1069 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1071 bool idle_hint = true;
1072 dual_timestamp ts = { 0, 0 };
1077 HASHMAP_FOREACH(s, m->sessions, i) {
1081 ih = session_get_idle_hint(s, &k);
1087 if (k.monotonic < ts.monotonic)
1093 } else if (idle_hint) {
1095 if (k.monotonic > ts.monotonic)
1106 int manager_startup(Manager *m) {
1114 assert(m->epoll_fd <= 0);
1116 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1117 if (m->epoll_fd < 0)
1120 /* Connect to console */
1121 r = manager_connect_console(m);
1125 /* Connect to udev */
1126 r = manager_connect_udev(m);
1130 /* Connect to the bus */
1131 r = manager_connect_bus(m);
1135 /* Instantiate magic seat 0 */
1136 r = manager_add_seat(m, "seat0", &m->vtconsole);
1140 /* Deserialize state */
1141 manager_enumerate_devices(m);
1142 manager_enumerate_seats(m);
1143 manager_enumerate_users(m);
1144 manager_enumerate_sessions(m);
1146 /* Remove stale objects before we start them */
1147 manager_gc(m, false);
1149 /* And start everything */
1150 HASHMAP_FOREACH(seat, m->seats, i)
1153 HASHMAP_FOREACH(user, m->users, i)
1156 HASHMAP_FOREACH(session, m->sessions, i)
1157 session_start(session);
1162 int manager_run(Manager *m) {
1166 struct epoll_event event;
1169 manager_gc(m, true);
1171 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1174 manager_gc(m, true);
1176 n = epoll_wait(m->epoll_fd, &event, 1, -1);
1178 if (errno == EINTR || errno == EAGAIN)
1181 log_error("epoll() failed: %m");
1185 switch (event.data.u32) {
1188 manager_dispatch_seat_udev(m);
1192 manager_dispatch_vcsa_udev(m);
1196 manager_dispatch_console(m);
1200 bus_loop_dispatch(m->bus_fd);
1204 if (event.data.u32 >= FD_FIFO_BASE)
1205 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1212 static int manager_parse_config_file(Manager *m) {
1219 fn = "/etc/systemd/logind.conf";
1220 f = fopen(fn, "re");
1222 if (errno == ENOENT)
1225 log_warning("Failed to open configuration file %s: %m", fn);
1229 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1231 log_warning("Failed to parse configuration file: %s", strerror(-r));
1238 int main(int argc, char *argv[]) {
1242 log_set_target(LOG_TARGET_AUTO);
1243 log_set_facility(LOG_AUTH);
1244 log_parse_environment();
1250 log_error("This program takes no arguments.");
1257 log_error("Out of memory");
1262 manager_parse_config_file(m);
1264 r = manager_startup(m);
1266 log_error("Failed to fully start up daemon: %s", strerror(-r));
1270 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1274 "STATUS=Processing requests...");
1278 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1282 "STATUS=Shutting down...");
1287 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;