logind.c revision f647962d64e844689f3e2acfce6102fc47e76df2
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering This file is part of systemd.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Copyright 2011 Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering under the terms of the GNU Lesser General Public License as published by
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering (at your option) any later version.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is distributed in the hope that it will be useful, but
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Lesser General Public License for more details.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering You should have received a copy of the GNU Lesser General Public License
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->handle_hibernate_key = HANDLE_HIBERNATE;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->handle_lid_switch_docked = HANDLE_IGNORE;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->idle_action_usec = 30 * USEC_PER_MINUTE;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->devices = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->seats = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->sessions = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->inhibitors = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->buttons = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->user_units = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->session_units = hashmap_new(&string_hash_ops);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->kill_exclude_users = strv_new("root", NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering while ((session = hashmap_first(m->sessions)))
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering while ((i = hashmap_first(m->inhibitors)))
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->idle_action_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->console_active_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->udev_seat_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->udev_device_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->udev_vcsa_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->udev_button_event_source);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_source_unref(m->lid_switch_ignore_event_source);
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering udev_monitor_unref(m->udev_seat_monitor);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering udev_monitor_unref(m->udev_device_monitor);
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering udev_monitor_unref(m->udev_vcsa_monitor);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering udev_monitor_unref(m->udev_button_monitor);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering bus_verify_polkit_async_registry_free(m->polkit_registry);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int manager_enumerate_devices(Manager *m) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering struct udev_list_entry *item = NULL, *first = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* Loads devices from udev and creates seats for them as
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * necessary */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = udev_enumerate_add_match_tag(e, "master-of-seat");
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering r = udev_enumerate_add_match_is_initialized(e);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering first = udev_enumerate_get_list_entry(e);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykrynstatic int manager_enumerate_buttons(Manager *m) {
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn struct udev_list_entry *item = NULL, *first = NULL;
a34faf579d2be139b0b9e8cd0c73ad4d918ef736Lukas Nykryn /* Loads buttons from udev */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (m->handle_power_key == HANDLE_IGNORE &&
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->handle_suspend_key == HANDLE_IGNORE &&
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->handle_hibernate_key == HANDLE_IGNORE &&
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->handle_lid_switch_docked == HANDLE_IGNORE)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "input");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = udev_enumerate_add_match_tag(e, "power-switch");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = udev_enumerate_add_match_is_initialized(e);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering first = udev_enumerate_get_list_entry(e);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int manager_enumerate_seats(Manager *m) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* This loads data about seats stored on disk, but does not
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * actually create any seats. Removes data of seats that no
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * longer exist. */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_error("Failed to open /run/systemd/seats: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int manager_enumerate_linger_users(Manager *m) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_error("Failed to open /var/lib/systemd/linger/: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering k = manager_add_user_by_name(m, de->d_name, NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int manager_enumerate_users(Manager *m) {
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering /* Add lingering users */
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering /* Read in user data stored on disk */
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering log_error("Failed to open /run/systemd/users: %m");
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering k = manager_add_user_by_name(m, de->d_name, &u);
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poetteringstatic int manager_enumerate_sessions(Manager *m) {
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering /* Read in session data stored on disk */
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering log_error("Failed to open /run/systemd/sessions: %m");
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering log_warning("Invalid session file name '%s', ignoring.", de->d_name);
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering k = manager_add_session(m, de->d_name, &s);
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poetteringstatic int manager_enumerate_inhibitors(Manager *m) {
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering log_error("Failed to open /run/systemd/inhibit: %m");
Inhibitor *i;
k = inhibitor_load(i);
static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(m);
return -ENOMEM;
manager_process_seat_device(m, d);
static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(m);
return -ENOMEM;
manager_process_seat_device(m, d);
static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
const char *name;
assert(m);
return -ENOMEM;
static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(m);
return -ENOMEM;
assert(m);
assert(m);
if (m->reserve_vt <= 0)
return log_oom();
if (m->reserve_vt_fd < 0) {
return -errno;
assert(m);
r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
NULL,
"path='/org/freedesktop/DBus'",
NULL,
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
"path='/org/freedesktop/systemd1'",
match_job_removed, m);
NULL,
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
"path='/org/freedesktop/systemd1'",
match_unit_removed, m);
NULL,
"sender='org.freedesktop.systemd1',"
NULL,
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
"path='/org/freedesktop/systemd1'",
match_reloading, m);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
assert(m);
if (m->console_active_fd < 0) {
return -errno;
r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
return -EINVAL;
assert(m);
if (!m->udev_seat_monitor)
return -ENOMEM;
r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m);
if (!m->udev_device_monitor)
return -ENOMEM;
r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m);
if (!m->udev_button_monitor)
return -ENOMEM;
r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m);
if (!m->udev_vcsa_monitor)
return -ENOMEM;
r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m);
assert(m);
assert(m);
m->idle_action_usec <= 0)
(m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
m->idle_action_not_before_usec = n;
if (!m->idle_action_event_source) {
r = sd_event_add_time(
m->event,
Iterator i;
assert(m);
r = manager_connect_console(m);
r = manager_connect_udev(m);
r = manager_connect_bus(m);
r = manager_enumerate_devices(m);
r = manager_enumerate_seats(m);
r = manager_enumerate_users(m);
r = manager_enumerate_sessions(m);
r = manager_enumerate_inhibitors(m);
r = manager_enumerate_buttons(m);
manager_gc(m, false);
assert(m);
if (r == SD_EVENT_FINISHED)
manager_gc(m, true);
if (manager_dispatch_delayed(m) > 0)
usec_t x, y;
us = x >= y ? 0 : y - x;
assert(m);
log_open();
r = -EINVAL;
goto finish;
m = manager_new();
r = log_oom();
goto finish;
r = manager_startup(m);
goto finish;
sd_notify(false,
r = manager_run(m);
sd_notify(false,
manager_free(m);