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;
53 m->inhibit_delay_max = 5 * USEC_PER_SEC;
55 m->devices = hashmap_new(string_hash_func, string_compare_func);
56 m->seats = hashmap_new(string_hash_func, string_compare_func);
57 m->sessions = hashmap_new(string_hash_func, string_compare_func);
58 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
59 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
61 m->cgroups = hashmap_new(string_hash_func, string_compare_func);
62 m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
63 m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
65 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors ||
66 !m->cgroups || !m->session_fds || !m->inhibitor_fds) {
71 m->reset_controllers = strv_new("cpu", NULL);
72 m->kill_exclude_users = strv_new("root", NULL);
73 if (!m->reset_controllers || !m->kill_exclude_users) {
84 if (cg_get_user_path(&m->cgroup_path) < 0) {
92 void manager_free(Manager *m) {
101 while ((session = hashmap_first(m->sessions)))
102 session_free(session);
104 while ((u = hashmap_first(m->users)))
107 while ((d = hashmap_first(m->devices)))
110 while ((s = hashmap_first(m->seats)))
113 while ((i = hashmap_first(m->inhibitors)))
116 hashmap_free(m->devices);
117 hashmap_free(m->seats);
118 hashmap_free(m->sessions);
119 hashmap_free(m->users);
120 hashmap_free(m->inhibitors);
122 hashmap_free(m->cgroups);
123 hashmap_free(m->session_fds);
124 hashmap_free(m->inhibitor_fds);
126 if (m->console_active_fd >= 0)
127 close_nointr_nofail(m->console_active_fd);
129 if (m->udev_seat_monitor)
130 udev_monitor_unref(m->udev_seat_monitor);
132 if (m->udev_vcsa_monitor)
133 udev_monitor_unref(m->udev_vcsa_monitor);
139 dbus_connection_flush(m->bus);
140 dbus_connection_close(m->bus);
141 dbus_connection_unref(m->bus);
145 close_nointr_nofail(m->bus_fd);
147 if (m->epoll_fd >= 0)
148 close_nointr_nofail(m->epoll_fd);
150 strv_free(m->controllers);
151 strv_free(m->reset_controllers);
152 strv_free(m->kill_only_users);
153 strv_free(m->kill_exclude_users);
155 free(m->cgroup_path);
159 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
165 d = hashmap_get(m->devices, sysfs);
173 d = device_new(m, sysfs);
183 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
189 s = hashmap_get(m->seats, id);
207 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
213 s = hashmap_get(m->sessions, id);
221 s = session_new(m, u, id);
231 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
237 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
245 u = user_new(m, uid, gid, name);
255 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
263 r = get_user_creds(&name, &uid, &gid, NULL);
267 return manager_add_user(m, uid, gid, name, _user);
270 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
278 return errno ? -errno : -ENOENT;
280 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
283 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
289 i = hashmap_get(m->inhibitors, id);
297 i = inhibitor_new(m, id);
307 int manager_process_seat_device(Manager *m, struct udev_device *d) {
313 if (streq_ptr(udev_device_get_action(d), "remove")) {
315 device = hashmap_get(m->devices, udev_device_get_syspath(d));
319 seat_add_to_gc_queue(device->seat);
326 sn = udev_device_get_property_value(d, "ID_SEAT");
330 if (!seat_name_is_valid(sn)) {
331 log_warning("Device with invalid seat name %s found, ignoring.", sn);
335 r = manager_add_device(m, udev_device_get_syspath(d), &device);
339 r = manager_add_seat(m, sn, &seat);
347 device_attach(device, seat);
354 int manager_enumerate_devices(Manager *m) {
355 struct udev_list_entry *item = NULL, *first = NULL;
356 struct udev_enumerate *e;
361 /* Loads devices from udev and creates seats for them as
364 e = udev_enumerate_new(m->udev);
370 r = udev_enumerate_add_match_subsystem(e, "graphics");
374 r = udev_enumerate_add_match_tag(e, "seat");
378 r = udev_enumerate_scan_devices(e);
382 first = udev_enumerate_get_list_entry(e);
383 udev_list_entry_foreach(item, first) {
384 struct udev_device *d;
387 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
393 k = manager_process_seat_device(m, d);
394 udev_device_unref(d);
402 udev_enumerate_unref(e);
407 int manager_enumerate_seats(Manager *m) {
414 /* This loads data about seats stored on disk, but does not
415 * actually create any seats. Removes data of seats that no
418 d = opendir("/run/systemd/seats");
423 log_error("Failed to open /run/systemd/seats: %m");
427 while ((de = readdir(d))) {
431 if (!dirent_is_file(de))
434 s = hashmap_get(m->seats, de->d_name);
436 unlinkat(dirfd(d), de->d_name, 0);
450 static int manager_enumerate_users_from_cgroup(Manager *m) {
455 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
460 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
464 while ((k = cg_read_subgroup(d, &name)) > 0) {
467 k = manager_add_user_by_name(m, name, &user);
474 user_add_to_gc_queue(user);
476 if (!user->cgroup_path)
477 if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
494 static int manager_enumerate_linger_users(Manager *m) {
499 d = opendir("/var/lib/systemd/linger");
504 log_error("Failed to open /var/lib/systemd/linger/: %m");
508 while ((de = readdir(d))) {
511 if (!dirent_is_file(de))
514 k = manager_add_user_by_name(m, de->d_name, NULL);
516 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
526 int manager_enumerate_users(Manager *m) {
533 /* First, enumerate user cgroups */
534 r = manager_enumerate_users_from_cgroup(m);
536 /* Second, add lingering users on top */
537 k = manager_enumerate_linger_users(m);
541 /* Third, read in user data stored on disk */
542 d = opendir("/run/systemd/users");
547 log_error("Failed to open /run/systemd/users: %m");
551 while ((de = readdir(d))) {
555 if (!dirent_is_file(de))
558 k = parse_uid(de->d_name, &uid);
560 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
564 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
566 unlinkat(dirfd(d), de->d_name, 0);
580 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
585 HASHMAP_FOREACH(u, m->users, i) {
593 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
598 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
603 while ((k = cg_read_subgroup(d, &name)) > 0) {
606 if (streq(name, "shared"))
609 k = manager_add_session(m, u, name, &session);
615 session_add_to_gc_queue(session);
617 if (!session->cgroup_path)
618 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
636 int manager_enumerate_sessions(Manager *m) {
643 /* First enumerate session cgroups */
644 r = manager_enumerate_sessions_from_cgroup(m);
646 /* Second, read in session data stored on disk */
647 d = opendir("/run/systemd/sessions");
652 log_error("Failed to open /run/systemd/sessions: %m");
656 while ((de = readdir(d))) {
660 if (!dirent_is_file(de))
663 s = hashmap_get(m->sessions, de->d_name);
665 unlinkat(dirfd(d), de->d_name, 0);
679 int manager_enumerate_inhibitors(Manager *m) {
686 d = opendir("/run/systemd/inhibit");
691 log_error("Failed to open /run/systemd/inhibit: %m");
695 while ((de = readdir(d))) {
699 if (!dirent_is_file(de))
702 k = manager_add_inhibitor(m, de->d_name, &i);
704 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
709 k = inhibitor_load(i);
719 int manager_dispatch_seat_udev(Manager *m) {
720 struct udev_device *d;
725 d = udev_monitor_receive_device(m->udev_seat_monitor);
729 r = manager_process_seat_device(m, d);
730 udev_device_unref(d);
735 int manager_dispatch_vcsa_udev(Manager *m) {
736 struct udev_device *d;
742 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
746 name = udev_device_get_sysname(d);
748 /* Whenever a VCSA device is removed try to reallocate our
749 * VTs, to make sure our auto VTs never go away. */
751 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
752 r = seat_preallocate_vts(m->vtconsole);
754 udev_device_unref(d);
759 int manager_dispatch_console(Manager *m) {
763 seat_read_active_vt(m->vtconsole);
768 static int vt_is_busy(int vtnr) {
769 struct vt_stat vt_stat;
774 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
775 * we'd open the latter we'd open the foreground tty which
776 * hence would be unconditionally busy. By opening /dev/tty1
777 * we avoid this. Since tty1 is special and needs to be an
778 * explicitly loaded getty or DM this is safe. */
780 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
784 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
787 r = !!(vt_stat.v_state & (1 << vtnr));
789 close_nointr_nofail(fd);
794 int manager_spawn_autovt(Manager *m, int vtnr) {
796 DBusMessage *message = NULL, *reply = NULL;
798 const char *mode = "fail";
804 dbus_error_init(&error);
806 if ((unsigned) vtnr > m->n_autovts)
809 r = vt_is_busy(vtnr);
815 message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
817 log_error("Could not allocate message.");
822 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
823 log_error("Could not allocate service name.");
828 if (!dbus_message_append_args(message,
829 DBUS_TYPE_STRING, &name,
830 DBUS_TYPE_STRING, &mode,
831 DBUS_TYPE_INVALID)) {
832 log_error("Could not attach target and flag information to message.");
837 reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
839 log_error("Failed to start unit: %s", bus_error_message(&error));
849 dbus_message_unref(message);
852 dbus_message_unref(reply);
854 dbus_error_free(&error);
859 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
867 s = hashmap_get(m->cgroups, cgroup);
875 log_error("Out of memory.");
891 s = hashmap_get(m->cgroups, p);
900 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
908 r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
912 r = manager_get_session_by_cgroup(m, p, session);
918 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
922 r = manager_get_session_by_cgroup(m, cgroup, &s);
926 session_add_to_gc_queue(s);
929 static void manager_pipe_notify_eof(Manager *m, int fd) {
936 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
938 assert(s->fifo_fd == fd);
939 session_remove_fifo(s);
944 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
946 assert(i->fifo_fd == fd);
952 assert_not_reached("Got EOF on unknown pipe");
955 static int manager_connect_bus(Manager *m) {
958 struct epoll_event ev;
962 assert(m->bus_fd < 0);
964 dbus_error_init(&error);
966 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
968 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
973 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
974 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
975 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
976 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
977 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
978 log_error("Not enough memory");
983 dbus_bus_add_match(m->bus,
985 "interface='org.freedesktop.systemd1.Agent',"
987 "path='/org/freedesktop/systemd1/agent'",
990 if (dbus_error_is_set(&error)) {
991 log_error("Failed to register match: %s", bus_error_message(&error));
996 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
997 if (dbus_error_is_set(&error)) {
998 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1003 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1004 log_error("Failed to acquire name.");
1009 m->bus_fd = bus_loop_open(m->bus);
1010 if (m->bus_fd < 0) {
1016 ev.events = EPOLLIN;
1017 ev.data.u32 = FD_BUS;
1019 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1025 dbus_error_free(&error);
1030 static int manager_connect_console(Manager *m) {
1031 struct epoll_event ev;
1034 assert(m->console_active_fd < 0);
1036 /* On certain architectures (S390 and Xen, and containers),
1037 /dev/tty0 does not exist, so don't fail if we can't open
1039 if (access("/dev/tty0", F_OK) < 0) {
1040 m->console_active_fd = -1;
1044 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1045 if (m->console_active_fd < 0) {
1046 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1052 ev.data.u32 = FD_CONSOLE;
1054 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1060 static int manager_connect_udev(Manager *m) {
1061 struct epoll_event ev;
1065 assert(!m->udev_seat_monitor);
1066 assert(!m->udev_vcsa_monitor);
1068 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1069 if (!m->udev_seat_monitor)
1072 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1076 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1080 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1084 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1087 ev.events = EPOLLIN;
1088 ev.data.u32 = FD_SEAT_UDEV;
1090 /* Don't bother watching VCSA devices, if nobody cares */
1091 if (m->n_autovts <= 0 || m->console_active_fd < 0)
1094 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1097 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1098 if (!m->udev_vcsa_monitor)
1101 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1105 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1109 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1112 ev.events = EPOLLIN;
1113 ev.data.u32 = FD_VCSA_UDEV;
1115 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1121 void manager_gc(Manager *m, bool drop_not_started) {
1128 while ((seat = m->seat_gc_queue)) {
1129 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1130 seat->in_gc_queue = false;
1132 if (seat_check_gc(seat, drop_not_started) == 0) {
1138 while ((session = m->session_gc_queue)) {
1139 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1140 session->in_gc_queue = false;
1142 if (session_check_gc(session, drop_not_started) == 0) {
1143 session_stop(session);
1144 session_free(session);
1148 while ((user = m->user_gc_queue)) {
1149 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1150 user->in_gc_queue = false;
1152 if (user_check_gc(user, drop_not_started) == 0) {
1159 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1162 dual_timestamp ts = { 0, 0 };
1167 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1169 HASHMAP_FOREACH(s, m->sessions, i) {
1173 ih = session_get_idle_hint(s, &k);
1179 if (k.monotonic < ts.monotonic)
1185 } else if (idle_hint) {
1187 if (k.monotonic > ts.monotonic)
1198 int manager_startup(Manager *m) {
1203 Inhibitor *inhibitor;
1207 assert(m->epoll_fd <= 0);
1209 cg_shorten_controllers(m->reset_controllers);
1210 cg_shorten_controllers(m->controllers);
1212 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1213 if (m->epoll_fd < 0)
1216 /* Connect to console */
1217 r = manager_connect_console(m);
1221 /* Connect to udev */
1222 r = manager_connect_udev(m);
1226 /* Connect to the bus */
1227 r = manager_connect_bus(m);
1231 /* Instantiate magic seat 0 */
1232 r = manager_add_seat(m, "seat0", &m->vtconsole);
1236 /* Deserialize state */
1237 manager_enumerate_devices(m);
1238 manager_enumerate_seats(m);
1239 manager_enumerate_users(m);
1240 manager_enumerate_sessions(m);
1241 manager_enumerate_inhibitors(m);
1243 /* Remove stale objects before we start them */
1244 manager_gc(m, false);
1246 /* And start everything */
1247 HASHMAP_FOREACH(seat, m->seats, i)
1250 HASHMAP_FOREACH(user, m->users, i)
1253 HASHMAP_FOREACH(session, m->sessions, i)
1254 session_start(session);
1256 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1257 inhibitor_start(inhibitor);
1262 int manager_run(Manager *m) {
1266 struct epoll_event event;
1270 manager_gc(m, true);
1272 if (manager_dispatch_delayed(m) > 0)
1275 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1278 manager_gc(m, true);
1280 if (m->delayed_unit) {
1283 x = now(CLOCK_MONOTONIC);
1284 y = m->delayed_timestamp + m->inhibit_delay_max;
1286 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1289 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1291 if (errno == EINTR || errno == EAGAIN)
1294 log_error("epoll() failed: %m");
1301 switch (event.data.u32) {
1304 manager_dispatch_seat_udev(m);
1308 manager_dispatch_vcsa_udev(m);
1312 manager_dispatch_console(m);
1316 bus_loop_dispatch(m->bus_fd);
1320 if (event.data.u32 >= FD_FIFO_BASE)
1321 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1328 static int manager_parse_config_file(Manager *m) {
1335 fn = "/etc/systemd/logind.conf";
1336 f = fopen(fn, "re");
1338 if (errno == ENOENT)
1341 log_warning("Failed to open configuration file %s: %m", fn);
1345 r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1347 log_warning("Failed to parse configuration file: %s", strerror(-r));
1354 int main(int argc, char *argv[]) {
1358 log_set_target(LOG_TARGET_AUTO);
1359 log_set_facility(LOG_AUTH);
1360 log_parse_environment();
1366 log_error("This program takes no arguments.");
1373 log_error("Out of memory");
1378 manager_parse_config_file(m);
1380 r = manager_startup(m);
1382 log_error("Failed to fully start up daemon: %s", strerror(-r));
1386 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1390 "STATUS=Processing requests...");
1394 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1398 "STATUS=Shutting down...");
1403 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;