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/timerfd.h>
30 #include "sd-daemon.h"
32 #include "conf-parser.h"
35 #include "bus-error.h"
37 #include "udev-util.h"
39 Manager *manager_new(void) {
47 m->console_active_fd = -1;
48 m->reserve_vt_fd = -1;
52 m->inhibit_delay_max = 5 * USEC_PER_SEC;
53 m->handle_power_key = HANDLE_POWEROFF;
54 m->handle_suspend_key = HANDLE_SUSPEND;
55 m->handle_hibernate_key = HANDLE_HIBERNATE;
56 m->handle_lid_switch = HANDLE_SUSPEND;
57 m->lid_switch_ignore_inhibited = true;
59 m->idle_action_usec = 30 * USEC_PER_MINUTE;
60 m->idle_action = HANDLE_IGNORE;
61 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
63 m->devices = hashmap_new(string_hash_func, string_compare_func);
64 m->seats = hashmap_new(string_hash_func, string_compare_func);
65 m->sessions = hashmap_new(string_hash_func, string_compare_func);
66 m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
67 m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
68 m->buttons = hashmap_new(string_hash_func, string_compare_func);
70 m->user_units = hashmap_new(string_hash_func, string_compare_func);
71 m->session_units = hashmap_new(string_hash_func, string_compare_func);
73 m->busnames = set_new(string_hash_func, string_compare_func);
75 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
76 !m->user_units || !m->session_units ||
82 m->kill_exclude_users = strv_new("root", NULL);
83 if (!m->kill_exclude_users) {
94 r = sd_event_default(&m->event);
100 sd_event_set_watchdog(m->event, true);
105 void manager_free(Manager *m) {
115 while ((session = hashmap_first(m->sessions)))
116 session_free(session);
118 while ((u = hashmap_first(m->users)))
121 while ((d = hashmap_first(m->devices)))
124 while ((s = hashmap_first(m->seats)))
127 while ((i = hashmap_first(m->inhibitors)))
130 while ((b = hashmap_first(m->buttons)))
133 hashmap_free(m->devices);
134 hashmap_free(m->seats);
135 hashmap_free(m->sessions);
136 hashmap_free(m->users);
137 hashmap_free(m->inhibitors);
138 hashmap_free(m->buttons);
140 hashmap_free(m->user_units);
141 hashmap_free(m->session_units);
143 set_free_free(m->busnames);
145 sd_event_source_unref(m->idle_action_event_source);
147 sd_event_source_unref(m->console_active_event_source);
148 sd_event_source_unref(m->udev_seat_event_source);
149 sd_event_source_unref(m->udev_device_event_source);
150 sd_event_source_unref(m->udev_vcsa_event_source);
151 sd_event_source_unref(m->udev_button_event_source);
153 if (m->console_active_fd >= 0)
154 close_nointr_nofail(m->console_active_fd);
156 if (m->udev_seat_monitor)
157 udev_monitor_unref(m->udev_seat_monitor);
158 if (m->udev_device_monitor)
159 udev_monitor_unref(m->udev_device_monitor);
160 if (m->udev_vcsa_monitor)
161 udev_monitor_unref(m->udev_vcsa_monitor);
162 if (m->udev_button_monitor)
163 udev_monitor_unref(m->udev_button_monitor);
168 bus_verify_polkit_async_registry_free(m->bus, m->polkit_registry);
170 sd_bus_unref(m->bus);
171 sd_event_unref(m->event);
173 if (m->reserve_vt_fd >= 0)
174 close_nointr_nofail(m->reserve_vt_fd);
176 strv_free(m->kill_only_users);
177 strv_free(m->kill_exclude_users);
183 static int manager_enumerate_devices(Manager *m) {
184 struct udev_list_entry *item = NULL, *first = NULL;
185 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
190 /* Loads devices from udev and creates seats for them as
193 e = udev_enumerate_new(m->udev);
197 r = udev_enumerate_add_match_tag(e, "master-of-seat");
201 r = udev_enumerate_add_match_is_initialized(e);
205 r = udev_enumerate_scan_devices(e);
209 first = udev_enumerate_get_list_entry(e);
210 udev_list_entry_foreach(item, first) {
211 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
214 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
218 k = manager_process_seat_device(m, d);
226 static int manager_enumerate_buttons(Manager *m) {
227 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
228 struct udev_list_entry *item = NULL, *first = NULL;
233 /* Loads buttons from udev */
235 if (m->handle_power_key == HANDLE_IGNORE &&
236 m->handle_suspend_key == HANDLE_IGNORE &&
237 m->handle_hibernate_key == HANDLE_IGNORE &&
238 m->handle_lid_switch == HANDLE_IGNORE)
241 e = udev_enumerate_new(m->udev);
245 r = udev_enumerate_add_match_subsystem(e, "input");
249 r = udev_enumerate_add_match_tag(e, "power-switch");
253 r = udev_enumerate_add_match_is_initialized(e);
257 r = udev_enumerate_scan_devices(e);
261 first = udev_enumerate_get_list_entry(e);
262 udev_list_entry_foreach(item, first) {
263 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
266 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
270 k = manager_process_button_device(m, d);
278 static int manager_enumerate_seats(Manager *m) {
279 _cleanup_closedir_ DIR *d = NULL;
285 /* This loads data about seats stored on disk, but does not
286 * actually create any seats. Removes data of seats that no
289 d = opendir("/run/systemd/seats");
294 log_error("Failed to open /run/systemd/seats: %m");
298 FOREACH_DIRENT(de, d, return -errno) {
302 if (!dirent_is_file(de))
305 s = hashmap_get(m->seats, de->d_name);
307 unlinkat(dirfd(d), de->d_name, 0);
319 static int manager_enumerate_linger_users(Manager *m) {
320 _cleanup_closedir_ DIR *d = NULL;
326 d = opendir("/var/lib/systemd/linger");
331 log_error("Failed to open /var/lib/systemd/linger/: %m");
335 FOREACH_DIRENT(de, d, return -errno) {
338 if (!dirent_is_file(de))
341 k = manager_add_user_by_name(m, de->d_name, NULL);
343 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
351 static int manager_enumerate_users(Manager *m) {
352 _cleanup_closedir_ DIR *d = NULL;
358 /* Add lingering users */
359 r = manager_enumerate_linger_users(m);
361 /* Read in user data stored on disk */
362 d = opendir("/run/systemd/users");
367 log_error("Failed to open /run/systemd/users: %m");
371 FOREACH_DIRENT(de, d, return -errno) {
374 if (!dirent_is_file(de))
377 k = manager_add_user_by_name(m, de->d_name, &u);
379 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
385 user_add_to_gc_queue(u);
395 static int manager_enumerate_sessions(Manager *m) {
396 _cleanup_closedir_ DIR *d = NULL;
402 /* Read in session data stored on disk */
403 d = opendir("/run/systemd/sessions");
408 log_error("Failed to open /run/systemd/sessions: %m");
412 FOREACH_DIRENT(de, d, return -errno) {
416 if (!dirent_is_file(de))
419 if (!session_id_valid(de->d_name)) {
420 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
425 k = manager_add_session(m, de->d_name, &s);
427 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
433 session_add_to_gc_queue(s);
443 static int manager_enumerate_inhibitors(Manager *m) {
444 _cleanup_closedir_ DIR *d = NULL;
450 d = opendir("/run/systemd/inhibit");
455 log_error("Failed to open /run/systemd/inhibit: %m");
459 FOREACH_DIRENT(de, d, return -errno) {
463 if (!dirent_is_file(de))
466 k = manager_add_inhibitor(m, de->d_name, &i);
468 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
473 k = inhibitor_load(i);
481 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
482 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
483 Manager *m = userdata;
487 d = udev_monitor_receive_device(m->udev_seat_monitor);
491 manager_process_seat_device(m, d);
495 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
496 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
497 Manager *m = userdata;
501 d = udev_monitor_receive_device(m->udev_device_monitor);
505 manager_process_seat_device(m, d);
509 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
510 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
511 Manager *m = userdata;
516 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
520 name = udev_device_get_sysname(d);
522 /* Whenever a VCSA device is removed try to reallocate our
523 * VTs, to make sure our auto VTs never go away. */
525 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
526 seat_preallocate_vts(m->seat0);
531 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
532 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
533 Manager *m = userdata;
537 d = udev_monitor_receive_device(m->udev_button_monitor);
541 manager_process_button_device(m, d);
545 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
546 Manager *m = userdata;
550 assert(m->console_active_fd == fd);
552 seat_read_active_vt(m->seat0);
556 static int manager_reserve_vt(Manager *m) {
557 _cleanup_free_ char *p = NULL;
561 if (m->reserve_vt <= 0)
564 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
567 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
568 if (m->reserve_vt_fd < 0) {
570 /* Don't complain on VT-less systems */
572 log_warning("Failed to pin reserved VT: %m");
579 static int manager_connect_bus(Manager *m) {
580 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
586 r = sd_bus_default_system(&m->bus);
588 log_error("Failed to connect to system bus: %s", strerror(-r));
592 r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
594 log_error("Failed to add manager object vtable: %s", strerror(-r));
598 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
600 log_error("Failed to add seat object vtable: %s", strerror(-r));
604 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
606 log_error("Failed to add seat enumerator: %s", strerror(-r));
610 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
612 log_error("Failed to add session object vtable: %s", strerror(-r));
616 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m);
618 log_error("Failed to add session enumerator: %s", strerror(-r));
622 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
624 log_error("Failed to add user object vtable: %s", strerror(-r));
628 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m);
630 log_error("Failed to add user enumerator: %s", strerror(-r));
634 r = sd_bus_add_match(m->bus,
636 "sender='org.freedesktop.DBus',"
637 "interface='org.freedesktop.DBus',"
638 "member='NameOwnerChanged',"
639 "path='/org/freedesktop/DBus'",
640 match_name_owner_changed, m);
642 log_error("Failed to add match for NameOwnerChanged: %s", strerror(-r));
646 r = sd_bus_add_match(m->bus,
648 "sender='org.freedesktop.systemd1',"
649 "interface='org.freedesktop.systemd1.Manager',"
650 "member='JobRemoved',"
651 "path='/org/freedesktop/systemd1'",
652 match_job_removed, m);
654 log_error("Failed to add match for JobRemoved: %s", strerror(-r));
658 r = sd_bus_add_match(m->bus,
660 "sender='org.freedesktop.systemd1',"
661 "interface='org.freedesktop.systemd1.Manager',"
662 "member='UnitRemoved',"
663 "path='/org/freedesktop/systemd1'",
664 match_unit_removed, m);
666 log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
670 r = sd_bus_add_match(m->bus,
672 "sender='org.freedesktop.systemd1',"
673 "interface='org.freedesktop.DBus.Properties',"
674 "member='PropertiesChanged'",
675 match_properties_changed, m);
677 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
681 r = sd_bus_add_match(m->bus,
683 "sender='org.freedesktop.systemd1',"
684 "interface='org.freedesktop.systemd1.Manager',"
685 "member='Reloading',"
686 "path='/org/freedesktop/systemd1'",
689 log_error("Failed to add match for Reloading: %s", strerror(-r));
693 r = sd_bus_call_method(
695 "org.freedesktop.systemd1",
696 "/org/freedesktop/systemd1",
697 "org.freedesktop.systemd1.Manager",
702 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
706 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
708 log_error("Failed to register name: %s", strerror(-r));
712 r = sd_bus_attach_event(m->bus, m->event, 0);
714 log_error("Failed to attach bus to event loop: %s", strerror(-r));
721 static int manager_connect_console(Manager *m) {
725 assert(m->console_active_fd < 0);
727 /* On certain architectures (S390 and Xen, and containers),
728 /dev/tty0 does not exist, so don't fail if we can't open
730 if (access("/dev/tty0", F_OK) < 0)
733 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
734 if (m->console_active_fd < 0) {
736 /* On some systems the device node /dev/tty0 may exist
737 * even though /sys/class/tty/tty0 does not. */
741 log_error("Failed to open /sys/class/tty/tty0/active: %m");
745 r = sd_event_add_io(m->event, m->console_active_fd, 0, manager_dispatch_console, m, &m->console_active_event_source);
747 log_error("Failed to watch foreground console");
754 static int manager_connect_udev(Manager *m) {
758 assert(!m->udev_seat_monitor);
759 assert(!m->udev_device_monitor);
760 assert(!m->udev_vcsa_monitor);
761 assert(!m->udev_button_monitor);
763 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
764 if (!m->udev_seat_monitor)
767 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
771 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
775 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m, &m->udev_seat_event_source);
779 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
780 if (!m->udev_device_monitor)
783 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
787 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
791 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
795 r = udev_monitor_enable_receiving(m->udev_device_monitor);
799 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m, &m->udev_device_event_source);
803 /* Don't watch keys if nobody cares */
804 if (m->handle_power_key != HANDLE_IGNORE ||
805 m->handle_suspend_key != HANDLE_IGNORE ||
806 m->handle_hibernate_key != HANDLE_IGNORE ||
807 m->handle_lid_switch != HANDLE_IGNORE) {
809 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
810 if (!m->udev_button_monitor)
813 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
817 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
821 r = udev_monitor_enable_receiving(m->udev_button_monitor);
825 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m, &m->udev_button_event_source);
830 /* Don't bother watching VCSA devices, if nobody cares */
831 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
833 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
834 if (!m->udev_vcsa_monitor)
837 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
841 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
845 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m, &m->udev_vcsa_event_source);
853 void manager_gc(Manager *m, bool drop_not_started) {
860 while ((seat = m->seat_gc_queue)) {
861 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
862 seat->in_gc_queue = false;
864 if (!seat_check_gc(seat, drop_not_started)) {
870 while ((session = m->session_gc_queue)) {
871 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
872 session->in_gc_queue = false;
874 if (!session_check_gc(session, drop_not_started)) {
875 session_stop(session);
876 session_finalize(session);
877 session_free(session);
881 while ((user = m->user_gc_queue)) {
882 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
883 user->in_gc_queue = false;
885 if (!user_check_gc(user, drop_not_started)) {
893 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
894 Manager *m = userdata;
895 struct dual_timestamp since;
901 if (m->idle_action == HANDLE_IGNORE ||
902 m->idle_action_usec <= 0)
905 n = now(CLOCK_MONOTONIC);
907 r = manager_get_idle_hint(m, &since);
909 /* Not idle. Let's check if after a timeout it might be idle then. */
910 elapse = n + m->idle_action_usec;
912 /* Idle! Let's see if it's time to do something, or if
913 * we shall sleep for longer. */
915 if (n >= since.monotonic + m->idle_action_usec &&
916 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
917 log_info("System idle. Taking action.");
919 manager_handle_action(m, 0, m->idle_action, false, false);
920 m->idle_action_not_before_usec = n;
923 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
926 if (!m->idle_action_event_source) {
928 r = sd_event_add_monotonic(m->event, elapse, USEC_PER_SEC*30, manager_dispatch_idle_action, m, &m->idle_action_event_source);
930 log_error("Failed to add idle event source: %s", strerror(-r));
934 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
936 log_error("Failed to set idle event source priority: %s", strerror(-r));
940 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
942 log_error("Failed to set idle event timer: %s", strerror(-r));
946 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
948 log_error("Failed to enable idle event timer: %s", strerror(-r));
956 int manager_startup(Manager *m) {
961 Inhibitor *inhibitor;
966 /* Connect to console */
967 r = manager_connect_console(m);
971 /* Connect to udev */
972 r = manager_connect_udev(m);
974 log_error("Failed to create udev watchers: %s", strerror(-r));
978 /* Connect to the bus */
979 r = manager_connect_bus(m);
983 /* Instantiate magic seat 0 */
984 r = manager_add_seat(m, "seat0", &m->seat0);
986 log_error("Failed to add seat0: %s", strerror(-r));
990 /* Deserialize state */
991 r = manager_enumerate_devices(m);
993 log_warning("Device enumeration failed: %s", strerror(-r));
995 r = manager_enumerate_seats(m);
997 log_warning("Seat enumeration failed: %s", strerror(-r));
999 r = manager_enumerate_users(m);
1001 log_warning("User enumeration failed: %s", strerror(-r));
1003 r = manager_enumerate_sessions(m);
1005 log_warning("Session enumeration failed: %s", strerror(-r));
1007 r = manager_enumerate_inhibitors(m);
1009 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1011 r = manager_enumerate_buttons(m);
1013 log_warning("Button enumeration failed: %s", strerror(-r));
1015 /* Remove stale objects before we start them */
1016 manager_gc(m, false);
1018 /* Reserve the special reserved VT */
1019 manager_reserve_vt(m);
1021 /* And start everything */
1022 HASHMAP_FOREACH(seat, m->seats, i)
1025 HASHMAP_FOREACH(user, m->users, i)
1028 HASHMAP_FOREACH(session, m->sessions, i)
1029 session_start(session);
1031 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1032 inhibitor_start(inhibitor);
1034 manager_dispatch_idle_action(NULL, 0, m);
1039 static int manager_recheck_buttons(Manager *m) {
1046 HASHMAP_FOREACH(b, m->buttons, i) {
1049 q = button_recheck(b);
1059 int manager_run(Manager *m) {
1065 usec_t us = (uint64_t) -1;
1067 r = sd_event_get_state(m->event);
1070 if (r == SD_EVENT_FINISHED)
1073 manager_gc(m, true);
1075 if (manager_dispatch_delayed(m) > 0)
1078 if (manager_recheck_buttons(m) > 0)
1081 if (m->action_what != 0 && !m->action_job) {
1084 x = now(CLOCK_MONOTONIC);
1085 y = m->action_timestamp + m->inhibit_delay_max;
1087 us = x >= y ? 0 : y - x;
1090 r = sd_event_run(m->event, us);
1098 static int manager_parse_config_file(Manager *m) {
1099 static const char fn[] = "/etc/systemd/logind.conf";
1100 _cleanup_fclose_ FILE *f = NULL;
1105 f = fopen(fn, "re");
1107 if (errno == ENOENT)
1110 log_warning("Failed to open configuration file %s: %m", fn);
1114 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1115 (void*) logind_gperf_lookup, false, false, m);
1117 log_warning("Failed to parse configuration file: %s", strerror(-r));
1122 int main(int argc, char *argv[]) {
1126 log_set_target(LOG_TARGET_AUTO);
1127 log_set_facility(LOG_AUTH);
1128 log_parse_environment();
1134 log_error("This program takes no arguments.");
1139 /* Always create the directories people can create inotify
1140 * watches in. Note that some applications might check for the
1141 * existence of /run/systemd/seats/ to determine whether
1142 * logind is available, so please always make sure this check
1144 mkdir_label("/run/systemd/seats", 0755);
1145 mkdir_label("/run/systemd/users", 0755);
1146 mkdir_label("/run/systemd/sessions", 0755);
1154 manager_parse_config_file(m);
1156 r = manager_startup(m);
1158 log_error("Failed to fully start up daemon: %s", strerror(-r));
1162 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1166 "STATUS=Processing requests...");
1170 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1174 "STATUS=Shutting down...");
1179 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;