logind-dbus.c revision ceb242292630b4633aa707b565585a1e8bcbfeb8
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering This file is part of systemd.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Copyright 2011 Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering (at your option) any later version.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is distributed in the hope that it will be useful, but
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Lesser General Public License for more details.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringint manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = sd_bus_creds_get_session(creds, &name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering session = hashmap_get(m->sessions, name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmekint manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek /* Note that we get the owner UID of the session, not the actual client UID here! */
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_creds_get_owner_uid(creds, &uid);
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek user = hashmap_get(m->users, UID_TO_PTR(uid));
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmekint manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek r = manager_get_session_from_creds(m, message, NULL, error, &session);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmekstatic int property_get_idle_hint(
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
ee530d8b73246f29781bd54a707ca75c7ef5a6cbLennart Poettering return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (streq(property, "PreparingForShutdown"))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering b = !!(m->action_what & INHIBIT_SHUTDOWN);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_message_append(reply, "b", b);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_read(message, "s", &name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_read(message, "u", &pid);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_session_from_creds(m, message, NULL, error, &session);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_session_by_pid(m, pid, &session);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_read(message, "u", &uid);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_user_from_creds(m, message, uid, error, &user);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_read(message, "u", &pid);
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_user_by_pid(m, pid, &user);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_read(message, "s", &name);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = manager_get_seat_from_creds(m, message, name, error, &seat);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(susso)");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering HASHMAP_FOREACH(session, m->sessions, i) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_append(reply, "(susso)",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_close_container(reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(uso)");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_append(reply, "(uso)",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_close_container(reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(so)");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_append(reply, "(so)", seat->id, p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = sd_bus_message_close_container(reply);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Iterator i;
static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int remote;
SessionType t;
SessionClass c;
assert(m);
r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
if (!seat)
if (!seat)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
if (!vtnr)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
if (!seat)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
if (vtnr != 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
if (seat) {
if (vtnr != 0)
if (t == _SESSION_TYPE_INVALID) {
t = SESSION_X11;
t = SESSION_TTY;
t = SESSION_UNSPECIFIED;
if (c == _SESSION_CLASS_INVALID) {
if (t == SESSION_UNSPECIFIED)
c = SESSION_BACKGROUND;
c = SESSION_USER;
if (leader <= 0) {
if (session) {
if (fifo_fd < 0)
return fifo_fd;
if (!path)
return -ENOMEM;
path,
return sd_bus_reply_method_return(
path,
if (audit_id > 0) {
return -ENOMEM;
audit_id = 0;
if (!id) {
return -ENOMEM;
goto fail;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
if (seat) {
goto fail;
goto fail;
fail:
if (session)
if (user)
static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
&m->polkit_registry,
error);
static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name;
assert(m);
static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path;
int interactive;
assert(m);
errno = 0;
if (!pw)
"org.freedesktop.login1.set-user-linger",
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
if (!cc)
return -ENOMEM;
User *u;
user_start(u);
User *u;
return -errno;
assert(m);
return -ENOMEM;
r = udev_enumerate_add_match_parent(e, d);
r = udev_enumerate_scan_devices(e);
return -ENOMEM;
const char *id_for_seat;
assert(m);
return -ENODEV;
return -ENODEV;
if (!id_for_seat)
return -ENODEV;
return -ENOMEM;
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
return -ENOMEM;
return trigger_device(m, d);
assert(m);
static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int interactive, r;
assert(m);
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
int interactive, r;
assert(m);
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = flush_devices(m);
static int have_multiple_sessions(
Manager *m,
Iterator i;
assert(m);
static int bus_manager_log_shutdown(
Manager *m,
InhibitWhat w,
const char *unit_name) {
assert(m);
if (w != INHIBIT_SHUTDOWN)
q = NULL;
NULL);
assert(e);
assert(m);
assert(m);
if (m->lid_switch_ignore_event_source) {
usec_t u;
if (until <= u)
r = sd_event_add_time(
m->event,
until, 0,
static int execute_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name,
assert(m);
assert(w >= 0);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
c = strdup(p);
return -ENOMEM;
m->action_job = c;
m->action_what = w;
static int delay_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name) {
assert(m);
assert(w >= 0);
m->action_what = w;
assert(m);
assert(w >= 0);
"/org/freedesktop/login1",
signal_name[w],
active);
Manager *m,
const char *unit_name,
InhibitWhat w,
bool delayed;
assert(m);
assert(w >= 0);
send_prepare_for(m, w, true);
delayed =
m->inhibit_delay_max > 0 &&
if (delayed)
static int method_do_shutdown_or_sleep(
Manager *m,
const char *unit_name,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
int interactive, r;
assert(m);
assert(w >= 0);
if (m->action_what)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
if (sleep_verb) {
multiple_sessions = r > 0;
if (multiple_sessions) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
if (blocked) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_do_shutdown_or_sleep(
m, message,
NULL,
error);
static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_do_shutdown_or_sleep(
m, message,
NULL,
error);
static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
error);
static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int method_can_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
assert(m);
assert(w >= 0);
if (sleep_verb) {
multiple_sessions = r > 0;
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
else if (challenge)
if (blocked) {
if (r > 0 && !result)
else if (challenge)
static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_can_shutdown_or_sleep(
m, message,
NULL,
error);
static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_can_shutdown_or_sleep(
m, message,
NULL,
error);
static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
error);
static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
InhibitWhat w;
assert(m);
if (mm < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
if (m->action_what & w)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
return -ENOMEM;
i->what = w;
r = -ENOMEM;
goto fail;
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
inhibitor_start(i);
fail:
inhibitor_free(i);
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
assert(s);
if (!s->started)
sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
r = session_send_create_reply(s, &e);
assert(m);
m->action_what = 0;
if (session) {
if (user) {
assert(m);
if (session)
if (user)
int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path;
assert(m);
if (!path)
if (session)
if (user)
Iterator i;
int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Iterator i;
char *key;
if (!key)
"/org/freedesktop/login1",
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
int manager_start_scope(
const char *scope,
const char *slice,
const char *description,
char **job) {
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
r = sd_bus_message_close_container(m);
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
if (job)
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
if (!path)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Scope",
NULL,
NULL);
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
return sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
const char *state;
if (!path)
return -ENOMEM;
r = sd_bus_get_property(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
&error,
&reply,
return -EINVAL;
r = sd_bus_get_property(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Job",
&error,
&reply,