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 /* On certain architectures (S390 and Xen, and containers),
949 /dev/tty0 does not exist, so don't fail if we can't open
951 if (access("/dev/tty0", F_OK) < 0) {
952 m->console_active_fd = -1;
956 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
957 if (m->console_active_fd < 0) {
958 log_error("Failed to open /sys/class/tty/tty0/active: %m");
964 ev.data.u32 = FD_CONSOLE;
966 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
972 static int manager_connect_udev(Manager *m) {
973 struct epoll_event ev;
977 assert(!m->udev_seat_monitor);
978 assert(!m->udev_vcsa_monitor);
980 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
981 if (!m->udev_seat_monitor)
984 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
988 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
992 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
996 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1000 ev.data.u32 = FD_SEAT_UDEV;
1002 /* Don't bother watching VCSA devices, if nobody cares */
1003 if (m->n_autovts <= 0 || m->console_active_fd < 0)
1006 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1009 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1010 if (!m->udev_vcsa_monitor)
1013 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1017 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1021 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1024 ev.events = EPOLLIN;
1025 ev.data.u32 = FD_VCSA_UDEV;
1027 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1033 void manager_gc(Manager *m, bool drop_not_started) {
1040 while ((seat = m->seat_gc_queue)) {
1041 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1042 seat->in_gc_queue = false;
1044 if (seat_check_gc(seat, drop_not_started) == 0) {
1050 while ((session = m->session_gc_queue)) {
1051 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1052 session->in_gc_queue = false;
1054 if (session_check_gc(session, drop_not_started) == 0) {
1055 session_stop(session);
1056 session_free(session);
1060 while ((user = m->user_gc_queue)) {
1061 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1062 user->in_gc_queue = false;
1064 if (user_check_gc(user, drop_not_started) == 0) {
1071 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1073 bool idle_hint = true;
1074 dual_timestamp ts = { 0, 0 };
1079 HASHMAP_FOREACH(s, m->sessions, i) {
1083 ih = session_get_idle_hint(s, &k);
1089 if (k.monotonic < ts.monotonic)
1095 } else if (idle_hint) {
1097 if (k.monotonic > ts.monotonic)
1108 int manager_startup(Manager *m) {
1116 assert(m->epoll_fd <= 0);
1118 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1119 if (m->epoll_fd < 0)
1122 /* Connect to console */
1123 r = manager_connect_console(m);
1127 /* Connect to udev */
1128 r = manager_connect_udev(m);
1132 /* Connect to the bus */
1133 r = manager_connect_bus(m);
1137 /* Instantiate magic seat 0 */
1138 r = manager_add_seat(m, "seat0", &m->vtconsole);
1142 /* Deserialize state */
1143 manager_enumerate_devices(m);
1144 manager_enumerate_seats(m);
1145 manager_enumerate_users(m);
1146 manager_enumerate_sessions(m);
1148 /* Remove stale objects before we start them */
1149 manager_gc(m, false);
1151 /* And start everything */
1152 HASHMAP_FOREACH(seat, m->seats, i)
1155 HASHMAP_FOREACH(user, m->users, i)
1158 HASHMAP_FOREACH(session, m->sessions, i)
1159 session_start(session);
1164 int manager_run(Manager *m) {
1168 struct epoll_event event;
1171 manager_gc(m, true);
1173 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1176 manager_gc(m, true);
1178 n = epoll_wait(m->epoll_fd, &event, 1, -1);
1180 if (errno == EINTR || errno == EAGAIN)
1183 log_error("epoll() failed: %m");
1187 switch (event.data.u32) {
1190 manager_dispatch_seat_udev(m);
1194 manager_dispatch_vcsa_udev(m);
1198 manager_dispatch_console(m);
1202 bus_loop_dispatch(m->bus_fd);
1206 if (event.data.u32 >= FD_FIFO_BASE)
1207 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1214 static int manager_parse_config_file(Manager *m) {
1221 fn = "/etc/systemd/logind.conf";
1222 f = fopen(fn, "re");
1224 if (errno == ENOENT)
1227 log_warning("Failed to open configuration file %s: %m", fn);
1231 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1233 log_warning("Failed to parse configuration file: %s", strerror(-r));
1240 int main(int argc, char *argv[]) {
1244 log_set_target(LOG_TARGET_AUTO);
1245 log_set_facility(LOG_AUTH);
1246 log_parse_environment();
1252 log_error("This program takes no arguments.");
1259 log_error("Out of memory");
1264 manager_parse_config_file(m);
1266 r = manager_startup(m);
1268 log_error("Failed to fully start up daemon: %s", strerror(-r));
1272 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1276 "STATUS=Processing requests...");
1280 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1284 "STATUS=Shutting down...");
1289 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;