[PATCH v2 10/14] systemd-logind: Add systemd-logind "core"

Jasper St. Pierre jstpierre at mecheye.net
Mon Feb 10 21:58:24 CET 2014


Something I noticed here is that you use GetSessionByPID(). This works
right now, but with systemd user sessions, the display server will run
outside of a session. We have to decide what to do in this case.

One idea is to pass the object path of the logind session on the command
line from the display manager:

    Xorg -background none -retro -logind-session
/org/freedesktop/login1/session/_1 :0

Another option, which is what Colin did when he was bringing up systemd
user sessions, is to only allow one graphical session per user. In this
case, you'd call ListSessions(); and scan for the first "x11" session you
can find.

It might be a bit inappropriate to encode such a policy in the X server,
but if it's only under a command-line switch, it should be OK.


On Tue, Feb 4, 2014 at 6:49 AM, Hans de Goede <hdegoede at redhat.com> 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.
>
> Note the configure bits check for udev since systemd-logind use will only
> be
> supported in combination with udev. Besides that it only checks for dbus
> since all communication with systemd-logind is happening over dbus, so
> no further libs are needed.
>
> 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          |   2 +
>  hw/xfree86/os-support/linux/Makefile.am      |   6 +
>  hw/xfree86/os-support/linux/systemd-logind.c | 529
> +++++++++++++++++++++++++++
>  include/Makefile.am                          |   1 +
>  include/dix-config.h.in                      |   3 +
>  include/systemd-logind.h                     |  45 +++
>  9 files changed, 611 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 fe9b783..bc89bfe 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -626,6 +626,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, AS_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, AS_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])
> @@ -901,6 +902,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])
> +
>  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 ff4d38f..4579ff5 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();
>
>          /* 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 e1d7bd0..4447e19 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, Bool unowned)
> diff --git a/hw/xfree86/common/xf86platformBus.h
> b/hw/xfree86/common/xf86platformBus.h
> index 3e27d34..78b5a5b 100644
> --- a/hw/xfree86/common/xf86platformBus.h
> +++ b/hw/xfree86/common/xf86platformBus.h
> @@ -36,12 +36,14 @@ struct xf86_platform_device {
>  /* xf86_platform_device flags */
>  #define XF86_PDEV_UNOWNED       0x01
>  #define XF86_PDEV_SERVER_FD     0x02
> +#define XF86_PDEV_PAUSED        0x04
>
>  #ifdef XSERVER_PLATFORM_BUS
>  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..176defd
> --- /dev/null
> +++ b/hw/xfree86/os-support/linux/systemd-logind.c
> @@ -0,0 +1,529 @@
> +/*
> + * 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 <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_take_fd(int _major, int _minor, const char *path,
> +                       Bool *paused_ret)
> +{
> +    struct systemd_logind_info *info = &logind_info;
> +    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;
> +
> +    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_release_fd(int _major, int _minor)
> +{
> +    struct systemd_logind_info *info = &logind_info;
> +    DBusError error;
> +    DBusMessage *msg = NULL;
> +    DBusMessage *reply = NULL;
> +    dbus_int32_t major = _major;
> +    dbus_int32_t minor = _minor;
> +
> +    if (!info->session || major == 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++) {
> +        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);
> +}
> +
> +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->flags |= XF86_PDEV_PAUSED;
> +        else {
> +            close(pInfo->fd);
> +            pInfo->fd = -1;
> +            pInfo->options = xf86ReplaceIntOption(pInfo->options, "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->flags &= ~XF86_PDEV_PAUSED;
> +            systemd_logind_vtenter();
> +        }
> +        else {
> +            pInfo->fd = fd;
> +            pInfo->options = xf86ReplaceIntOption(pInfo->options, "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);
> +
> +    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 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,
> &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);
> +}
> 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 7c77956..3865d5e 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..7acc4ff
> --- /dev/null
> +++ b/include/systemd-logind.h
> @@ -0,0 +1,45 @@
> +/*
> + * 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
> +
> +#ifdef SYSTEMD_LOGIND
> +int systemd_logind_init(void);
> +void systemd_logind_fini(void);
> +int systemd_logind_take_fd(int major, int minor, const char *path, Bool
> *paus);
> +void systemd_logind_release_fd(int major, int minor);
> +int systemd_logind_controls_session(void);
> +void systemd_logind_vtenter(void);
> +#else
> +#define systemd_logind_init()
> +#define systemd_logind_fini()
> +#define systemd_logind_take_fd(major, minor, path) -1
> +#define systemd_logind_rekease_fd(dev)
> +#define systemd_logind_controls_session() 0
> +#define systemd_logind_vtenter()
> +#endif
> +
> +#endif
> --
> 1.8.5.3
>
> _______________________________________________
> 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




-- 
  Jasper
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.x.org/archives/xorg-devel/attachments/20140210/fbf65b7f/attachment-0001.html>


More information about the xorg-devel mailing list