[PATCH 08/12] systemd-logind: Add systemd-logind "core"

David Herrmann dh.herrmann at gmail.com
Mon Jan 27 23:52:21 PST 2014


Hi Peter

On Tue, Jan 28, 2014 at 8:15 AM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> On Wed, Jan 15, 2014 at 03:32:22PM +0100, Hans de Goede wrote:
>> This commits add the bulk of the systemd-logind integration code, but does
>> not hook it up yet other then calling its init and fini functions, which
>> don't do that much.
>>
>> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>> ---
>>  configure.ac                                 |  21 ++
>>  hw/xfree86/common/xf86Init.c                 |   3 +
>>  hw/xfree86/common/xf86platformBus.c          |   2 +-
>>  hw/xfree86/common/xf86platformBus.h          |   1 +
>>  hw/xfree86/os-support/linux/Makefile.am      |   6 +
>>  hw/xfree86/os-support/linux/systemd-logind.c | 493 +++++++++++++++++++++++++++
>>  include/Makefile.am                          |   1 +
>>  include/dix-config.h.in                      |   3 +
>>  include/systemd-logind.h                     |  46 +++
>>  9 files changed, 575 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/xfree86/os-support/linux/systemd-logind.c
>>  create mode 100644 include/systemd-logind.h
>>
>> diff --git a/configure.ac b/configure.ac
>> index c277593..cb8d770 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -628,6 +628,7 @@ AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg
>>  AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
>>  AC_ARG_ENABLE(linux_acpi, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
>>  AC_ARG_ENABLE(linux_apm, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
>> +AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
>>
>>  dnl DDXes.
>>  AC_ARG_ENABLE(xorg,                AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
>> @@ -902,6 +903,26 @@ if test "x$CONFIG_HAL" = xyes; then
>>  fi
>>  AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
>>
>> +if test "x$SYSTEMD_LOGIND" = xauto; then
>> +        if test "x$HAVE_DBUS" = xyes -a "x$CONFIG_UDEV" = xyes ; then
>> +                SYSTEMD_LOGIND=yes
>> +        else
>> +                SYSTEMD_LOGIND=no
>> +        fi
>> +fi
>> +if test "x$SYSTEMD_LOGIND" = xyes; then
>> +        if ! test "x$HAVE_DBUS" = xyes; then
>> +                AC_MSG_ERROR([systemd-logind requested, but D-Bus is not installed.])
>> +        fi
>> +        if ! test "x$CONFIG_UDEV" = xyes ; then
>> +                AC_MSG_ERROR([systemd-logind is only supported in combination with udev configuration.])
>> +        fi
>> +
>> +        AC_DEFINE(SYSTEMD_LOGIND, 1, [Enable systemd-logind integration])
>> +        NEED_DBUS="yes"
>> +fi
>> +AM_CONDITIONAL(SYSTEMD_LOGIND, [test "x$SYSTEMD_LOGIND" = xyes])
>> +
>
> this looks a bit odd - don't we need to check for some systemd-specific bits as
> well here? if not, or if we're already checking for it, maybe note that in
> the commit message.

For the dbus-stuff it's fine to not check for any systemd stuff, but
the patch uses systemd/sd-login.h so we definitely need to check via
pkg-config here.

>>  if test "x$NEED_DBUS" = xyes; then
>>          AC_DEFINE(NEED_DBUS, 1, [Enable D-Bus core])
>>  fi
>> diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
>> index 815f679..380a70e 100644
>> --- a/hw/xfree86/common/xf86Init.c
>> +++ b/hw/xfree86/common/xf86Init.c
>> @@ -54,6 +54,7 @@
>>  #include "site.h"
>>  #include "mi.h"
>>  #include "dbus-core.h"
>> +#include "systemd-logind.h"
>>
>>  #include "compiler.h"
>>
>> @@ -458,6 +459,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
>>              DoShowOptions();
>>
>>          dbus_core_init();
>> +        systemd_logind_init();
>
> just making sure: we won't have a namespace clash with a current or furture
> systemd_logind_*? could always go for the tried and tested xfoo naming
> convention (xsystemd_logind_...)

systemd uses sd_* as global prefix, so no problem with that.

>>
>>          /* Do a general bus probe.  This will be a PCI probe for x86 platforms */
>>          xf86BusProbe();
>> @@ -1062,6 +1064,7 @@ ddxGiveUp(enum ExitCode error)
>>      if (xorgHWOpenConsole)
>>          xf86CloseConsole();
>>
>> +    systemd_logind_fini();
>>      dbus_core_fini();
>>
>>      xf86CloseLog(error);
>> diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
>> index 993d6a4..1b4b50f 100644
>> --- a/hw/xfree86/common/xf86platformBus.c
>> +++ b/hw/xfree86/common/xf86platformBus.c
>> @@ -52,7 +52,7 @@ int platformSlotClaimed;
>>
>>  int xf86_num_platform_devices;
>>
>> -static struct xf86_platform_device *xf86_platform_devices;
>> +struct xf86_platform_device *xf86_platform_devices;
>>
>>  int
>>  xf86_add_platform_device(struct OdevAttributes *attribs)
>> diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
>> index 4e17578..b986715 100644
>> --- a/hw/xfree86/common/xf86platformBus.h
>> +++ b/hw/xfree86/common/xf86platformBus.h
>> @@ -37,6 +37,7 @@ int xf86platformProbe(void);
>>  int xf86platformProbeDev(DriverPtr drvp);
>>
>>  extern int xf86_num_platform_devices;
>> +extern struct xf86_platform_device *xf86_platform_devices;
>>
>>  extern char *
>>  xf86_get_platform_attrib(int index, int attrib_id);
>> diff --git a/hw/xfree86/os-support/linux/Makefile.am b/hw/xfree86/os-support/linux/Makefile.am
>> index 83e7e00..1686dc2 100644
>> --- a/hw/xfree86/os-support/linux/Makefile.am
>> +++ b/hw/xfree86/os-support/linux/Makefile.am
>> @@ -21,6 +21,11 @@ APM_SRCS = lnx_apm.c
>>  XORG_CFLAGS += -DHAVE_APM
>>  endif
>>
>> +if SYSTEMD_LOGIND
>> +LOGIND_SRCS = systemd-logind.c
>> +XORG_CFLAGS += $(DBUS_CFLAGS)
>> +endif
>> +
>>  liblinux_la_SOURCES = lnx_init.c lnx_video.c \
>>                       lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \
>>                       $(srcdir)/../shared/bios_mmap.c \
>> @@ -30,6 +35,7 @@ liblinux_la_SOURCES = lnx_init.c lnx_video.c \
>>                    $(srcdir)/../shared/sigio.c \
>>                       $(ACPI_SRCS) \
>>                       $(APM_SRCS) \
>> +                     $(LOGIND_SRCS) \
>>                       $(PLATFORM_PCI_SUPPORT)
>>
>>  AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_DEFINES)
>> diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
>> new file mode 100644
>> index 0000000..f8be375
>> --- /dev/null
>> +++ b/hw/xfree86/os-support/linux/systemd-logind.c
>> @@ -0,0 +1,493 @@
>> +/*
>> + * 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 at redhat.com>
>> + */
>> +
>> +#ifdef HAVE_XORG_CONFIG_H
>> +#include <xorg-config.h>
>> +#endif
>> +
>> +#include <dbus/dbus.h>
>> +#include <string.h>
>> +#include <sys/types.h>
>> +#include <systemd/sd-login.h>
>> +#include <unistd.h>
>> +
>> +#include "os.h"
>> +#include "dbus-core.h"
>> +#include "xf86.h"
>> +#include "xf86platformBus.h"
>> +#include "xf86Xinput.h"
>> +
>> +#include "systemd-logind.h"
>> +
>> +#define DBUS_TIMEOUT 500 /* Wait max 0.5 seconds */
>> +
>> +struct systemd_logind_info {
>> +    DBusConnection *conn;
>> +    char *session;
>> +    Bool active;
>> +    Bool vt_active;
>> +};
>> +
>> +static struct systemd_logind_info logind_info;
>> +
>> +int
>> +systemd_logind_get_fd(dev_t devnum, const char *path, Bool *paused_ret)
>> +{
>> +    struct systemd_logind_info *info = &logind_info;
>> +    DBusError error;
>> +    DBusMessage *msg = NULL;
>> +    DBusMessage *reply = NULL;
>> +    dbus_int32_t minor = minor(devnum);
>> +    dbus_int32_t major = major(devnum);
>> +    dbus_bool_t paused;
>> +    int fd = -1;
>> +
>> +    if (!info->session || devnum == 0)
>> +        return -1;
>> +
>> +    /* logind does not support mouse devs (with evdev we don't need them) */
>> +    if (strstr(path, "mouse"))
>> +        return -1;
>
> hmm, is there some better way of checking this rather than a string
> comparison on the path?

You can use "devnum", but major/minor comparison is actually worse, so
seems fine to me.

>
>> +
>> +    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, &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_put_fd(dev_t devnum)
>
> I find it funny that you use get/put fd when the logind API itself calls it
> "take" and "release". maybe we should stick close to that naming?
> or get_fd and release_fd or so, I found put_fd a bit confusing.

+1 for dropping the weird kernel-style _get/put suffixes.

>
>> +{
>> +    struct systemd_logind_info *info = &logind_info;
>> +    DBusError error;
>> +    DBusMessage *msg = NULL;
>> +    DBusMessage *reply = NULL;
>> +    dbus_int32_t minor = minor(devnum);
>> +    dbus_int32_t major = major(devnum);
>> +
>> +    if (!info->session || devnum == 0)
>> +        return;
>> +
>> +    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, &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);
>> +}
>> +
>> +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++) {
>> +        struct OdevAttributes *attr = xf86_platform_devices[i].attribs;
>> +        if (attr->server_fd && attr->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);
>> +}
>> +
>> +static InputInfoPtr
>> +systemd_logind_find_info_ptr_by_devnum(int major, int minor)
>> +{
>> +    InputInfoPtr pInfo;
>> +
>> +    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
>> +        if (pInfo->major == major && pInfo->minor == minor &&
>> +                (pInfo->flags & XI86_SERVER_FD))
>> +            return pInfo;
>> +
>> +    return NULL;
>> +}
>> +
>> +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, &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 (strcmp(dbus_message_get_path(message), info->session) != 0)
>> +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
>> +
>> +    dbus_error_init(&error);
>> +
>> +    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(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->attribs->paused = TRUE;
>> +        else {
>> +            close(pInfo->fd);
>> +            pInfo->fd = -1;
>> +        }
>> +        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->attribs->paused = FALSE;
>> +            systemd_logind_vtenter();
>> +        }
>> +        else {
>> +            pInfo->fd = fd;
>> +            if (info->vt_active)
>> +                xf86EnableInputDeviceForVTSwitch(pInfo);
>> +        }
>> +    }
>> +    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, &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);
>
> I'm curious why you have all the errors above but here you're just briging
> down the server if it fails.
>
>> +
>> +    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;
>> +    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, &error);
>> +    if (!reply) {
>> +        LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
>> +                   error.message);
>> +        goto cleanup;
>> +    }
>> +
>> +    /*
>> +     * HdG: This is not useful with systemd <= 208 since the signal only
>> +     * contains invalidated property names there, rather then property, val
>
> typo: "than"
>
> Cheers,
>    Peter
>
>> +     * pairs as it should.  Instead we just use the first resume / pause now.
>> +     */

