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;
51 m
->udev_button_fd
= -1;
53 m
->reserve_vt_fd
= -1;
57 m
->inhibit_delay_max
= 5 * USEC_PER_SEC
;
58 m
->handle_power_key
= HANDLE_NO_SESSION
;
59 m
->handle_sleep_key
= HANDLE_TTY_SESSION
;
60 m
->handle_lid_switch
= HANDLE_OFF
;
62 m
->devices
= hashmap_new(string_hash_func
, string_compare_func
);
63 m
->seats
= hashmap_new(string_hash_func
, string_compare_func
);
64 m
->sessions
= hashmap_new(string_hash_func
, string_compare_func
);
65 m
->users
= hashmap_new(trivial_hash_func
, trivial_compare_func
);
66 m
->inhibitors
= hashmap_new(string_hash_func
, string_compare_func
);
67 m
->buttons
= hashmap_new(string_hash_func
, string_compare_func
);
69 m
->user_cgroups
= hashmap_new(string_hash_func
, string_compare_func
);
70 m
->session_cgroups
= hashmap_new(string_hash_func
, string_compare_func
);
72 m
->session_fds
= hashmap_new(trivial_hash_func
, trivial_compare_func
);
73 m
->inhibitor_fds
= hashmap_new(trivial_hash_func
, trivial_compare_func
);
74 m
->button_fds
= hashmap_new(trivial_hash_func
, trivial_compare_func
);
76 if (!m
->devices
|| !m
->seats
|| !m
->sessions
|| !m
->users
|| !m
->inhibitors
|| !m
->buttons
||
77 !m
->user_cgroups
|| !m
->session_cgroups
||
78 !m
->session_fds
|| !m
->inhibitor_fds
|| !m
->button_fds
) {
83 m
->reset_controllers
= strv_new("cpu", NULL
);
84 m
->kill_exclude_users
= strv_new("root", NULL
);
85 if (!m
->reset_controllers
|| !m
->kill_exclude_users
) {
96 if (cg_get_user_path(&m
->cgroup_path
) < 0) {
104 void manager_free(Manager
*m
) {
114 while ((session
= hashmap_first(m
->sessions
)))
115 session_free(session
);
117 while ((u
= hashmap_first(m
->users
)))
120 while ((d
= hashmap_first(m
->devices
)))
123 while ((s
= hashmap_first(m
->seats
)))
126 while ((i
= hashmap_first(m
->inhibitors
)))
129 while ((b
= hashmap_first(m
->buttons
)))
132 hashmap_free(m
->devices
);
133 hashmap_free(m
->seats
);
134 hashmap_free(m
->sessions
);
135 hashmap_free(m
->users
);
136 hashmap_free(m
->inhibitors
);
137 hashmap_free(m
->buttons
);
139 hashmap_free(m
->user_cgroups
);
140 hashmap_free(m
->session_cgroups
);
142 hashmap_free(m
->session_fds
);
143 hashmap_free(m
->inhibitor_fds
);
144 hashmap_free(m
->button_fds
);
146 if (m
->console_active_fd
>= 0)
147 close_nointr_nofail(m
->console_active_fd
);
149 if (m
->udev_seat_monitor
)
150 udev_monitor_unref(m
->udev_seat_monitor
);
151 if (m
->udev_vcsa_monitor
)
152 udev_monitor_unref(m
->udev_vcsa_monitor
);
153 if (m
->udev_button_monitor
)
154 udev_monitor_unref(m
->udev_button_monitor
);
160 dbus_connection_flush(m
->bus
);
161 dbus_connection_close(m
->bus
);
162 dbus_connection_unref(m
->bus
);
166 close_nointr_nofail(m
->bus_fd
);
168 if (m
->epoll_fd
>= 0)
169 close_nointr_nofail(m
->epoll_fd
);
171 if (m
->reserve_vt_fd
>= 0)
172 close_nointr_nofail(m
->reserve_vt_fd
);
174 strv_free(m
->controllers
);
175 strv_free(m
->reset_controllers
);
176 strv_free(m
->kill_only_users
);
177 strv_free(m
->kill_exclude_users
);
179 free(m
->cgroup_path
);
183 int manager_add_device(Manager
*m
, const char *sysfs
, Device
**_device
) {
189 d
= hashmap_get(m
->devices
, sysfs
);
197 d
= device_new(m
, sysfs
);
207 int manager_add_seat(Manager
*m
, const char *id
, Seat
**_seat
) {
213 s
= hashmap_get(m
->seats
, id
);
231 int manager_add_session(Manager
*m
, User
*u
, const char *id
, Session
**_session
) {
237 s
= hashmap_get(m
->sessions
, id
);
245 s
= session_new(m
, u
, id
);
255 int manager_add_user(Manager
*m
, uid_t uid
, gid_t gid
, const char *name
, User
**_user
) {
261 u
= hashmap_get(m
->users
, ULONG_TO_PTR((unsigned long) uid
));
269 u
= user_new(m
, uid
, gid
, name
);
279 int manager_add_user_by_name(Manager
*m
, const char *name
, User
**_user
) {
287 r
= get_user_creds(&name
, &uid
, &gid
, NULL
, NULL
);
291 return manager_add_user(m
, uid
, gid
, name
, _user
);
294 int manager_add_user_by_uid(Manager
*m
, uid_t uid
, User
**_user
) {
302 return errno
? -errno
: -ENOENT
;
304 return manager_add_user(m
, uid
, p
->pw_gid
, p
->pw_name
, _user
);
307 int manager_add_inhibitor(Manager
*m
, const char* id
, Inhibitor
**_inhibitor
) {
313 i
= hashmap_get(m
->inhibitors
, id
);
321 i
= inhibitor_new(m
, id
);
331 int manager_add_button(Manager
*m
, const char *name
, Button
**_button
) {
337 b
= hashmap_get(m
->buttons
, name
);
345 b
= button_new(m
, name
);
355 int manager_process_seat_device(Manager
*m
, struct udev_device
*d
) {
361 if (streq_ptr(udev_device_get_action(d
), "remove")) {
363 device
= hashmap_get(m
->devices
, udev_device_get_syspath(d
));
367 seat_add_to_gc_queue(device
->seat
);
374 sn
= udev_device_get_property_value(d
, "ID_SEAT");
378 if (!seat_name_is_valid(sn
)) {
379 log_warning("Device with invalid seat name %s found, ignoring.", sn
);
383 r
= manager_add_device(m
, udev_device_get_syspath(d
), &device
);
387 r
= manager_add_seat(m
, sn
, &seat
);
395 device_attach(device
, seat
);
402 int manager_process_button_device(Manager
*m
, struct udev_device
*d
) {
409 if (streq_ptr(udev_device_get_action(d
), "remove")) {
411 b
= hashmap_get(m
->buttons
, udev_device_get_sysname(d
));
420 r
= manager_add_button(m
, udev_device_get_sysname(d
), &b
);
424 sn
= udev_device_get_property_value(d
, "ID_SEAT");
428 button_set_seat(b
, sn
);
435 int manager_enumerate_devices(Manager
*m
) {
436 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
437 struct udev_enumerate
*e
;
442 /* Loads devices from udev and creates seats for them as
445 e
= udev_enumerate_new(m
->udev
);
451 r
= udev_enumerate_add_match_subsystem(e
, "graphics");
455 r
= udev_enumerate_add_match_tag(e
, "seat");
459 r
= udev_enumerate_scan_devices(e
);
463 first
= udev_enumerate_get_list_entry(e
);
464 udev_list_entry_foreach(item
, first
) {
465 struct udev_device
*d
;
468 d
= udev_device_new_from_syspath(m
->udev
, udev_list_entry_get_name(item
));
474 k
= manager_process_seat_device(m
, d
);
475 udev_device_unref(d
);
483 udev_enumerate_unref(e
);
488 int manager_enumerate_buttons(Manager
*m
) {
489 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
490 struct udev_enumerate
*e
;
495 /* Loads buttons from udev */
497 if (m
->handle_power_key
== HANDLE_OFF
&&
498 m
->handle_sleep_key
== HANDLE_OFF
&&
499 m
->handle_lid_switch
== HANDLE_OFF
)
502 e
= udev_enumerate_new(m
->udev
);
508 r
= udev_enumerate_add_match_subsystem(e
, "input");
512 r
= udev_enumerate_add_match_tag(e
, "power-switch");
516 r
= udev_enumerate_scan_devices(e
);
520 first
= udev_enumerate_get_list_entry(e
);
521 udev_list_entry_foreach(item
, first
) {
522 struct udev_device
*d
;
525 d
= udev_device_new_from_syspath(m
->udev
, udev_list_entry_get_name(item
));
531 k
= manager_process_button_device(m
, d
);
532 udev_device_unref(d
);
540 udev_enumerate_unref(e
);
545 int manager_enumerate_seats(Manager
*m
) {
552 /* This loads data about seats stored on disk, but does not
553 * actually create any seats. Removes data of seats that no
556 d
= opendir("/run/systemd/seats");
561 log_error("Failed to open /run/systemd/seats: %m");
565 while ((de
= readdir(d
))) {
569 if (!dirent_is_file(de
))
572 s
= hashmap_get(m
->seats
, de
->d_name
);
574 unlinkat(dirfd(d
), de
->d_name
, 0);
588 static int manager_enumerate_users_from_cgroup(Manager
*m
) {
593 r
= cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER
, m
->cgroup_path
, &d
);
598 log_error("Failed to open %s: %s", m
->cgroup_path
, strerror(-r
));
602 while ((k
= cg_read_subgroup(d
, &name
)) > 0) {
605 k
= manager_add_user_by_name(m
, name
, &user
);
612 user_add_to_gc_queue(user
);
614 if (!user
->cgroup_path
)
615 if (asprintf(&user
->cgroup_path
, "%s/%s", m
->cgroup_path
, name
) < 0) {
632 static int manager_enumerate_linger_users(Manager
*m
) {
637 d
= opendir("/var/lib/systemd/linger");
642 log_error("Failed to open /var/lib/systemd/linger/: %m");
646 while ((de
= readdir(d
))) {
649 if (!dirent_is_file(de
))
652 k
= manager_add_user_by_name(m
, de
->d_name
, NULL
);
654 log_notice("Couldn't add lingering user %s: %s", de
->d_name
, strerror(-k
));
664 int manager_enumerate_users(Manager
*m
) {
671 /* First, enumerate user cgroups */
672 r
= manager_enumerate_users_from_cgroup(m
);
674 /* Second, add lingering users on top */
675 k
= manager_enumerate_linger_users(m
);
679 /* Third, read in user data stored on disk */
680 d
= opendir("/run/systemd/users");
685 log_error("Failed to open /run/systemd/users: %m");
689 while ((de
= readdir(d
))) {
693 if (!dirent_is_file(de
))
696 k
= parse_uid(de
->d_name
, &uid
);
698 log_error("Failed to parse file name %s: %s", de
->d_name
, strerror(-k
));
702 u
= hashmap_get(m
->users
, ULONG_TO_PTR(uid
));
704 unlinkat(dirfd(d
), de
->d_name
, 0);
718 static int manager_enumerate_sessions_from_cgroup(Manager
*m
) {
723 HASHMAP_FOREACH(u
, m
->users
, i
) {
731 k
= cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER
, u
->cgroup_path
, &d
);
736 log_error("Failed to open %s: %s", u
->cgroup_path
, strerror(-k
));
741 while ((k
= cg_read_subgroup(d
, &name
)) > 0) {
744 if (streq(name
, "shared"))
747 k
= manager_add_session(m
, u
, name
, &session
);
753 session_add_to_gc_queue(session
);
755 if (!session
->cgroup_path
)
756 if (asprintf(&session
->cgroup_path
, "%s/%s", u
->cgroup_path
, name
) < 0) {
774 int manager_enumerate_sessions(Manager
*m
) {
781 /* First enumerate session cgroups */
782 r
= manager_enumerate_sessions_from_cgroup(m
);
784 /* Second, read in session data stored on disk */
785 d
= opendir("/run/systemd/sessions");
790 log_error("Failed to open /run/systemd/sessions: %m");
794 while ((de
= readdir(d
))) {
798 if (!dirent_is_file(de
))
801 s
= hashmap_get(m
->sessions
, de
->d_name
);
803 unlinkat(dirfd(d
), de
->d_name
, 0);
817 int manager_enumerate_inhibitors(Manager
*m
) {
824 d
= opendir("/run/systemd/inhibit");
829 log_error("Failed to open /run/systemd/inhibit: %m");
833 while ((de
= readdir(d
))) {
837 if (!dirent_is_file(de
))
840 k
= manager_add_inhibitor(m
, de
->d_name
, &i
);
842 log_notice("Couldn't add inhibitor %s: %s", de
->d_name
, strerror(-k
));
847 k
= inhibitor_load(i
);
857 int manager_dispatch_seat_udev(Manager
*m
) {
858 struct udev_device
*d
;
863 d
= udev_monitor_receive_device(m
->udev_seat_monitor
);
867 r
= manager_process_seat_device(m
, d
);
868 udev_device_unref(d
);
873 int manager_dispatch_vcsa_udev(Manager
*m
) {
874 struct udev_device
*d
;
880 d
= udev_monitor_receive_device(m
->udev_vcsa_monitor
);
884 name
= udev_device_get_sysname(d
);
886 /* Whenever a VCSA device is removed try to reallocate our
887 * VTs, to make sure our auto VTs never go away. */
889 if (name
&& startswith(name
, "vcsa") && streq_ptr(udev_device_get_action(d
), "remove"))
890 r
= seat_preallocate_vts(m
->vtconsole
);
892 udev_device_unref(d
);
897 int manager_dispatch_button_udev(Manager
*m
) {
898 struct udev_device
*d
;
903 d
= udev_monitor_receive_device(m
->udev_button_monitor
);
907 r
= manager_process_button_device(m
, d
);
908 udev_device_unref(d
);
913 int manager_dispatch_console(Manager
*m
) {
917 seat_read_active_vt(m
->vtconsole
);
922 static int vt_is_busy(int vtnr
) {
923 struct vt_stat vt_stat
;
928 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
929 * we'd open the latter we'd open the foreground tty which
930 * hence would be unconditionally busy. By opening /dev/tty1
931 * we avoid this. Since tty1 is special and needs to be an
932 * explicitly loaded getty or DM this is safe. */
934 fd
= open_terminal("/dev/tty1", O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
938 if (ioctl(fd
, VT_GETSTATE
, &vt_stat
) < 0)
941 r
= !!(vt_stat
.v_state
& (1 << vtnr
));
943 close_nointr_nofail(fd
);
948 int manager_spawn_autovt(Manager
*m
, int vtnr
) {
951 const char *mode
= "fail";
956 if ((unsigned) vtnr
> m
->n_autovts
&&
957 (unsigned) vtnr
!= m
->reserve_vt
)
960 if ((unsigned) vtnr
!= m
->reserve_vt
) {
961 /* If this is the reserved TTY, we'll start the getty
962 * on it in any case, but otherwise only if it is not
965 r
= vt_is_busy(vtnr
);
972 if (asprintf(&name
, "autovt@tty%i.service", vtnr
) < 0) {
973 log_error("Could not allocate service name.");
978 r
= bus_method_call_with_reply (
980 "org.freedesktop.systemd1",
981 "/org/freedesktop/systemd1",
982 "org.freedesktop.systemd1.Manager",
986 DBUS_TYPE_STRING
, &name
,
987 DBUS_TYPE_STRING
, &mode
,
996 static int manager_reserve_vt(Manager
*m
) {
997 _cleanup_free_
char *p
= NULL
;
1001 if (m
->reserve_vt
<= 0)
1004 if (asprintf(&p
, "/dev/tty%u", m
->reserve_vt
) < 0)
1007 m
->reserve_vt_fd
= open(p
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
|O_NONBLOCK
);
1008 if (m
->reserve_vt_fd
< 0) {
1010 /* Don't complain on VT-less systems */
1011 if (errno
!= ENOENT
)
1012 log_warning("Failed to pin reserved VT: %m");
1019 int manager_get_session_by_cgroup(Manager
*m
, const char *cgroup
, Session
**session
) {
1027 s
= hashmap_get(m
->session_cgroups
, cgroup
);
1040 e
= strrchr(p
, '/');
1049 s
= hashmap_get(m
->session_cgroups
, p
);
1058 int manager_get_user_by_cgroup(Manager
*m
, const char *cgroup
, User
**user
) {
1066 u
= hashmap_get(m
->user_cgroups
, cgroup
);
1079 e
= strrchr(p
, '/');
1088 u
= hashmap_get(m
->user_cgroups
, p
);
1097 int manager_get_session_by_pid(Manager
*m
, pid_t pid
, Session
**session
) {
1105 r
= cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER
, pid
, &p
);
1109 r
= manager_get_session_by_cgroup(m
, p
, session
);
1115 void manager_cgroup_notify_empty(Manager
*m
, const char *cgroup
) {
1120 r
= manager_get_session_by_cgroup(m
, cgroup
, &s
);
1122 session_add_to_gc_queue(s
);
1124 r
= manager_get_user_by_cgroup(m
, cgroup
, &u
);
1126 user_add_to_gc_queue(u
);
1129 static void manager_dispatch_other(Manager
*m
, int fd
) {
1137 s
= hashmap_get(m
->session_fds
, INT_TO_PTR(fd
+ 1));
1139 assert(s
->fifo_fd
== fd
);
1140 session_remove_fifo(s
);
1145 i
= hashmap_get(m
->inhibitor_fds
, INT_TO_PTR(fd
+ 1));
1147 assert(i
->fifo_fd
== fd
);
1153 b
= hashmap_get(m
->button_fds
, INT_TO_PTR(fd
+ 1));
1155 assert(b
->fd
== fd
);
1160 assert_not_reached("Got event for unknown fd");
1163 static int manager_connect_bus(Manager
*m
) {
1166 struct epoll_event ev
;
1170 assert(m
->bus_fd
< 0);
1172 dbus_error_init(&error
);
1174 m
->bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
1176 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error
));
1181 if (!dbus_connection_register_object_path(m
->bus
, "/org/freedesktop/login1", &bus_manager_vtable
, m
) ||
1182 !dbus_connection_register_fallback(m
->bus
, "/org/freedesktop/login1/seat", &bus_seat_vtable
, m
) ||
1183 !dbus_connection_register_fallback(m
->bus
, "/org/freedesktop/login1/session", &bus_session_vtable
, m
) ||
1184 !dbus_connection_register_fallback(m
->bus
, "/org/freedesktop/login1/user", &bus_user_vtable
, m
) ||
1185 !dbus_connection_add_filter(m
->bus
, bus_message_filter
, m
, NULL
)) {
1190 dbus_bus_add_match(m
->bus
,
1192 "interface='org.freedesktop.systemd1.Agent',"
1193 "member='Released',"
1194 "path='/org/freedesktop/systemd1/agent'",
1197 if (dbus_error_is_set(&error
)) {
1198 log_error("Failed to register match: %s", bus_error_message(&error
));
1203 r
= dbus_bus_request_name(m
->bus
, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE
, &error
);
1204 if (dbus_error_is_set(&error
)) {
1205 log_error("Failed to register name on bus: %s", bus_error_message(&error
));
1210 if (r
!= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
) {
1211 log_error("Failed to acquire name.");
1216 m
->bus_fd
= bus_loop_open(m
->bus
);
1217 if (m
->bus_fd
< 0) {
1223 ev
.events
= EPOLLIN
;
1224 ev
.data
.u32
= FD_BUS
;
1226 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->bus_fd
, &ev
) < 0)
1232 dbus_error_free(&error
);
1237 static int manager_connect_console(Manager
*m
) {
1238 struct epoll_event ev
;
1241 assert(m
->console_active_fd
< 0);
1243 /* On certain architectures (S390 and Xen, and containers),
1244 /dev/tty0 does not exist, so don't fail if we can't open
1246 if (access("/dev/tty0", F_OK
) < 0) {
1247 m
->console_active_fd
= -1;
1251 m
->console_active_fd
= open("/sys/class/tty/tty0/active", O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
1252 if (m
->console_active_fd
< 0) {
1254 /* On some systems the device node /dev/tty0 may exist
1255 * even though /sys/class/tty/tty0 does not. */
1256 if (errno
== ENOENT
)
1259 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1265 ev
.data
.u32
= FD_CONSOLE
;
1267 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->console_active_fd
, &ev
) < 0)
1273 static int manager_connect_udev(Manager
*m
) {
1274 struct epoll_event ev
;
1278 assert(!m
->udev_seat_monitor
);
1279 assert(!m
->udev_vcsa_monitor
);
1280 assert(!m
->udev_button_monitor
);
1282 m
->udev_seat_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
1283 if (!m
->udev_seat_monitor
)
1286 r
= udev_monitor_filter_add_match_tag(m
->udev_seat_monitor
, "seat");
1290 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_seat_monitor
, "graphics", NULL
);
1294 r
= udev_monitor_enable_receiving(m
->udev_seat_monitor
);
1298 m
->udev_seat_fd
= udev_monitor_get_fd(m
->udev_seat_monitor
);
1301 ev
.events
= EPOLLIN
;
1302 ev
.data
.u32
= FD_SEAT_UDEV
;
1303 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->udev_seat_fd
, &ev
) < 0)
1306 /* Don't watch keys if nobody cares */
1307 if (m
->handle_power_key
!= HANDLE_OFF
||
1308 m
->handle_sleep_key
!= HANDLE_OFF
||
1309 m
->handle_lid_switch
!= HANDLE_OFF
) {
1311 m
->udev_button_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
1312 if (!m
->udev_button_monitor
)
1315 r
= udev_monitor_filter_add_match_tag(m
->udev_button_monitor
, "power-switch");
1319 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_button_monitor
, "input", NULL
);
1323 r
= udev_monitor_enable_receiving(m
->udev_button_monitor
);
1327 m
->udev_button_fd
= udev_monitor_get_fd(m
->udev_button_monitor
);
1330 ev
.events
= EPOLLIN
;
1331 ev
.data
.u32
= FD_BUTTON_UDEV
;
1332 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->udev_button_fd
, &ev
) < 0)
1336 /* Don't bother watching VCSA devices, if nobody cares */
1337 if (m
->n_autovts
> 0 && m
->console_active_fd
>= 0) {
1339 m
->udev_vcsa_monitor
= udev_monitor_new_from_netlink(m
->udev
, "udev");
1340 if (!m
->udev_vcsa_monitor
)
1343 r
= udev_monitor_filter_add_match_subsystem_devtype(m
->udev_vcsa_monitor
, "vc", NULL
);
1347 r
= udev_monitor_enable_receiving(m
->udev_vcsa_monitor
);
1351 m
->udev_vcsa_fd
= udev_monitor_get_fd(m
->udev_vcsa_monitor
);
1354 ev
.events
= EPOLLIN
;
1355 ev
.data
.u32
= FD_VCSA_UDEV
;
1356 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->udev_vcsa_fd
, &ev
) < 0)
1363 void manager_gc(Manager
*m
, bool drop_not_started
) {
1370 while ((seat
= m
->seat_gc_queue
)) {
1371 LIST_REMOVE(Seat
, gc_queue
, m
->seat_gc_queue
, seat
);
1372 seat
->in_gc_queue
= false;
1374 if (seat_check_gc(seat
, drop_not_started
) == 0) {
1380 while ((session
= m
->session_gc_queue
)) {
1381 LIST_REMOVE(Session
, gc_queue
, m
->session_gc_queue
, session
);
1382 session
->in_gc_queue
= false;
1384 if (session_check_gc(session
, drop_not_started
) == 0) {
1385 session_stop(session
);
1386 session_free(session
);
1390 while ((user
= m
->user_gc_queue
)) {
1391 LIST_REMOVE(User
, gc_queue
, m
->user_gc_queue
, user
);
1392 user
->in_gc_queue
= false;
1394 if (user_check_gc(user
, drop_not_started
) == 0) {
1401 int manager_get_idle_hint(Manager
*m
, dual_timestamp
*t
) {
1404 dual_timestamp ts
= { 0, 0 };
1409 idle_hint
= !manager_is_inhibited(m
, INHIBIT_IDLE
, INHIBIT_BLOCK
, t
);
1411 HASHMAP_FOREACH(s
, m
->sessions
, i
) {
1415 ih
= session_get_idle_hint(s
, &k
);
1421 if (k
.monotonic
< ts
.monotonic
)
1427 } else if (idle_hint
) {
1429 if (k
.monotonic
> ts
.monotonic
)
1440 int manager_startup(Manager
*m
) {
1445 Inhibitor
*inhibitor
;
1449 assert(m
->epoll_fd
<= 0);
1451 cg_shorten_controllers(m
->reset_controllers
);
1452 cg_shorten_controllers(m
->controllers
);
1454 m
->epoll_fd
= epoll_create1(EPOLL_CLOEXEC
);
1455 if (m
->epoll_fd
< 0)
1458 /* Connect to console */
1459 r
= manager_connect_console(m
);
1463 /* Connect to udev */
1464 r
= manager_connect_udev(m
);
1468 /* Connect to the bus */
1469 r
= manager_connect_bus(m
);
1473 /* Instantiate magic seat 0 */
1474 r
= manager_add_seat(m
, "seat0", &m
->vtconsole
);
1478 /* Deserialize state */
1479 manager_enumerate_devices(m
);
1480 manager_enumerate_seats(m
);
1481 manager_enumerate_users(m
);
1482 manager_enumerate_sessions(m
);
1483 manager_enumerate_inhibitors(m
);
1484 manager_enumerate_buttons(m
);
1486 /* Remove stale objects before we start them */
1487 manager_gc(m
, false);
1489 /* Reserve the special reserved VT */
1490 manager_reserve_vt(m
);
1492 /* And start everything */
1493 HASHMAP_FOREACH(seat
, m
->seats
, i
)
1496 HASHMAP_FOREACH(user
, m
->users
, i
)
1499 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1500 session_start(session
);
1502 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
)
1503 inhibitor_start(inhibitor
);
1508 int manager_run(Manager
*m
) {
1512 struct epoll_event event
;
1516 manager_gc(m
, true);
1518 if (manager_dispatch_delayed(m
) > 0)
1521 if (dbus_connection_dispatch(m
->bus
) != DBUS_DISPATCH_COMPLETE
)
1524 manager_gc(m
, true);
1526 if (m
->delayed_unit
) {
1529 x
= now(CLOCK_MONOTONIC
);
1530 y
= m
->delayed_timestamp
+ m
->inhibit_delay_max
;
1532 msec
= x
>= y
? 0 : (int) ((y
- x
) / USEC_PER_MSEC
);
1535 n
= epoll_wait(m
->epoll_fd
, &event
, 1, msec
);
1537 if (errno
== EINTR
|| errno
== EAGAIN
)
1540 log_error("epoll() failed: %m");
1547 switch (event
.data
.u32
) {
1550 manager_dispatch_seat_udev(m
);
1554 manager_dispatch_vcsa_udev(m
);
1557 case FD_BUTTON_UDEV
:
1558 manager_dispatch_button_udev(m
);
1562 manager_dispatch_console(m
);
1566 bus_loop_dispatch(m
->bus_fd
);
1570 if (event
.data
.u32
>= FD_OTHER_BASE
)
1571 manager_dispatch_other(m
, event
.data
.u32
- FD_OTHER_BASE
);
1578 static int manager_parse_config_file(Manager
*m
) {
1585 fn
= "/etc/systemd/logind.conf";
1586 f
= fopen(fn
, "re");
1588 if (errno
== ENOENT
)
1591 log_warning("Failed to open configuration file %s: %m", fn
);
1595 r
= config_parse(fn
, f
, "Login\0", config_item_perf_lookup
, (void*) logind_gperf_lookup
, false, m
);
1597 log_warning("Failed to parse configuration file: %s", strerror(-r
));
1604 int main(int argc
, char *argv
[]) {
1608 log_set_target(LOG_TARGET_AUTO
);
1609 log_set_facility(LOG_AUTH
);
1610 log_parse_environment();
1616 log_error("This program takes no arguments.");
1627 manager_parse_config_file(m
);
1629 r
= manager_startup(m
);
1631 log_error("Failed to fully start up daemon: %s", strerror(-r
));
1635 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1639 "STATUS=Processing requests...");
1643 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1647 "STATUS=Shutting down...");
1652 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;