logind-dbus.c revision 314b4b0a68d9ab35de981923a088fc8c8820caa5
4c80d201ace0377312c27143afab04e9c9f1ee64Filipe Brandenburger/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4c80d201ace0377312c27143afab04e9c9f1ee64Filipe Brandenburger This file is part of systemd.
4c80d201ace0377312c27143afab04e9c9f1ee64Filipe Brandenburger Copyright 2011 Lennart Poettering
4c80d201ace0377312c27143afab04e9c9f1ee64Filipe Brandenburger systemd is free software; you can redistribute it and/or modify it
along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include "logind.h"
#include "dbus-common.h"
#include "strv.h"
#include "mkdir.h"
#include "path-util.h"
#include "polkit.h"
#include "special.h"
#include "systemd/sd-id128.h"
#include "systemd/sd-messages.h"
#define BUS_MANAGER_INTERFACE \
#define INTROSPECTION_BEGIN \
#define INTROSPECTION_END \
#define INTERFACES_LIST \
dbus_bool_t b;
assert(i);
assert(m);
return -ENOMEM;
static int bus_manager_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
uint64_t u;
assert(i);
assert(m);
manager_get_idle_hint(m, &t);
return -ENOMEM;
InhibitWhat w;
p = inhibit_what_to_string(w);
return -ENOMEM;
dbus_bool_t b;
assert(i);
SessionType t;
SessionClass c;
Seat *s;
assert(m);
return -EINVAL;
return -EINVAL;
if (leader <= 0 ||
return -EINVAL;
return -EINVAL;
return -EINVAL;
c = SESSION_USER;
return -EINVAL;
s = NULL;
return -ENOENT;
return -EINVAL;
return -EINVAL;
s = m->vtconsole;
else if (s != m->vtconsole)
return -EINVAL;
return v < 0 ? v : -EINVAL;
if (vtnr <= 0)
return -EINVAL;
s = m->vtconsole;
else if (s != m->vtconsole)
return -EINVAL;
if (vtnr != 0)
return -EINVAL;
if (seat_can_multi_session(s)) {
return -EINVAL;
if (vtnr != 0)
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
r = -EINVAL;
goto fail;
goto fail;
r = -EINVAL;
goto fail;
goto fail;
if (audit_id > 0) {
if (!id) {
r = -ENOMEM;
goto fail;
if (session) {
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
if (!reply) {
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
exists = true;
free(p);
r = -ENOMEM;
goto fail;
r = -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;
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
goto fail;
goto fail;
if (!reply) {
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
exists = false;
free(p);
r = -ENOMEM;
goto fail;
fail:
if (session)
if (user)
if (fifo_fd >= 0)
if (reply)
static int bus_manager_inhibit(
Manager *m,
InhibitWhat w;
unsigned long ul;
assert(m);
if (!dbus_message_get_args(
r = -EIO;
goto fail;
r = -EINVAL;
goto fail;
if (mm < 0) {
r = -EINVAL;
goto fail;
r = -EINVAL;
goto fail;
if (m->action_what & w) {
r = -EALREADY;
goto fail;
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") :
goto fail;
r = -EIO;
goto fail;
if (pid <= 0) {
r = -EIO;
goto fail;
r = -ENOMEM;
goto fail;
goto fail;
i->what = w;
r = -ENOMEM;
goto fail;
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
if (!reply) {
r = -ENOMEM;
goto fail;
if (!dbus_message_append_args(
r = -ENOMEM;
goto fail;
inhibitor_start(i);
fail:
inhibitor_free(i);
if (fifo_fd >= 0)
if (reply)
struct udev_enumerate *e;
assert(m);
r = -ENOMEM;
goto finish;
if (udev_enumerate_add_match_parent(e, d) < 0) {
r = -EIO;
goto finish;
if (udev_enumerate_scan_devices(e) < 0) {
r = -EIO;
goto finish;
r = -ENOMEM;
goto finish;
free(t);
struct udev_device *d;
const char *id_for_seat;
assert(m);
return -ENODEV;
r = -ENODEV;
goto finish;
if (!id_for_seat) {
r = -ENODEV;
goto finish;
r = -ENOMEM;
goto finish;
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
r = -ENOMEM;
goto finish;
goto finish;
r = trigger_device(m, d);
DIR *d;
assert(m);
closedir(d);
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;
q, NULL);
static int execute_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name,
assert(m);
assert(w >= 0);
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
if (!dbus_message_get_args(
return -EINVAL;
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;
static int bus_manager_can_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_type,
const char *sleep_disk_type,
const char *result;
unsigned long ul;
assert(m);
assert(w >= 0);
if (sleep_type) {
goto finish;
if (sleep_disk_type) {
goto finish;
return -EIO;
multiple_sessions = r > 0;
if (multiple_sessions) {
else if (challenge)
if (blocked) {
if (r > 0 && !result)
else if (challenge)
if (!reply)
return -ENOMEM;
return -ENOMEM;
assert(m);
assert(w >= 0);
message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
if (!message)
return -ENOMEM;
return -ENOMEM;
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 bus_manager_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_type,
const char *sleep_disk_type,
unsigned long ul;
assert(m);
assert(w >= 0);
if (m->action_what)
return -EALREADY;
if (!dbus_message_get_args(
return -EINVAL;
if (sleep_type) {
return -ENOTSUP;
if (sleep_disk_type) {
return -ENOTSUP;
return -EIO;
multiple_sessions = r > 0;
if (multiple_sessions) {
if (blocked) {
if (!reply)
return -ENOMEM;
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_action, handle_action, HandleAction);
{ "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
{ "HandleSuspendKey", bus_manager_append_handle_action, "s", offsetof(Manager, handle_suspend_key) },
{ "HandleHibernateKey", bus_manager_append_handle_action, "s", offsetof(Manager, handle_hibernate_key)},
{ NULL, }
void *userdata) {
assert(m);
const char *name;
if (!dbus_message_get_args(
&error,
if (!session)
if (!reply)
goto oom;
goto oom;
free(p);
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSessionByPID")) {
if (!dbus_message_get_args(
&error,
if (!reply)
goto oom;
goto oom;
free(p);
goto oom;
if (!dbus_message_get_args(
&error,
if (!user)
if (!reply)
goto oom;
goto oom;
free(p);
goto oom;
const char *name;
if (!dbus_message_get_args(
&error,
if (!seat)
if (!reply)
goto oom;
goto oom;
free(p);
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
Iterator i;
if (!reply)
goto oom;
goto oom;
goto oom;
goto oom;
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
free(p);
goto oom;
free(p);
goto oom;
goto oom;
Iterator i;
if (!reply)
goto oom;
goto oom;
goto oom;
goto oom;
free(p);
goto oom;
free(p);
goto oom;
goto oom;
Iterator i;
if (!reply)
goto oom;
goto oom;
goto oom;
goto oom;
free(p);
goto oom;
free(p);
goto oom;
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListInhibitors")) {
Iterator i;
if (!reply)
goto oom;
goto oom;
goto oom;
goto oom;
goto oom;
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ReleaseSession")) {
const char *name;
if (!dbus_message_get_args(
&error,
if (!session)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
const char *name;
if (!dbus_message_get_args(
&error,
if (!session)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSessionOnSeat")) {
if (!dbus_message_get_args(
&error,
if (!session)
if (!seat)
if (!reply)
goto oom;
const char *name;
if (!dbus_message_get_args(
&error,
if (!session)
goto oom;
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions") ||
if (!reply)
goto oom;
const char *swho;
const char *name;
if (!dbus_message_get_args(
&error,
if (who < 0)
if (!session)
if (!reply)
goto oom;
if (!dbus_message_get_args(
&error,
if (!user)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
const char *name;
if (!dbus_message_get_args(
&error,
if (!session)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
if (!dbus_message_get_args(
&error,
if (!user)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
const char *name;
if (!dbus_message_get_args(
&error,
if (!seat)
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
char *path;
if (!dbus_message_get_args(
&error,
DBUS_TYPE_BOOLEAN, &b,
errno = 0;
if (!pw)
r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, NULL, &error);
if (!path)
goto oom;
User *u;
user_start(u);
User *u;
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
if (!dbus_message_get_args(
&error,
r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, NULL, &error);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
if (!dbus_message_get_args(
&error,
r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, NULL, &error);
r = flush_devices(m);
if (!reply)
goto oom;
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHybridSleep")) {
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
FILE *f;
Iterator i;
goto oom;
goto oom;
free(p);
free(p);
if (ferror(f)) {
fclose(f);
goto oom;
fclose(f);
if (!introspection)
goto oom;
goto oom;
{ NULL, }
if (reply) {
goto oom;
return DBUS_HANDLER_RESULT_HANDLED;
oom:
if (reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
void *userdata) {
assert(m);
const char *cgroup;
m->action_what = 0;
DBusMessage *m;
int r = -ENOMEM;
m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties);
goto finish;
goto finish;