Actually you're supposed to send a Properties.GetAll() iff the
PropertiesChanged signal only contains the invalidation-information.
But the first resume/pause seems fine for xorg.

Thanks
David

>> +#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
>> +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)
>> +{
>> +    dbus_core_remove_hook(&core_hook);
>> +}
>> diff --git a/include/Makefile.am b/include/Makefile.am
>> index fa6da00..6578038 100644
>> --- a/include/Makefile.am
>> +++ b/include/Makefile.am
>> @@ -72,4 +72,5 @@ EXTRA_DIST =        \
>>       dix-config-apple-verbatim.h \
>>       dixfontstubs.h eventconvert.h eventstr.h inpututils.h \
>>       protocol-versions.h \
>> +     systemd-logind.h \
>>       xsha1.h
>> diff --git a/include/dix-config.h.in b/include/dix-config.h.in
>> index caea9b2..4931b9a 100644
>> --- a/include/dix-config.h.in
>> +++ b/include/dix-config.h.in
>> @@ -420,6 +420,9 @@
>>  /* Support HAL for hotplug */
>>  #undef CONFIG_HAL
>>
>> +/* Enable systemd-logind integration */
>> +#undef SYSTEMD_LOGIND 1
>> +
>>  /* Have a monotonic clock from clock_gettime() */
>>  #undef MONOTONIC_CLOCK
>>
>> diff --git a/include/systemd-logind.h b/include/systemd-logind.h
>> new file mode 100644
>> index 0000000..96ae6db
>> --- /dev/null
>> +++ b/include/systemd-logind.h
>> @@ -0,0 +1,46 @@
>> +/*
>> + * 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 at redhat.com>
>> + */
>> +
>> +#ifndef SYSTEMD_LOGIND_H
>> +#define SYSTEMD_LOGIND_H
>> +
>> +#include <sys/types.h>
>> +
>> +#ifdef SYSTEMD_LOGIND
>> +int systemd_logind_init(void);
>> +void systemd_logind_fini(void);
>> +int systemd_logind_get_fd(dev_t devnum, const char *path, Bool *paused_ret);
>> +void systemd_logind_put_fd(dev_t devnum);
>> +int systemd_logind_controls_session(void);
>> +void systemd_logind_vtenter(void);
>> +#else
>> +#define systemd_logind_init()
>> +#define systemd_logind_fini()
>> +#define systemd_logind_get_fd(dev) -1
>> +#define systemd_logind_controls_session() 0
>> +#define systemd_logind_vtenter()
>> +#endif
>> +
>> +#endif
>> --
>> 1.8.4.2
>>
>> _______________________________________________
>> xorg-devel at lists.x.org: X.Org development
>> Archives: http://lists.x.org/archives/xorg-devel
>> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel


More information about the xorg-devel mailing list