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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU 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_parse_environment();
1249 log_error("This program takes no arguments.");
1256 log_error("Out of memory");
1261 manager_parse_config_file(m
);
1263 r
= manager_startup(m
);
1265 log_error("Failed to fully start up daemon: %s", strerror(-r
));
1269 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1273 "STATUS=Processing requests...");
1277 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1281 "STATUS=Shutting down...");
1286 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;