mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-10-15 19:59:02 +00:00
launcher: add logind backend
Instead of connecting to weston-launch from launcher-util, we now try to connect to logind first. If logind provides session-devices, we use them. If not, we fall back to the old weston-launch facility.
This commit is contained in:
parent
e461f85385
commit
cc5b2ed2b8
17
configure.ac
17
configure.ac
|
@ -316,14 +316,21 @@ AC_ARG_ENABLE(resize-optimization,
|
|||
AS_IF([test "x$enable_resize_optimization" = "xyes"],
|
||||
[AC_DEFINE([USE_RESIZE_POOL], [1], [Use resize memory pool as a performance optimization])])
|
||||
|
||||
PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login],
|
||||
[have_systemd_login=yes], [have_systemd_login=no])
|
||||
AS_IF([test "x$have_systemd_login" = "xyes"],
|
||||
[AC_DEFINE([HAVE_SYSTEMD_LOGIN], [1], [Have systemd-login])])
|
||||
AM_CONDITIONAL(HAVE_SYSTEMD_LOGIN, test "x$have_systemd_login" = "xyes")
|
||||
|
||||
PKG_CHECK_MODULES(SYSTEMD_LOGIN_209, [libsystemd-login >= 209],
|
||||
[have_systemd_login_209=yes], [have_systemd_login_209=no])
|
||||
AS_IF([test "x$have_systemd_login_209" = "xyes"],
|
||||
[AC_DEFINE([HAVE_SYSTEMD_LOGIN_209], [1], [Have systemd-login >= 209])])
|
||||
|
||||
AC_ARG_ENABLE(weston-launch, [ --enable-weston-launch],, enable_weston_launch=yes)
|
||||
AM_CONDITIONAL(BUILD_WESTON_LAUNCH, test x$enable_weston_launch == xyes)
|
||||
if test x$enable_weston_launch == xyes; then
|
||||
PKG_CHECK_MODULES(WESTON_LAUNCH, [libdrm])
|
||||
PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login],
|
||||
[have_systemd_login=yes], [have_systemd_login=no])
|
||||
AS_IF([test "x$have_systemd_login" = "xyes"],
|
||||
[AC_DEFINE([HAVE_SYSTEMD_LOGIN], [1], [Have systemd-login])])
|
||||
|
||||
AC_CHECK_LIB([pam], [pam_open_session], [have_pam=yes], [have_pam=no])
|
||||
if test x$have_pam == xno; then
|
||||
|
@ -495,7 +502,7 @@ AC_MSG_RESULT([
|
|||
Build Tablet Shell ${enable_tablet_shell}
|
||||
|
||||
weston-launch utility ${enable_weston_launch}
|
||||
weston-launch systemd support ${have_systemd_login}
|
||||
systemd-login support ${have_systemd_login}
|
||||
|
||||
DRM Compositor ${enable_drm_compositor}
|
||||
X11 Compositor ${enable_x11_compositor}
|
||||
|
|
|
@ -55,6 +55,14 @@ weston_SOURCES += \
|
|||
dbus.c
|
||||
weston_CFLAGS += $(DBUS_CFLAGS)
|
||||
weston_LDADD += $(DBUS_LIBS)
|
||||
|
||||
if HAVE_SYSTEMD_LOGIN
|
||||
weston_SOURCES += \
|
||||
logind-util.h \
|
||||
logind-util.c
|
||||
weston_CFLAGS += $(SYSTEMD_LOGIN_CFLAGS)
|
||||
weston_LDADD += $(SYSTEMD_LOGIN_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
git-version.h : .FORCE
|
||||
|
|
|
@ -2623,7 +2623,8 @@ drm_compositor_create(struct wl_display *display,
|
|||
}
|
||||
|
||||
/* Check if we run drm-backend using weston-launch */
|
||||
ec->base.launcher = weston_launcher_connect(&ec->base, param->tty);
|
||||
ec->base.launcher = weston_launcher_connect(&ec->base, param->tty,
|
||||
param->seat_id);
|
||||
if (ec->base.launcher == NULL) {
|
||||
weston_log("fatal: drm backend should be run "
|
||||
"using weston-launch binary or as root\n");
|
||||
|
|
|
@ -894,7 +894,7 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[],
|
|||
wl_signal_add(&compositor->base.session_signal,
|
||||
&compositor->session_listener);
|
||||
compositor->base.launcher =
|
||||
weston_launcher_connect(&compositor->base, param->tty);
|
||||
weston_launcher_connect(&compositor->base, param->tty, "seat0");
|
||||
if (!compositor->base.launcher) {
|
||||
weston_log("fatal: fbdev backend should be run "
|
||||
"using weston-launch binary or as root\n");
|
||||
|
|
|
@ -752,7 +752,7 @@ rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
|
|||
wl_signal_add(&compositor->base.session_signal,
|
||||
&compositor ->session_listener);
|
||||
compositor->base.launcher =
|
||||
weston_launcher_connect(&compositor->base, param->tty);
|
||||
weston_launcher_connect(&compositor->base, param->tty, "seat0");
|
||||
if (!compositor->base.launcher) {
|
||||
weston_log("Failed to initialize tty.\n");
|
||||
goto out_udev;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "compositor.h"
|
||||
#include "launcher-util.h"
|
||||
#include "logind-util.h"
|
||||
#include "weston-launch.h"
|
||||
|
||||
#define DRM_MAJOR 226
|
||||
|
@ -57,6 +58,7 @@
|
|||
union cmsg_data { unsigned char b[4]; int fd; };
|
||||
|
||||
struct weston_launcher {
|
||||
struct weston_logind *logind;
|
||||
struct weston_compositor *compositor;
|
||||
int fd;
|
||||
struct wl_event_source *source;
|
||||
|
@ -104,6 +106,9 @@ weston_launcher_open(struct weston_launcher *launcher,
|
|||
struct weston_launcher_open *message;
|
||||
struct stat s;
|
||||
|
||||
if (launcher->logind)
|
||||
return weston_logind_open(launcher->logind, path, flags);
|
||||
|
||||
if (launcher->fd == -1) {
|
||||
fd = open(path, flags | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
|
@ -176,6 +181,9 @@ weston_launcher_open(struct weston_launcher *launcher,
|
|||
void
|
||||
weston_launcher_close(struct weston_launcher *launcher, int fd)
|
||||
{
|
||||
if (launcher->logind)
|
||||
return weston_logind_close(launcher->logind, fd);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
@ -184,6 +192,9 @@ weston_launcher_restore(struct weston_launcher *launcher)
|
|||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (launcher->logind)
|
||||
return weston_logind_restore(launcher->logind);
|
||||
|
||||
if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
|
||||
ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
|
||||
weston_log("failed to restore kb mode: %m\n");
|
||||
|
@ -342,19 +353,25 @@ setup_tty(struct weston_launcher *launcher, int tty)
|
|||
int
|
||||
weston_launcher_activate_vt(struct weston_launcher *launcher, int vt)
|
||||
{
|
||||
if (launcher->logind)
|
||||
return weston_logind_activate_vt(launcher->logind, vt);
|
||||
|
||||
return ioctl(launcher->tty, VT_ACTIVATE, vt);
|
||||
}
|
||||
|
||||
struct weston_launcher *
|
||||
weston_launcher_connect(struct weston_compositor *compositor, int tty)
|
||||
weston_launcher_connect(struct weston_compositor *compositor, int tty,
|
||||
const char *seat_id)
|
||||
{
|
||||
struct weston_launcher *launcher;
|
||||
struct wl_event_loop *loop;
|
||||
int r;
|
||||
|
||||
launcher = malloc(sizeof *launcher);
|
||||
if (launcher == NULL)
|
||||
return NULL;
|
||||
|
||||
launcher->logind = NULL;
|
||||
launcher->compositor = compositor;
|
||||
launcher->drm_fd = -1;
|
||||
launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
|
||||
|
@ -369,14 +386,21 @@ weston_launcher_connect(struct weston_compositor *compositor, int tty)
|
|||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
} else if (geteuid() == 0) {
|
||||
if (setup_tty(launcher, tty) == -1) {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
r = weston_logind_connect(&launcher->logind, compositor,
|
||||
seat_id, tty);
|
||||
if (r < 0) {
|
||||
launcher->logind = NULL;
|
||||
if (geteuid() == 0) {
|
||||
if (setup_tty(launcher, tty) == -1) {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
free(launcher);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return launcher;
|
||||
|
@ -385,6 +409,8 @@ weston_launcher_connect(struct weston_compositor *compositor, int tty)
|
|||
void
|
||||
weston_launcher_destroy(struct weston_launcher *launcher)
|
||||
{
|
||||
if (launcher->logind)
|
||||
weston_logind_destroy(launcher->logind);
|
||||
if (launcher->fd != -1) {
|
||||
close(launcher->fd);
|
||||
wl_event_source_remove(launcher->source);
|
||||
|
@ -393,6 +419,8 @@ weston_launcher_destroy(struct weston_launcher *launcher)
|
|||
wl_event_source_remove(launcher->vt_source);
|
||||
}
|
||||
|
||||
close(launcher->tty);
|
||||
if (launcher->tty >= 0)
|
||||
close(launcher->tty);
|
||||
|
||||
free(launcher);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
struct weston_launcher;
|
||||
|
||||
struct weston_launcher *
|
||||
weston_launcher_connect(struct weston_compositor *compositor, int tty);
|
||||
weston_launcher_connect(struct weston_compositor *compositor, int tty,
|
||||
const char *seat_id);
|
||||
|
||||
void
|
||||
weston_launcher_destroy(struct weston_launcher *launcher);
|
||||
|
|
913
src/logind-util.c
Normal file
913
src/logind-util.c
Normal file
|
@ -0,0 +1,913 @@
|
|||
/*
|
||||
* Copyright © 2013 David Herrmann
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <dbus.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <systemd/sd-login.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "compositor.h"
|
||||
#include "dbus.h"
|
||||
#include "logind-util.h"
|
||||
|
||||
#ifndef KDSKBMUTE
|
||||
#define KDSKBMUTE 0x4B51
|
||||
#endif
|
||||
|
||||
struct weston_logind {
|
||||
struct weston_compositor *compositor;
|
||||
char *seat;
|
||||
char *sid;
|
||||
unsigned int vtnr;
|
||||
int vt;
|
||||
int kb_mode;
|
||||
int sfd;
|
||||
struct wl_event_source *sfd_source;
|
||||
|
||||
DBusConnection *dbus;
|
||||
struct wl_event_source *dbus_ctx;
|
||||
char *spath;
|
||||
DBusPendingCall *pending_active;
|
||||
};
|
||||
|
||||
static int
|
||||
weston_logind_take_device(struct weston_logind *wl, uint32_t major,
|
||||
uint32_t minor, bool *paused_out)
|
||||
{
|
||||
DBusMessage *m, *reply;
|
||||
bool b, paused;
|
||||
int r, fd;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.login1.Session",
|
||||
"TakeDevice");
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
b = dbus_message_append_args(m,
|
||||
DBUS_TYPE_UINT32, &major,
|
||||
DBUS_TYPE_UINT32, &minor,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!b) {
|
||||
r = -ENOMEM;
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(wl->dbus, m,
|
||||
-1, NULL);
|
||||
if (!reply) {
|
||||
r = -ENODEV;
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
b = dbus_message_get_args(reply, NULL,
|
||||
DBUS_TYPE_UNIX_FD, &fd,
|
||||
DBUS_TYPE_BOOLEAN, &paused,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!b) {
|
||||
r = -ENODEV;
|
||||
goto err_reply;
|
||||
}
|
||||
|
||||
r = fd;
|
||||
if (paused_out)
|
||||
*paused_out = paused;
|
||||
|
||||
err_reply:
|
||||
dbus_message_unref(reply);
|
||||
err_unref:
|
||||
dbus_message_unref(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_release_device(struct weston_logind *wl, uint32_t major,
|
||||
uint32_t minor)
|
||||
{
|
||||
DBusMessage *m;
|
||||
bool b;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.login1.Session",
|
||||
"ReleaseDevice");
|
||||
if (m) {
|
||||
b = dbus_message_append_args(m,
|
||||
DBUS_TYPE_UINT32, &major,
|
||||
DBUS_TYPE_UINT32, &minor,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (b)
|
||||
dbus_connection_send(wl->dbus, m, NULL);
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_pause_device_complete(struct weston_logind *wl, uint32_t major,
|
||||
uint32_t minor)
|
||||
{
|
||||
DBusMessage *m;
|
||||
bool b;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.login1.Session",
|
||||
"PauseDeviceComplete");
|
||||
if (m) {
|
||||
b = dbus_message_append_args(m,
|
||||
DBUS_TYPE_UINT32, &major,
|
||||
DBUS_TYPE_UINT32, &minor,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (b)
|
||||
dbus_connection_send(wl->dbus, m, NULL);
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags)
|
||||
{
|
||||
struct stat st;
|
||||
int fl, r, fd;
|
||||
|
||||
r = stat(path, &st);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
return -ENODEV;
|
||||
|
||||
fd = weston_logind_take_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev), NULL);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
/* Compared to weston_launcher_open() we cannot specify the open-mode
|
||||
* directly. Instead, logind passes us an fd with sane default modes.
|
||||
* For DRM and evdev this means O_RDWR | O_CLOEXEC. If we want
|
||||
* something else, we need to change it afterwards. We currently
|
||||
* only support dropping FD_CLOEXEC and setting O_NONBLOCK. Changing
|
||||
* access-modes is not possible so accept whatever logind passes us. */
|
||||
|
||||
fl = fcntl(fd, F_GETFL);
|
||||
if (fl < 0) {
|
||||
r = -errno;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (flags & O_NONBLOCK)
|
||||
fl |= O_NONBLOCK;
|
||||
|
||||
r = fcntl(fd, F_SETFL, fl);
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
fl = fcntl(fd, F_GETFD);
|
||||
if (fl < 0) {
|
||||
r = -errno;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (!(flags & O_CLOEXEC))
|
||||
fl &= ~FD_CLOEXEC;
|
||||
|
||||
r = fcntl(fd, F_SETFD, fl);
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
err_close:
|
||||
close(fd);
|
||||
weston_logind_release_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev));
|
||||
return r;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_close(struct weston_logind *wl, int fd)
|
||||
{
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
r = fstat(fd, &st);
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot fstat fd: %m\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
weston_log("logind: invalid device passed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
weston_logind_release_device(wl, major(st.st_rdev),
|
||||
minor(st.st_rdev));
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_restore(struct weston_logind *wl)
|
||||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
ioctl(wl->vt, KDSETMODE, KD_TEXT);
|
||||
ioctl(wl->vt, KDSKBMUTE, 0);
|
||||
ioctl(wl->vt, KDSKBMODE, wl->kb_mode);
|
||||
mode.mode = VT_AUTO;
|
||||
ioctl(wl->vt, VT_SETMODE, &mode);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = ioctl(wl->vt, VT_ACTIVATE, vt);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_set_active(struct weston_logind *wl, bool active)
|
||||
{
|
||||
if (active)
|
||||
wl->compositor->session_active = 1;
|
||||
else
|
||||
wl->compositor->session_active = 0;
|
||||
|
||||
wl_signal_emit(&wl->compositor->session_signal,
|
||||
wl->compositor);
|
||||
}
|
||||
|
||||
static void
|
||||
get_active_cb(DBusPendingCall *pending, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
DBusMessage *m;
|
||||
DBusMessageIter iter, sub;
|
||||
int type;
|
||||
bool b;
|
||||
|
||||
dbus_pending_call_unref(wl->pending_active);
|
||||
wl->pending_active = NULL;
|
||||
|
||||
m = dbus_pending_call_steal_reply(pending);
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
type = dbus_message_get_type(m);
|
||||
if (type != DBUS_MESSAGE_TYPE_METHOD_RETURN)
|
||||
goto err_unref;
|
||||
|
||||
if (!dbus_message_iter_init(m, &iter) ||
|
||||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
|
||||
goto err_unref;
|
||||
|
||||
dbus_message_iter_recurse(&iter, &sub);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
|
||||
goto err_unref;
|
||||
|
||||
dbus_message_iter_get_basic(&sub, &b);
|
||||
weston_logind_set_active(wl, b);
|
||||
|
||||
err_unref:
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_get_active(struct weston_logind *wl)
|
||||
{
|
||||
DBusPendingCall *pending;
|
||||
DBusMessage *m;
|
||||
bool b;
|
||||
const char *iface, *name;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get");
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
iface = "org.freedesktop.login1.Session";
|
||||
name = "Active";
|
||||
b = dbus_message_append_args(m,
|
||||
DBUS_TYPE_STRING, &iface,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!b)
|
||||
goto err_unref;
|
||||
|
||||
b = dbus_connection_send_with_reply(wl->dbus, m, &pending, -1);
|
||||
if (!b)
|
||||
goto err_unref;
|
||||
|
||||
b = dbus_pending_call_set_notify(pending, get_active_cb, wl, NULL);
|
||||
if (!b) {
|
||||
dbus_pending_call_cancel(pending);
|
||||
dbus_pending_call_unref(pending);
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
if (wl->pending_active) {
|
||||
dbus_pending_call_cancel(wl->pending_active);
|
||||
dbus_pending_call_unref(wl->pending_active);
|
||||
}
|
||||
wl->pending_active = pending;
|
||||
return;
|
||||
|
||||
err_unref:
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
|
||||
static void
|
||||
disconnected_dbus(struct weston_logind *wl)
|
||||
{
|
||||
weston_log("logind: dbus connection lost, exiting..\n");
|
||||
weston_logind_restore(wl);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void
|
||||
session_removed(struct weston_logind *wl, DBusMessage *m)
|
||||
{
|
||||
const char *name, *obj;
|
||||
bool r;
|
||||
|
||||
r = dbus_message_get_args(m, NULL,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_OBJECT_PATH, &obj,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!r) {
|
||||
weston_log("logind: cannot parse SessionRemoved dbus signal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(name, wl->sid)) {
|
||||
weston_log("logind: our session got closed, exiting..\n");
|
||||
weston_logind_restore(wl);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
property_changed(struct weston_logind *wl, DBusMessage *m)
|
||||
{
|
||||
DBusMessageIter iter, sub, entry;
|
||||
const char *interface, *name;
|
||||
dbus_bool_t b;
|
||||
|
||||
if (!dbus_message_iter_init(m, &iter) ||
|
||||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
goto error;
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &interface);
|
||||
|
||||
if (!dbus_message_iter_next(&iter) ||
|
||||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
|
||||
goto error;
|
||||
|
||||
dbus_message_iter_recurse(&iter, &sub);
|
||||
|
||||
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY) {
|
||||
dbus_message_iter_recurse(&sub, &entry);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
|
||||
goto error;
|
||||
|
||||
dbus_message_iter_get_basic(&entry, &name);
|
||||
if (!dbus_message_iter_next(&entry))
|
||||
goto error;
|
||||
|
||||
if (!strcmp(name, "Active")) {
|
||||
if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_BOOLEAN) {
|
||||
dbus_message_iter_get_basic(&entry, &b);
|
||||
weston_logind_set_active(wl, b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dbus_message_iter_next(&sub);
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_next(&iter) ||
|
||||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
|
||||
goto error;
|
||||
|
||||
dbus_message_iter_recurse(&iter, &sub);
|
||||
|
||||
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
|
||||
dbus_message_iter_get_basic(&sub, &name);
|
||||
|
||||
if (!strcmp(name, "Active")) {
|
||||
weston_logind_get_active(wl);
|
||||
return;
|
||||
}
|
||||
|
||||
dbus_message_iter_next(&sub);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
weston_log("logind: cannot parse PropertiesChanged dbus signal\n");
|
||||
}
|
||||
|
||||
static void
|
||||
device_paused(struct weston_logind *wl, DBusMessage *m)
|
||||
{
|
||||
bool r;
|
||||
const char *type;
|
||||
uint32_t major, minor;
|
||||
|
||||
r = dbus_message_get_args(m, NULL,
|
||||
DBUS_TYPE_UINT32, &major,
|
||||
DBUS_TYPE_UINT32, &minor,
|
||||
DBUS_TYPE_STRING, &type,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!r) {
|
||||
weston_log("logind: cannot parse PauseDevice dbus signal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* "pause" means synchronous pausing. Acknowledge it unconditionally
|
||||
* as we support asynchronous device shutdowns, anyway.
|
||||
* "force" means asynchronous pausing. We ignore it as the following
|
||||
* session-deactivation will suffice as notification.
|
||||
* "gone" means the device is gone. We ignore it as we receive a
|
||||
* udev notification, anyway. */
|
||||
|
||||
if (!strcmp(type, "pause"))
|
||||
weston_logind_pause_device_complete(wl, major, minor);
|
||||
}
|
||||
|
||||
static void
|
||||
device_resumed(struct weston_logind *wl, DBusMessage *m)
|
||||
{
|
||||
/*
|
||||
* DeviceResumed messages provide us a new file-descriptor for
|
||||
* resumed devices. For DRM devices it's the same as before, for evdev
|
||||
* devices it's a new open-file. As we reopen evdev devices, anyway,
|
||||
* there is no need for us to handle this event. If we ever optimize
|
||||
* our evdev code to support resuming devices, this event can be
|
||||
* parsed like this:
|
||||
* r = dbus_message_get_args(m, NULL,
|
||||
* DBUS_TYPE_UINT32, &major,
|
||||
* DBUS_TYPE_UINT32, &minor,
|
||||
* DBUS_TYPE_UNIX_FD, &fd,
|
||||
* DBUS_TYPE_INVALID);
|
||||
*/
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
filter_dbus(DBusConnection *c, DBusMessage *m, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
|
||||
if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
||||
disconnected_dbus(wl);
|
||||
} else if (dbus_message_is_signal(m, "org.freedesktop.login1.Manager",
|
||||
"SessionRemoved")) {
|
||||
session_removed(wl, m);
|
||||
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged")) {
|
||||
property_changed(wl, m);
|
||||
} else if (dbus_message_is_signal(m, "org.freedesktop.login1.Session",
|
||||
"PauseDevice")) {
|
||||
device_paused(wl, m);
|
||||
} else if (dbus_message_is_signal(m, "org.freedesktop.login1.Session",
|
||||
"ResumeDevice")) {
|
||||
device_resumed(wl, m);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static int
|
||||
weston_logind_setup_dbus(struct weston_logind *wl)
|
||||
{
|
||||
bool b;
|
||||
int r;
|
||||
|
||||
r = asprintf(&wl->spath, "/org/freedesktop/login1/session/%s",
|
||||
wl->sid);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
b = dbus_connection_add_filter(wl->dbus, filter_dbus, wl, NULL);
|
||||
if (!b) {
|
||||
weston_log("logind: cannot add dbus filter\n");
|
||||
r = -ENOMEM;
|
||||
goto err_spath;
|
||||
}
|
||||
|
||||
r = weston_dbus_add_match_signal(wl->dbus,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SessionRemoved",
|
||||
"/org/freedesktop/login1");
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot add dbus match\n");
|
||||
goto err_spath;
|
||||
}
|
||||
|
||||
r = weston_dbus_add_match_signal(wl->dbus,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Session",
|
||||
"PauseDevice",
|
||||
wl->spath);
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot add dbus match\n");
|
||||
goto err_spath;
|
||||
}
|
||||
|
||||
r = weston_dbus_add_match_signal(wl->dbus,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Session",
|
||||
"ResumeDevice",
|
||||
wl->spath);
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot add dbus match\n");
|
||||
goto err_spath;
|
||||
}
|
||||
|
||||
r = weston_dbus_add_match_signal(wl->dbus,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
wl->spath);
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot add dbus match\n");
|
||||
goto err_spath;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_spath:
|
||||
/* don't remove any dbus-match as the connection is closed, anyway */
|
||||
free(wl->spath);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_destroy_dbus(struct weston_logind *wl)
|
||||
{
|
||||
/* don't remove any dbus-match as the connection is closed, anyway */
|
||||
free(wl->spath);
|
||||
}
|
||||
|
||||
static int
|
||||
weston_logind_take_control(struct weston_logind *wl)
|
||||
{
|
||||
DBusError err;
|
||||
DBusMessage *m, *reply;
|
||||
dbus_bool_t force;
|
||||
bool b;
|
||||
int r;
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.login1.Session",
|
||||
"TakeControl");
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
force = false;
|
||||
b = dbus_message_append_args(m,
|
||||
DBUS_TYPE_BOOLEAN, &force,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!b) {
|
||||
r = -ENOMEM;
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(wl->dbus,
|
||||
m, -1, &err);
|
||||
if (!reply) {
|
||||
if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD))
|
||||
weston_log("logind: old systemd version detected\n");
|
||||
else
|
||||
weston_log("logind: cannot take control over session %s\n", wl->sid);
|
||||
|
||||
dbus_error_free(&err);
|
||||
r = -EIO;
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
dbus_message_unref(reply);
|
||||
dbus_message_unref(m);
|
||||
return 0;
|
||||
|
||||
err_unref:
|
||||
dbus_message_unref(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_release_control(struct weston_logind *wl)
|
||||
{
|
||||
DBusMessage *m;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.login1",
|
||||
wl->spath,
|
||||
"org.freedesktop.login1.Session",
|
||||
"ReleaseControl");
|
||||
if (m) {
|
||||
dbus_connection_send(wl->dbus, m, NULL);
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
signal_event(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct weston_logind *wl = data;
|
||||
struct signalfd_siginfo sig;
|
||||
|
||||
if (read(fd, &sig, sizeof sig) != sizeof sig) {
|
||||
weston_log("logind: cannot read signalfd: %m\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (sig.ssi_signo) {
|
||||
case SIGUSR1:
|
||||
ioctl(wl->vt, VT_RELDISP, 1);
|
||||
break;
|
||||
case SIGUSR2:
|
||||
ioctl(wl->vt, VT_RELDISP, VT_ACKACQ);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
weston_logind_setup_vt(struct weston_logind *wl)
|
||||
{
|
||||
struct stat st;
|
||||
char buf[64];
|
||||
struct vt_mode mode = { 0 };
|
||||
int r;
|
||||
sigset_t mask;
|
||||
struct wl_event_loop *loop;
|
||||
|
||||
snprintf(buf, sizeof(buf), "/dev/tty%d", wl->vtnr);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
|
||||
wl->vt = open(buf, O_RDWR|O_CLOEXEC|O_NONBLOCK);
|
||||
|
||||
if (wl->vt < 0) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot open VT %s: %m\n", buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (fstat(wl->vt, &st) == -1 ||
|
||||
major(st.st_rdev) != TTY_MAJOR || minor(st.st_rdev) <= 0 ||
|
||||
minor(st.st_rdev) >= 64) {
|
||||
r = -EINVAL;
|
||||
weston_log("logind: TTY %s is no virtual terminal\n", buf);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
/*r = setsid();
|
||||
if (r < 0 && errno != EPERM) {
|
||||
r = -errno;
|
||||
weston_log("logind: setsid() failed: %m\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
r = ioctl(wl->vt, TIOCSCTTY, 0);
|
||||
if (r < 0)
|
||||
weston_log("logind: VT %s already in use\n", buf);*/
|
||||
|
||||
if (ioctl(wl->vt, KDGKBMODE, &wl->kb_mode) < 0) {
|
||||
weston_log("logind: cannot read keyboard mode on %s: %m\n",
|
||||
buf);
|
||||
wl->kb_mode = K_UNICODE;
|
||||
} else if (wl->kb_mode == K_OFF) {
|
||||
wl->kb_mode = K_UNICODE;
|
||||
}
|
||||
|
||||
if (ioctl(wl->vt, KDSKBMUTE, 1) < 0 &&
|
||||
ioctl(wl->vt, KDSKBMODE, K_OFF) < 0) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot set K_OFF KB-mode on %s: %m\n",
|
||||
buf);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (ioctl(wl->vt, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot set KD_GRAPHICS mode on %s: %m\n",
|
||||
buf);
|
||||
goto err_kbmode;
|
||||
}
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigaddset(&mask, SIGUSR2);
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
wl->sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (wl->sfd < 0) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot create signalfd: %m\n");
|
||||
goto err_mode;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(wl->compositor->wl_display);
|
||||
wl->sfd_source = wl_event_loop_add_fd(loop, wl->sfd,
|
||||
WL_EVENT_READABLE,
|
||||
signal_event, wl);
|
||||
if (!wl->sfd_source) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot create signalfd source: %m\n");
|
||||
goto err_sfd;
|
||||
}
|
||||
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGUSR1;
|
||||
mode.acqsig = SIGUSR2;
|
||||
if (ioctl(wl->vt, VT_SETMODE, &mode) < 0) {
|
||||
r = -errno;
|
||||
weston_log("logind: cannot take over VT: %m\n");
|
||||
goto err_sfd_source;
|
||||
}
|
||||
|
||||
weston_log("logind: using VT %s\n", buf);
|
||||
return 0;
|
||||
|
||||
err_sfd_source:
|
||||
wl_event_source_remove(wl->sfd_source);
|
||||
err_sfd:
|
||||
close(wl->sfd);
|
||||
err_mode:
|
||||
ioctl(wl->vt, KDSETMODE, KD_TEXT);
|
||||
err_kbmode:
|
||||
ioctl(wl->vt, KDSKBMUTE, 0);
|
||||
ioctl(wl->vt, KDSKBMODE, wl->kb_mode);
|
||||
err_close:
|
||||
close(wl->vt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_logind_destroy_vt(struct weston_logind *wl)
|
||||
{
|
||||
weston_logind_restore(wl);
|
||||
wl_event_source_remove(wl->sfd_source);
|
||||
close(wl->sfd);
|
||||
close(wl->vt);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty)
|
||||
{
|
||||
struct weston_logind *wl;
|
||||
struct wl_event_loop *loop;
|
||||
char *t;
|
||||
int r;
|
||||
|
||||
wl = calloc(1, sizeof(*wl));
|
||||
if (!wl) {
|
||||
r = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
wl->compositor = compositor;
|
||||
|
||||
wl->seat = strdup(seat_id);
|
||||
if (!wl->seat) {
|
||||
r = -ENOMEM;
|
||||
goto err_wl;
|
||||
}
|
||||
|
||||
r = sd_pid_get_session(getpid(), &wl->sid);
|
||||
if (r < 0) {
|
||||
weston_log("logind: not running in a systemd session\n");
|
||||
goto err_seat;
|
||||
}
|
||||
|
||||
t = NULL;
|
||||
r = sd_session_get_seat(wl->sid, &t);
|
||||
if (r < 0 || strcmp(seat_id, t)) {
|
||||
weston_log("logind: weston's seat '%s' differs from session-seat '%s'\n",
|
||||
seat_id, t);
|
||||
free(t);
|
||||
goto err_session;
|
||||
}
|
||||
free(t);
|
||||
|
||||
r = weston_sd_session_get_vt(wl->sid, &wl->vtnr);
|
||||
if (r < 0) {
|
||||
weston_log("logind: session not running on a VT\n");
|
||||
goto err_session;
|
||||
} else if (tty > 0 && wl->vtnr != (unsigned int )tty) {
|
||||
weston_log("logind: requested VT --tty=%d differs from real session VT %u\n",
|
||||
tty, wl->vtnr);
|
||||
goto err_session;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(compositor->wl_display);
|
||||
r = weston_dbus_open(loop, DBUS_BUS_SYSTEM, &wl->dbus, &wl->dbus_ctx);
|
||||
if (r < 0) {
|
||||
weston_log("logind: cannot connect to system dbus\n");
|
||||
goto err_session;
|
||||
}
|
||||
|
||||
r = weston_logind_setup_dbus(wl);
|
||||
if (r < 0)
|
||||
goto err_dbus;
|
||||
|
||||
r = weston_logind_take_control(wl);
|
||||
if (r < 0)
|
||||
goto err_dbus_cleanup;
|
||||
|
||||
r = weston_logind_setup_vt(wl);
|
||||
if (r < 0)
|
||||
goto err_control;
|
||||
|
||||
weston_log("logind: session control granted\n");
|
||||
*out = wl;
|
||||
return 0;
|
||||
|
||||
err_control:
|
||||
weston_logind_release_control(wl);
|
||||
err_dbus_cleanup:
|
||||
weston_logind_destroy_dbus(wl);
|
||||
err_dbus:
|
||||
weston_dbus_close(wl->dbus, wl->dbus_ctx);
|
||||
err_session:
|
||||
free(wl->sid);
|
||||
err_seat:
|
||||
free(wl->seat);
|
||||
err_wl:
|
||||
free(wl);
|
||||
err_out:
|
||||
weston_log("logind: cannot setup systemd-logind helper (%d), using legacy fallback\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
weston_logind_destroy(struct weston_logind *wl)
|
||||
{
|
||||
if (wl->pending_active) {
|
||||
dbus_pending_call_cancel(wl->pending_active);
|
||||
dbus_pending_call_unref(wl->pending_active);
|
||||
}
|
||||
|
||||
weston_logind_destroy_vt(wl);
|
||||
weston_logind_release_control(wl);
|
||||
weston_logind_destroy_dbus(wl);
|
||||
weston_dbus_close(wl->dbus, wl->dbus_ctx);
|
||||
free(wl->sid);
|
||||
free(wl->seat);
|
||||
free(wl);
|
||||
}
|
120
src/logind-util.h
Normal file
120
src/logind-util.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright © 2013 David Herrmann
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compositor.h"
|
||||
|
||||
struct weston_logind;
|
||||
|
||||
#if defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS)
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags);
|
||||
|
||||
void
|
||||
weston_logind_close(struct weston_logind *wl, int fd);
|
||||
|
||||
void
|
||||
weston_logind_restore(struct weston_logind *wl);
|
||||
|
||||
int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt);
|
||||
|
||||
int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty);
|
||||
|
||||
void
|
||||
weston_logind_destroy(struct weston_logind *wl);
|
||||
|
||||
static inline int
|
||||
weston_sd_session_get_vt(const char *sid, unsigned int *out)
|
||||
{
|
||||
#ifdef HAVE_SYSTEMD_LOGIN_209
|
||||
return sd_session_get_vt(sid, out);
|
||||
#else
|
||||
int r;
|
||||
char *tty;
|
||||
|
||||
r = sd_session_get_tty(sid, &tty);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sscanf(tty, "tty%u", out);
|
||||
free(tty);
|
||||
|
||||
if (r != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS) */
|
||||
|
||||
static inline int
|
||||
weston_logind_open(struct weston_logind *wl, const char *path,
|
||||
int flags)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_close(struct weston_logind *wl, int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_restore(struct weston_logind *wl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
weston_logind_activate_vt(struct weston_logind *wl, int vt)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
weston_logind_connect(struct weston_logind **out,
|
||||
struct weston_compositor *compositor,
|
||||
const char *seat_id, int tty)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
weston_logind_destroy(struct weston_logind *wl)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS) */
|
Loading…
Reference in a new issue