610 lines
19 KiB
C
610 lines
19 KiB
C
/*
|
|
* Copyright © 2013 Red Hat Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Author: Hans de Goede <hdegoede@redhat.com>
|
|
*/
|
|
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
#include <xorg-config.h>
|
|
#endif
|
|
|
|
#include <dbus/dbus.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "os.h"
|
|
#include "dbus-core.h"
|
|
#include "xf86.h"
|
|
#include "xf86platformBus.h"
|
|
#include "xf86Xinput.h"
|
|
|
|
#include "systemd-logind.h"
|
|
|
|
struct systemd_logind_info {
|
|
DBusConnection *conn;
|
|
char *session;
|
|
Bool active;
|
|
Bool vt_active;
|
|
};
|
|
|
|
static struct systemd_logind_info logind_info;
|
|
|
|
static InputInfoPtr
|
|
systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
|
|
int major, int minor)
|
|
{
|
|
InputInfoPtr pInfo;
|
|
|
|
for (pInfo = start; pInfo; pInfo = pInfo->next)
|
|
if (pInfo->major == major && pInfo->minor == minor &&
|
|
(pInfo->flags & XI86_SERVER_FD))
|
|
return pInfo;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
systemd_logind_set_input_fd_for_all_devs(int major, int minor, int fd,
|
|
Bool enable)
|
|
{
|
|
InputInfoPtr pInfo;
|
|
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
|
|
while (pInfo) {
|
|
pInfo->fd = fd;
|
|
pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
|
|
if (enable)
|
|
xf86EnableInputDeviceForVTSwitch(pInfo);
|
|
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
|
|
}
|
|
}
|
|
|
|
int
|
|
systemd_logind_take_fd(int _major, int _minor, const char *path,
|
|
Bool *paused_ret)
|
|
{
|
|
struct systemd_logind_info *info = &logind_info;
|
|
InputInfoPtr pInfo;
|
|
DBusError error;
|
|
DBusMessage *msg = NULL;
|
|
DBusMessage *reply = NULL;
|
|
dbus_int32_t major = _major;
|
|
dbus_int32_t minor = _minor;
|
|
dbus_bool_t paused;
|
|
int fd = -1;
|
|
|
|
if (!info->session || major == 0)
|
|
return -1;
|
|
|
|
/* logind does not support mouse devs (with evdev we don't need them) */
|
|
if (strstr(path, "mouse"))
|
|
return -1;
|
|
|
|
/* Check if we already have an InputInfo entry with this major, minor
|
|
* (shared device-nodes happen ie with Wacom tablets). */
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
|
|
if (pInfo) {
|
|
LogMessage(X_INFO, "systemd-logind: returning pre-existing fd for %s %u:%u\n",
|
|
path, major, minor);
|
|
*paused_ret = FALSE;
|
|
return pInfo->fd;
|
|
}
|
|
|
|
dbus_error_init(&error);
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
|
|
"org.freedesktop.login1.Session", "TakeDevice");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
|
|
DBUS_TYPE_UINT32, &minor,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply) {
|
|
LogMessage(X_ERROR, "systemd-logind: failed to take device %s: %s\n",
|
|
path, error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!dbus_message_get_args(reply, &error,
|
|
DBUS_TYPE_UNIX_FD, &fd,
|
|
DBUS_TYPE_BOOLEAN, &paused,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: TakeDevice %s: %s\n",
|
|
path, error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
*paused_ret = paused;
|
|
|
|
LogMessage(X_INFO, "systemd-logind: got fd for %s %u:%u fd %d paused %d\n",
|
|
path, major, minor, fd, paused);
|
|
|
|
cleanup:
|
|
if (msg)
|
|
dbus_message_unref(msg);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
dbus_error_free(&error);
|
|
|
|
return fd;
|
|
}
|
|
|
|
void
|
|
systemd_logind_release_fd(int _major, int _minor, int fd)
|
|
{
|
|
struct systemd_logind_info *info = &logind_info;
|
|
InputInfoPtr pInfo;
|
|
DBusError error;
|
|
DBusMessage *msg = NULL;
|
|
DBusMessage *reply = NULL;
|
|
dbus_int32_t major = _major;
|
|
dbus_int32_t minor = _minor;
|
|
int matches = 0;
|
|
|
|
if (!info->session || major == 0)
|
|
goto close;
|
|
|
|
/* Only release the fd if there is only 1 InputInfo left for this major
|
|
* and minor, otherwise other InputInfo's are still referencing the fd. */
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
|
|
while (pInfo) {
|
|
matches++;
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
|
|
}
|
|
if (matches > 1) {
|
|
LogMessage(X_INFO, "systemd-logind: not releasing fd for %u:%u, still in use\n", major, minor);
|
|
return;
|
|
}
|
|
|
|
LogMessage(X_INFO, "systemd-logind: releasing fd for %u:%u\n", major, minor);
|
|
|
|
dbus_error_init(&error);
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
|
|
"org.freedesktop.login1.Session", "ReleaseDevice");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
|
|
DBUS_TYPE_UINT32, &minor,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply)
|
|
LogMessage(X_ERROR, "systemd-logind: failed to release device: %s\n",
|
|
error.message);
|
|
|
|
cleanup:
|
|
if (msg)
|
|
dbus_message_unref(msg);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
dbus_error_free(&error);
|
|
close:
|
|
if (fd != -1)
|
|
close(fd);
|
|
}
|
|
|
|
int
|
|
systemd_logind_controls_session(void)
|
|
{
|
|
return logind_info.session ? 1 : 0;
|
|
}
|
|
|
|
void
|
|
systemd_logind_vtenter(void)
|
|
{
|
|
struct systemd_logind_info *info = &logind_info;
|
|
InputInfoPtr pInfo;
|
|
int i;
|
|
|
|
if (!info->session)
|
|
return; /* Not using systemd-logind */
|
|
|
|
if (!info->active)
|
|
return; /* Session not active */
|
|
|
|
if (info->vt_active)
|
|
return; /* Already did vtenter */
|
|
|
|
for (i = 0; i < xf86_num_platform_devices; i++) {
|
|
if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED)
|
|
break;
|
|
}
|
|
if (i != xf86_num_platform_devices)
|
|
return; /* Some drm nodes are still paused wait for resume */
|
|
|
|
xf86VTEnter();
|
|
info->vt_active = TRUE;
|
|
|
|
/* Activate any input devices which were resumed before the drm nodes */
|
|
for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
|
|
if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
|
|
xf86EnableInputDeviceForVTSwitch(pInfo);
|
|
|
|
/* Do delayed input probing, this must be done after the above enabling */
|
|
xf86InputEnableVTProbe();
|
|
}
|
|
|
|
static void
|
|
systemd_logind_ack_pause(struct systemd_logind_info *info,
|
|
dbus_int32_t minor, dbus_int32_t major)
|
|
{
|
|
DBusError error;
|
|
DBusMessage *msg = NULL;
|
|
DBusMessage *reply = NULL;
|
|
|
|
dbus_error_init(&error);
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
|
|
"org.freedesktop.login1.Session", "PauseDeviceComplete");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
|
|
DBUS_TYPE_UINT32, &minor,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply)
|
|
LogMessage(X_ERROR, "systemd-logind: failed to ack pause: %s\n",
|
|
error.message);
|
|
|
|
cleanup:
|
|
if (msg)
|
|
dbus_message_unref(msg);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
dbus_error_free(&error);
|
|
}
|
|
|
|
static DBusHandlerResult
|
|
message_filter(DBusConnection * connection, DBusMessage * message, void *data)
|
|
{
|
|
struct systemd_logind_info *info = data;
|
|
struct xf86_platform_device *pdev = NULL;
|
|
InputInfoPtr pInfo = NULL;
|
|
int ack = 0, pause = 0, fd = -1;
|
|
DBusError error;
|
|
dbus_int32_t major, minor;
|
|
char *pause_str;
|
|
|
|
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
dbus_error_init(&error);
|
|
|
|
if (dbus_message_is_signal(message,
|
|
"org.freedesktop.DBus", "NameOwnerChanged")) {
|
|
char *name, *old_owner, *new_owner;
|
|
|
|
dbus_message_get_args(message, &error,
|
|
DBUS_TYPE_STRING, &name,
|
|
DBUS_TYPE_STRING, &old_owner,
|
|
DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID);
|
|
if (dbus_error_is_set(&error)) {
|
|
LogMessage(X_ERROR, "systemd-logind: NameOwnerChanged: %s\n",
|
|
error.message);
|
|
dbus_error_free(&error);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
if (name && strcmp(name, "org.freedesktop.login1") == 0)
|
|
FatalError("systemd-logind disappeared (stopped/restarted?)\n");
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
if (strcmp(dbus_message_get_path(message), info->session) != 0)
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
|
|
"PauseDevice")) {
|
|
if (!dbus_message_get_args(message, &error,
|
|
DBUS_TYPE_UINT32, &major,
|
|
DBUS_TYPE_UINT32, &minor,
|
|
DBUS_TYPE_STRING, &pause_str,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: PauseDevice: %s\n",
|
|
error.message);
|
|
dbus_error_free(&error);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
if (strcmp(pause_str, "pause") == 0) {
|
|
pause = 1;
|
|
ack = 1;
|
|
}
|
|
else if (strcmp(pause_str, "force") == 0) {
|
|
pause = 1;
|
|
}
|
|
else if (strcmp(pause_str, "gone") == 0) {
|
|
/* Device removal is handled through udev */
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
else {
|
|
LogMessage(X_WARNING, "systemd-logind: unknown pause type: %s\n",
|
|
pause_str);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
}
|
|
else if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
|
|
"ResumeDevice")) {
|
|
if (!dbus_message_get_args(message, &error,
|
|
DBUS_TYPE_UINT32, &major,
|
|
DBUS_TYPE_UINT32, &minor,
|
|
DBUS_TYPE_UNIX_FD, &fd,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: ResumeDevice: %s\n",
|
|
error.message);
|
|
dbus_error_free(&error);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
} else
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
LogMessage(X_INFO, "systemd-logind: got %s for %u:%u\n",
|
|
pause ? "pause" : "resume", major, minor);
|
|
|
|
pdev = xf86_find_platform_device_by_devnum(major, minor);
|
|
if (!pdev)
|
|
pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs,
|
|
major, minor);
|
|
if (!pdev && !pInfo) {
|
|
LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
|
|
major, minor);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
if (pause) {
|
|
/* Our VT_PROCESS usage guarantees we've already given up the vt */
|
|
info->active = info->vt_active = FALSE;
|
|
/* Note the actual vtleave has already been handled by xf86Events.c */
|
|
if (pdev)
|
|
pdev->flags |= XF86_PDEV_PAUSED;
|
|
else {
|
|
close(pInfo->fd);
|
|
systemd_logind_set_input_fd_for_all_devs(major, minor, -1, FALSE);
|
|
}
|
|
if (ack)
|
|
systemd_logind_ack_pause(info, major, minor);
|
|
}
|
|
else {
|
|
/* info->vt_active gets set by systemd_logind_vtenter() */
|
|
info->active = TRUE;
|
|
|
|
if (pdev)
|
|
pdev->flags &= ~XF86_PDEV_PAUSED;
|
|
else
|
|
systemd_logind_set_input_fd_for_all_devs(major, minor, fd,
|
|
info->vt_active);
|
|
|
|
/* Always call vtenter(), in case there are only legacy video devs */
|
|
systemd_logind_vtenter();
|
|
}
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
}
|
|
|
|
static void
|
|
connect_hook(DBusConnection *connection, void *data)
|
|
{
|
|
struct systemd_logind_info *info = data;
|
|
DBusError error;
|
|
DBusMessage *msg = NULL;
|
|
DBusMessage *reply = NULL;
|
|
dbus_int32_t arg;
|
|
char *session = NULL;
|
|
|
|
dbus_error_init(&error);
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1",
|
|
"/org/freedesktop/login1", "org.freedesktop.login1.Manager",
|
|
"GetSessionByPID");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
arg = getpid();
|
|
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &arg,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(connection, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply) {
|
|
LogMessage(X_ERROR, "systemd-logind: failed to get session: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
dbus_message_unref(msg);
|
|
|
|
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: GetSessionByPID: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
session = XNFstrdup(session);
|
|
|
|
dbus_message_unref(reply);
|
|
reply = NULL;
|
|
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1",
|
|
session, "org.freedesktop.login1.Session", "TakeControl");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
arg = FALSE; /* Don't forcibly take over over the session */
|
|
if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg,
|
|
DBUS_TYPE_INVALID)) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(connection, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply) {
|
|
LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
dbus_bus_add_match(connection,
|
|
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus'",
|
|
&error);
|
|
if (dbus_error_is_set(&error)) {
|
|
LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* HdG: This is not useful with systemd <= 208 since the signal only
|
|
* contains invalidated property names there, rather than property, val
|
|
* pairs as it should. Instead we just use the first resume / pause now.
|
|
*/
|
|
#if 0
|
|
snprintf(match, sizeof(match),
|
|
"type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='%s'",
|
|
session);
|
|
dbus_bus_add_match(connection, match, &error);
|
|
if (dbus_error_is_set(&error)) {
|
|
LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
#endif
|
|
|
|
if (!dbus_connection_add_filter(connection, message_filter, info, NULL)) {
|
|
LogMessage(X_ERROR, "systemd-logind: could not add filter: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
LogMessage(X_INFO, "systemd-logind: took control of session %s\n",
|
|
session);
|
|
info->conn = connection;
|
|
info->session = session;
|
|
info->vt_active = info->active = TRUE; /* The server owns the vt during init */
|
|
session = NULL;
|
|
|
|
cleanup:
|
|
free(session);
|
|
if (msg)
|
|
dbus_message_unref(msg);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
dbus_error_free(&error);
|
|
}
|
|
|
|
static void
|
|
systemd_logind_release_control(struct systemd_logind_info *info)
|
|
{
|
|
DBusError error;
|
|
DBusMessage *msg = NULL;
|
|
DBusMessage *reply = NULL;
|
|
|
|
dbus_error_init(&error);
|
|
|
|
msg = dbus_message_new_method_call("org.freedesktop.login1",
|
|
info->session, "org.freedesktop.login1.Session", "ReleaseControl");
|
|
if (!msg) {
|
|
LogMessage(X_ERROR, "systemd-logind: out of memory\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
|
|
DBUS_TIMEOUT_USE_DEFAULT, &error);
|
|
if (!reply) {
|
|
LogMessage(X_ERROR, "systemd-logind: ReleaseControl failed: %s\n",
|
|
error.message);
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if (msg)
|
|
dbus_message_unref(msg);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
dbus_error_free(&error);
|
|
}
|
|
|
|
static void
|
|
disconnect_hook(void *data)
|
|
{
|
|
struct systemd_logind_info *info = data;
|
|
|
|
free(info->session);
|
|
info->session = NULL;
|
|
info->conn = NULL;
|
|
}
|
|
|
|
static struct dbus_core_hook core_hook = {
|
|
.connect = connect_hook,
|
|
.disconnect = disconnect_hook,
|
|
.data = &logind_info,
|
|
};
|
|
|
|
int
|
|
systemd_logind_init(void)
|
|
{
|
|
return dbus_core_add_hook(&core_hook);
|
|
}
|
|
|
|
void
|
|
systemd_logind_fini(void)
|
|
{
|
|
if (logind_info.session)
|
|
systemd_logind_release_control(&logind_info);
|
|
|
|
dbus_core_remove_hook(&core_hook);
|
|
}
|