[PATCH weston 2/3] launcher: Split out launcher implementations into three distinct ones
Derek Foreman
derekf at osg.samsung.com
Wed Sep 23 11:42:13 PDT 2015
On 23/09/15 12:46 PM, Jasper St. Pierre wrote:
> We now have a launcher interface and distinct implementations for
> logind, weston-launch, and direct DRM, each in their own files.
>
> This helps up clean up the spaghetti code into something that's
> hopefully a bit more understood. There should be no functional
> changes here.
> ---
> Makefile.am | 7 +-
> src/launcher-direct.c | 315 +++++++++++++++++++++++++++++++
> src/launcher-impl.h | 45 +++++
> src/launcher-logind.c | 154 +++++++++------
> src/launcher-logind.h | 123 ------------
> src/launcher-util.c | 441 ++++---------------------------------------
> src/launcher-weston-launch.c | 302 +++++++++++++++++++++++++++++
> 7 files changed, 796 insertions(+), 591 deletions(-)
> create mode 100644 src/launcher-direct.c
> create mode 100644 src/launcher-impl.h
> delete mode 100644 src/launcher-logind.h
> create mode 100644 src/launcher-weston-launch.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 79a442c..94a824b 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -127,9 +127,11 @@ noinst_LTLIBRARIES += \
> libsession-helper.la
>
> libsession_helper_la_SOURCES = \
> - src/weston-launch.h \
> src/launcher-util.c \
> - src/launcher-util.h
> + src/launcher-util.h \
> + src/weston-launch.h \
> + src/launcher-weston-launch.c \
> + src/launcher-direct.c
> libsession_helper_la_CFLAGS = $(AM_CFLAGS) $(LIBDRM_CFLAGS) $(PIXMAN_CFLAGS) $(COMPOSITOR_CFLAGS)
> libsession_helper_la_LIBADD = $(LIBDRM_LIBS)
>
> @@ -138,7 +140,6 @@ if HAVE_SYSTEMD_LOGIN
> libsession_helper_la_SOURCES += \
> src/dbus.h \
> src/dbus.c \
> - src/launcher-logind.h \
> src/launcher-logind.c
> libsession_helper_la_CFLAGS += $(SYSTEMD_LOGIN_CFLAGS) $(DBUS_CFLAGS)
> libsession_helper_la_LIBADD += $(SYSTEMD_LOGIN_LIBS) $(DBUS_LIBS)
> diff --git a/src/launcher-direct.c b/src/launcher-direct.c
> new file mode 100644
> index 0000000..29d9c28
> --- /dev/null
> +++ b/src/launcher-direct.c
> @@ -0,0 +1,315 @@
> +/*
> + * Copyright © 2012 Benjamin Franzke
> + * Copyright © 2013 Intel Corporation
> + *
> + * 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 "compositor.h"
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <signal.h>
> +#include <sys/stat.h>
> +#include <sys/ioctl.h>
> +#include <linux/vt.h>
> +#include <linux/kd.h>
> +#include <linux/major.h>
> +
> +#include "launcher-impl.h"
> +
> +#define DRM_MAJOR 226
> +
> +#ifndef KDSKBMUTE
> +#define KDSKBMUTE 0x4B51
> +#endif
> +
> +#ifdef HAVE_LIBDRM
> +
> +#include <xf86drm.h>
> +
> +static inline int
> +is_drm_master(int drm_fd)
> +{
> + drm_magic_t magic;
> +
> + return drmGetMagic(drm_fd, &magic) == 0 &&
> + drmAuthMagic(drm_fd, magic) == 0;
> +}
> +
> +#else
> +
> +static inline int
> +drmDropMaster(int drm_fd)
> +{
> + return 0;
> +}
> +
> +static inline int
> +drmSetMaster(int drm_fd)
> +{
> + return 0;
> +}
> +
> +static inline int
> +is_drm_master(int drm_fd)
> +{
> + return 0;
> +}
> +
> +#endif
> +
> +struct launcher_direct {
> + struct weston_launcher base;
> + struct weston_compositor *compositor;
> + int kb_mode, tty, drm_fd;
> + struct wl_event_source *vt_source;
> +};
> +
> +static int
> +vt_handler(int signal_number, void *data)
> +{
> + struct launcher_direct *launcher = data;
> + struct weston_compositor *compositor = launcher->compositor;
> +
> + if (compositor->session_active) {
> + compositor->session_active = 0;
> + wl_signal_emit(&compositor->session_signal, compositor);
> + drmDropMaster(launcher->drm_fd);
> + ioctl(launcher->tty, VT_RELDISP, 1);
> + } else {
> + ioctl(launcher->tty, VT_RELDISP, VT_ACKACQ);
> + drmSetMaster(launcher->drm_fd);
> + compositor->session_active = 1;
> + wl_signal_emit(&compositor->session_signal, compositor);
> + }
> +
> + return 1;
> +}
> +
> +static int
> +setup_tty(struct launcher_direct *launcher, int tty)
> +{
> + struct wl_event_loop *loop;
> + struct vt_mode mode = { 0 };
> + struct stat buf;
> + char tty_device[32] ="<stdin>";
> + int ret, kd_mode;
> +
> + if (tty == 0) {
> + launcher->tty = dup(tty);
> + if (launcher->tty == -1) {
> + weston_log("couldn't dup stdin: %m\n");
> + return -1;
> + }
> + } else {
> + snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty);
> + launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC);
> + if (launcher->tty == -1) {
> + weston_log("couldn't open tty %s: %m\n", tty_device);
> + return -1;
> + }
> + }
> +
> + if (fstat(launcher->tty, &buf) == -1 ||
> + major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) {
> + weston_log("%s not a vt\n", tty_device);
> + weston_log("if running weston from ssh, "
> + "use --tty to specify a tty\n");
> + goto err_close;
> + }
> +
> + ret = ioctl(launcher->tty, KDGETMODE, &kd_mode);
> + if (ret) {
> + weston_log("failed to get VT mode: %m\n");
> + return -1;
> + }
> + if (kd_mode != KD_TEXT) {
> + weston_log("%s is already in graphics mode, "
> + "is another display server running?\n", tty_device);
> + goto err_close;
> + }
> +
> + ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev));
> + ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev));
> +
> + if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) {
> + weston_log("failed to read keyboard mode: %m\n");
> + goto err_close;
> + }
> +
> + if (ioctl(launcher->tty, KDSKBMUTE, 1) &&
> + ioctl(launcher->tty, KDSKBMODE, K_OFF)) {
> + weston_log("failed to set K_OFF keyboard mode: %m\n");
> + goto err_close;
> + }
> +
> + ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS);
> + if (ret) {
> + weston_log("failed to set KD_GRAPHICS mode on tty: %m\n");
> + goto err_close;
> + }
> +
> + /*
> + * SIGRTMIN is used as global VT-acquire+release signal. Note that
> + * SIGRT* must be tested on runtime, as their exact values are not
> + * known at compile-time. POSIX requires 32 of them to be available.
> + */
> + if (SIGRTMIN > SIGRTMAX) {
> + weston_log("not enough RT signals available: %u-%u\n",
> + SIGRTMIN, SIGRTMAX);
> + ret = -EINVAL;
> + goto err_close;
> + }
> +
> + mode.mode = VT_PROCESS;
> + mode.relsig = SIGRTMIN;
> + mode.acqsig = SIGRTMIN;
> + if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) {
> + weston_log("failed to take control of vt handling\n");
> + goto err_close;
> + }
> +
> + loop = wl_display_get_event_loop(launcher->compositor->wl_display);
> + launcher->vt_source =
> + wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher);
> + if (!launcher->vt_source)
> + goto err_close;
> +
> + return 0;
> +
> + err_close:
> + close(launcher->tty);
> + return -1;
> +}
> +
> +static int
> +launcher_direct_open(struct weston_launcher *launcher_base, const char *path, int flags)
> +{
> + struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
> + struct stat s;
> + int fd;
> +
> + fd = open(path, flags | O_CLOEXEC);
> + if (fd == -1)
> + return -1;
> +
> + if (fstat(fd, &s) == -1) {
> + close(fd);
> + return -1;
> + }
> +
> + if (major(s.st_rdev) == DRM_MAJOR) {
> + launcher->drm_fd = fd;
> + if (!is_drm_master(fd)) {
> + weston_log("drm fd not master\n");
> + close(fd);
> + return -1;
> + }
> + }
> +
> + return fd;
> +}
> +
> +static void
> +launcher_direct_close(struct weston_launcher *launcher_base, int fd)
> +{
> + close(fd);
> +}
> +
> +static void
> +launcher_direct_restore(struct weston_launcher *launcher_base)
> +{
> + struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
> + struct vt_mode mode = { 0 };
> +
> + if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
> + ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
> + weston_log("failed to restore kb mode: %m\n");
> +
> + if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
> + weston_log("failed to set KD_TEXT mode on tty: %m\n");
> +
> + /* We have to drop master before we switch the VT back in
> + * VT_AUTO, so we don't risk switching to a VT with another
> + * display server, that will then fail to set drm master. */
> + drmDropMaster(launcher->drm_fd);
> +
> + mode.mode = VT_AUTO;
> + if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
> + weston_log("could not reset vt handling\n");
> +}
> +
> +static int
> +launcher_direct_activate_vt(struct weston_launcher *launcher_base, int vt)
> +{
> + struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
> + return ioctl(launcher->tty, VT_ACTIVATE, vt);
> +}
> +
> +static int
> +launcher_direct_connect(struct weston_launcher **out, struct weston_compositor *compositor,
> + int tty, const char *seat_id, bool sync_drm)
> +{
> + struct launcher_direct *launcher;
> +
> + if (geteuid() != 0)
> + return -EINVAL;
> +
> + launcher = zalloc(sizeof(*launcher));
> + if (launcher == NULL)
> + return -ENOMEM;
> +
> + launcher->base.iface = &launcher_direct_iface;
> + launcher->compositor = compositor;
> +
> + if (setup_tty(launcher, tty) == -1) {
> + free(launcher);
> + return -1;
> + }
> +
> + * (struct launcher_direct **) out = launcher;
> + return 0;
> +}
> +
> +static void
> +launcher_direct_destroy(struct weston_launcher *launcher_base)
> +{
> + struct launcher_direct *launcher = wl_container_of(launcher_base, launcher, base);
> +
> + launcher_direct_restore(&launcher->base);
> + wl_event_source_remove(launcher->vt_source);
> +
> + if (launcher->tty >= 0)
> + close(launcher->tty);
> +
> + free(launcher);
> +}
> +
> +struct launcher_interface launcher_direct_iface = {
> + launcher_direct_connect,
> + launcher_direct_destroy,
> + launcher_direct_open,
> + launcher_direct_close,
> + launcher_direct_activate_vt,
> + launcher_direct_restore,
> +};
> diff --git a/src/launcher-impl.h b/src/launcher-impl.h
> new file mode 100644
> index 0000000..742721b
> --- /dev/null
> +++ b/src/launcher-impl.h
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright © 2015 Jasper St. Pierre
> + *
> + * 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 "compositor.h"
> +
> +struct weston_launcher;
> +
> +struct launcher_interface {
> + int (* connect) (struct weston_launcher **launcher_out, struct weston_compositor *compositor,
> + int tty, const char *seat_id, bool sync_drm);
> + void (* destroy) (struct weston_launcher *launcher);
> + int (* open) (struct weston_launcher *launcher, const char *path, int flags);
> + void (* close) (struct weston_launcher *launcher, int fd);
> + int (* activate_vt) (struct weston_launcher *launcher, int vt);
> + void (* restore) (struct weston_launcher *launcher);
> +};
> +
> +struct weston_launcher {
> + struct launcher_interface *iface;
> +};
> +
> +extern struct launcher_interface launcher_logind_iface;
> +extern struct launcher_interface launcher_weston_launch_iface;
> +extern struct launcher_interface launcher_direct_iface;
> diff --git a/src/launcher-logind.c b/src/launcher-logind.c
> index 4fab9a4..c148b24 100644
> --- a/src/launcher-logind.c
> +++ b/src/launcher-logind.c
> @@ -44,7 +44,7 @@
>
> #include "compositor.h"
> #include "dbus.h"
> -#include "launcher-logind.h"
> +#include "launcher-impl.h"
>
> #define DRM_MAJOR 226
>
> @@ -52,7 +52,8 @@
> #define KDSKBMUTE 0x4B51
> #endif
>
> -struct weston_logind {
> +struct launcher_logind {
> + struct weston_launcher base;
> struct weston_compositor *compositor;
> bool sync_drm;
> char *seat;
> @@ -70,7 +71,7 @@ struct weston_logind {
> };
>
> static int
> -weston_logind_take_device(struct weston_logind *wl, uint32_t major,
> +launcher_logind_take_device(struct launcher_logind *wl, uint32_t major,
> uint32_t minor, bool *paused_out)
> {
> DBusMessage *m, *reply;
> @@ -122,7 +123,7 @@ err_unref:
> }
>
> static void
> -weston_logind_release_device(struct weston_logind *wl, uint32_t major,
> +launcher_logind_release_device(struct launcher_logind *wl, uint32_t major,
> uint32_t minor)
> {
> DBusMessage *m;
> @@ -144,7 +145,7 @@ weston_logind_release_device(struct weston_logind *wl, uint32_t major,
> }
>
> static void
> -weston_logind_pause_device_complete(struct weston_logind *wl, uint32_t major,
> +launcher_logind_pause_device_complete(struct launcher_logind *wl, uint32_t major,
> uint32_t minor)
> {
> DBusMessage *m;
> @@ -165,10 +166,10 @@ weston_logind_pause_device_complete(struct weston_logind *wl, uint32_t major,
> }
> }
>
> -WL_EXPORT int
> -weston_logind_open(struct weston_logind *wl, const char *path,
> - int flags)
> +static int
> +launcher_logind_open(struct weston_launcher *launcher, const char *path, int flags)
> {
> + struct launcher_logind *wl = wl_container_of(launcher, wl, base);
> struct stat st;
> int fl, r, fd;
>
> @@ -180,7 +181,7 @@ weston_logind_open(struct weston_logind *wl, const char *path,
> return -1;
> }
>
> - fd = weston_logind_take_device(wl, major(st.st_rdev),
> + fd = launcher_logind_take_device(wl, major(st.st_rdev),
> minor(st.st_rdev), NULL);
> if (fd < 0)
> return fd;
> @@ -210,15 +211,16 @@ weston_logind_open(struct weston_logind *wl, const char *path,
>
> err_close:
> close(fd);
> - weston_logind_release_device(wl, major(st.st_rdev),
> + launcher_logind_release_device(wl, major(st.st_rdev),
> minor(st.st_rdev));
> errno = -r;
> return -1;
> }
>
> -WL_EXPORT void
> -weston_logind_close(struct weston_logind *wl, int fd)
> +static void
> +launcher_logind_close(struct weston_launcher *launcher, int fd)
> {
> + struct launcher_logind *wl = wl_container_of(launcher, wl, base);
> struct stat st;
> int r;
>
> @@ -233,13 +235,14 @@ weston_logind_close(struct weston_logind *wl, int fd)
> return;
> }
>
> - weston_logind_release_device(wl, major(st.st_rdev),
> + launcher_logind_release_device(wl, major(st.st_rdev),
> minor(st.st_rdev));
> }
>
> -WL_EXPORT void
> -weston_logind_restore(struct weston_logind *wl)
> +static void
> +launcher_logind_restore(struct weston_launcher *launcher)
> {
> + struct launcher_logind *wl = wl_container_of(launcher, wl, base);
> struct vt_mode mode = { 0 };
>
> ioctl(wl->vt, KDSETMODE, KD_TEXT);
> @@ -249,9 +252,10 @@ weston_logind_restore(struct weston_logind *wl)
> ioctl(wl->vt, VT_SETMODE, &mode);
> }
>
> -WL_EXPORT int
> -weston_logind_activate_vt(struct weston_logind *wl, int vt)
> +static int
> +launcher_logind_activate_vt(struct weston_launcher *launcher, int vt)
> {
> + struct launcher_logind *wl = wl_container_of(launcher, wl, base);
> int r;
>
> r = ioctl(wl->vt, VT_ACTIVATE, vt);
> @@ -262,7 +266,7 @@ weston_logind_activate_vt(struct weston_logind *wl, int vt)
> }
>
> static void
> -weston_logind_set_active(struct weston_logind *wl, bool active)
> +launcher_logind_set_active(struct launcher_logind *wl, bool active)
> {
> if (!wl->compositor->session_active == !active)
> return;
> @@ -274,7 +278,7 @@ weston_logind_set_active(struct weston_logind *wl, bool active)
> }
>
> static void
> -parse_active(struct weston_logind *wl, DBusMessage *m, DBusMessageIter *iter)
> +parse_active(struct launcher_logind *wl, DBusMessage *m, DBusMessageIter *iter)
> {
> DBusMessageIter sub;
> dbus_bool_t b;
> @@ -293,13 +297,13 @@ parse_active(struct weston_logind *wl, DBusMessage *m, DBusMessageIter *iter)
> * wake-up the compositor once the master-device is up and running. For
> * other backends, we immediately forward the Active-change event. */
> if (!wl->sync_drm || !b)
> - weston_logind_set_active(wl, b);
> + launcher_logind_set_active(wl, b);
> }
>
> static void
> get_active_cb(DBusPendingCall *pending, void *data)
> {
> - struct weston_logind *wl = data;
> + struct launcher_logind *wl = data;
> DBusMessageIter iter;
> DBusMessage *m;
> int type;
> @@ -320,7 +324,7 @@ get_active_cb(DBusPendingCall *pending, void *data)
> }
>
> static void
> -weston_logind_get_active(struct weston_logind *wl)
> +launcher_logind_get_active(struct launcher_logind *wl)
> {
> DBusPendingCall *pending;
> DBusMessage *m;
> @@ -366,15 +370,15 @@ err_unref:
> }
>
> static void
> -disconnected_dbus(struct weston_logind *wl)
> +disconnected_dbus(struct launcher_logind *wl)
> {
> weston_log("logind: dbus connection lost, exiting..\n");
> - weston_logind_restore(wl);
> + launcher_logind_restore(&wl->base);
> exit(-1);
> }
>
> static void
> -session_removed(struct weston_logind *wl, DBusMessage *m)
> +session_removed(struct launcher_logind *wl, DBusMessage *m)
> {
> const char *name, *obj;
> bool r;
> @@ -390,13 +394,13 @@ session_removed(struct weston_logind *wl, DBusMessage *m)
>
> if (!strcmp(name, wl->sid)) {
> weston_log("logind: our session got closed, exiting..\n");
> - weston_logind_restore(wl);
> + launcher_logind_restore(&wl->base);
> exit(-1);
> }
> }
>
> static void
> -property_changed(struct weston_logind *wl, DBusMessage *m)
> +property_changed(struct launcher_logind *wl, DBusMessage *m)
> {
> DBusMessageIter iter, sub, entry;
> const char *interface, *name;
> @@ -441,7 +445,7 @@ property_changed(struct weston_logind *wl, DBusMessage *m)
> dbus_message_iter_get_basic(&sub, &name);
>
> if (!strcmp(name, "Active")) {
> - weston_logind_get_active(wl);
> + launcher_logind_get_active(wl);
> return;
> }
>
> @@ -455,7 +459,7 @@ error:
> }
>
> static void
> -device_paused(struct weston_logind *wl, DBusMessage *m)
> +device_paused(struct launcher_logind *wl, DBusMessage *m)
> {
> bool r;
> const char *type;
> @@ -480,14 +484,14 @@ device_paused(struct weston_logind *wl, DBusMessage *m)
> * If it's our main DRM device, tell the compositor to go asleep. */
>
> if (!strcmp(type, "pause"))
> - weston_logind_pause_device_complete(wl, major, minor);
> + launcher_logind_pause_device_complete(wl, major, minor);
>
> if (wl->sync_drm && major == DRM_MAJOR)
> - weston_logind_set_active(wl, false);
> + launcher_logind_set_active(wl, false);
> }
>
> static void
> -device_resumed(struct weston_logind *wl, DBusMessage *m)
> +device_resumed(struct launcher_logind *wl, DBusMessage *m)
> {
> bool r;
> uint32_t major;
> @@ -509,13 +513,13 @@ device_resumed(struct weston_logind *wl, DBusMessage *m)
> * notify the compositor to wake up. */
>
> if (wl->sync_drm && major == DRM_MAJOR)
> - weston_logind_set_active(wl, true);
> + launcher_logind_set_active(wl, true);
> }
>
> static DBusHandlerResult
> filter_dbus(DBusConnection *c, DBusMessage *m, void *data)
> {
> - struct weston_logind *wl = data;
> + struct launcher_logind *wl = data;
>
> if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
> disconnected_dbus(wl);
> @@ -537,7 +541,7 @@ filter_dbus(DBusConnection *c, DBusMessage *m, void *data)
> }
>
> static int
> -weston_logind_setup_dbus(struct weston_logind *wl)
> +launcher_logind_setup_dbus(struct launcher_logind *wl)
> {
> bool b;
> int r;
> @@ -603,14 +607,14 @@ err_spath:
> }
>
> static void
> -weston_logind_destroy_dbus(struct weston_logind *wl)
> +launcher_logind_destroy_dbus(struct launcher_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)
> +launcher_logind_take_control(struct launcher_logind *wl)
> {
> DBusError err;
> DBusMessage *m, *reply;
> @@ -659,7 +663,7 @@ err_unref:
> }
>
> static void
> -weston_logind_release_control(struct weston_logind *wl)
> +launcher_logind_release_control(struct launcher_logind *wl)
> {
> DBusMessage *m;
>
> @@ -676,7 +680,7 @@ weston_logind_release_control(struct weston_logind *wl)
> static int
> signal_event(int fd, uint32_t mask, void *data)
> {
> - struct weston_logind *wl = data;
> + struct launcher_logind *wl = data;
> struct signalfd_siginfo sig;
>
> if (read(fd, &sig, sizeof sig) != sizeof sig) {
> @@ -693,7 +697,7 @@ signal_event(int fd, uint32_t mask, void *data)
> }
>
> static int
> -weston_logind_setup_vt(struct weston_logind *wl)
> +launcher_logind_setup_vt(struct launcher_logind *wl)
> {
> struct stat st;
> char buf[64];
> @@ -816,20 +820,42 @@ err_close:
> }
>
> static void
> -weston_logind_destroy_vt(struct weston_logind *wl)
> +launcher_logind_destroy_vt(struct launcher_logind *wl)
> {
> - weston_logind_restore(wl);
> + launcher_logind_restore(&wl->base);
> 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, bool sync_drm)
> +static int
> +weston_sd_session_get_vt(const char *sid, unsigned int *out)
> {
> - struct weston_logind *wl;
> +#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
> +}
> +
> +static int
> +launcher_logind_connect(struct weston_launcher **out, struct weston_compositor *compositor,
> + int tty, const char *seat_id, bool sync_drm)
> +{
> + struct launcher_logind *wl;
> struct wl_event_loop *loop;
> char *t;
> int r;
> @@ -840,6 +866,7 @@ weston_logind_connect(struct weston_logind **out,
> goto err_out;
> }
>
> + wl->base.iface = &launcher_logind_iface;
> wl->compositor = compositor;
> wl->sync_drm = sync_drm;
>
> @@ -888,26 +915,26 @@ weston_logind_connect(struct weston_logind **out,
> goto err_session;
> }
>
> - r = weston_logind_setup_dbus(wl);
> + r = launcher_logind_setup_dbus(wl);
> if (r < 0)
> goto err_dbus;
>
> - r = weston_logind_take_control(wl);
> + r = launcher_logind_take_control(wl);
> if (r < 0)
> goto err_dbus_cleanup;
>
> - r = weston_logind_setup_vt(wl);
> + r = launcher_logind_setup_vt(wl);
> if (r < 0)
> goto err_control;
>
> weston_log("logind: session control granted\n");
> - *out = wl;
> + * (struct launcher_logind **) out = wl;
> return 0;
>
> err_control:
> - weston_logind_release_control(wl);
> + launcher_logind_release_control(wl);
> err_dbus_cleanup:
> - weston_logind_destroy_dbus(wl);
> + launcher_logind_destroy_dbus(wl);
> err_dbus:
> weston_dbus_close(wl->dbus, wl->dbus_ctx);
> err_session:
> @@ -922,19 +949,30 @@ err_out:
> return -1;
> }
>
> -WL_EXPORT void
> -weston_logind_destroy(struct weston_logind *wl)
> +static void
> +launcher_logind_destroy(struct weston_launcher *launcher)
> {
> + struct launcher_logind *wl = wl_container_of(launcher, wl, base);
> +
> 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);
> + launcher_logind_destroy_vt(wl);
> + launcher_logind_release_control(wl);
> + launcher_logind_destroy_dbus(wl);
> weston_dbus_close(wl->dbus, wl->dbus_ctx);
> free(wl->sid);
> free(wl->seat);
> free(wl);
> }
> +
> +struct launcher_interface launcher_logind_iface = {
> + launcher_logind_connect,
> + launcher_logind_destroy,
> + launcher_logind_open,
> + launcher_logind_close,
> + launcher_logind_activate_vt,
> + launcher_logind_restore,
> +};
> diff --git a/src/launcher-logind.h b/src/launcher-logind.h
> deleted file mode 100644
> index 1bc4961..0000000
> --- a/src/launcher-logind.h
> +++ /dev/null
> @@ -1,123 +0,0 @@
> -/*
> - * Copyright © 2013 David Herrmann
> - *
> - * 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.
> - */
> -
> -#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, bool sync_drm);
> -
> -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, bool sync_drm)
> -{
> - return -ENOSYS;
> -}
> -
> -static inline void
> -weston_logind_destroy(struct weston_logind *wl)
> -{
> -}
> -
> -#endif /* defined(HAVE_SYSTEMD_LOGIN) && defined(HAVE_DBUS) */
> diff --git a/src/launcher-util.c b/src/launcher-util.c
> index dc02dff..f0f4e8a 100644
> --- a/src/launcher-util.c
> +++ b/src/launcher-util.c
> @@ -26,440 +26,67 @@
>
> #include "config.h"
>
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -
> -#include <errno.h>
> -#include <signal.h>
> -#include <sys/socket.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/uio.h>
> -#include <sys/ioctl.h>
> -#include <fcntl.h>
> -#include <unistd.h>
> -#include <linux/vt.h>
> -#include <linux/kd.h>
> -#include <linux/major.h>
> -
> #include "compositor.h"
> +
> #include "launcher-util.h"
> -#include "launcher-logind.h"
> -#include "weston-launch.h"
> +#include "launcher-impl.h"
>
> -#define DRM_MAJOR 226
> +#include <unistd.h>
>
> -#ifndef KDSKBMUTE
> -#define KDSKBMUTE 0x4B51
> +static struct launcher_interface *ifaces[] = {
> +#ifdef HAVE_SYSTEMD_LOGIN
> + &launcher_logind_iface,
> #endif
> + &launcher_weston_launch_iface,
> + &launcher_direct_iface,
> + NULL,
> +};
>
> -#ifdef HAVE_LIBDRM
> -
> -#include <xf86drm.h>
> -
> -static inline int
> -is_drm_master(int drm_fd)
> +WL_EXPORT struct weston_launcher *
> +weston_launcher_connect(struct weston_compositor *compositor, int tty,
> + const char *seat_id, bool sync_drm)
> {
> - drm_magic_t magic;
> + struct launcher_interface **it;
>
> - return drmGetMagic(drm_fd, &magic) == 0 &&
> - drmAuthMagic(drm_fd, magic) == 0;
> -}
> + for (it = ifaces; *it != NULL; it++) {
> + struct launcher_interface *iface = *it;
> + struct weston_launcher *launcher;
>
> -#else
> -
> -static inline int
> -drmDropMaster(int drm_fd)
> -{
> - return 0;
> -}
> + if (iface->connect(&launcher, compositor, tty, seat_id, sync_drm) == 0)
> + return launcher;
> + }
>
> -static inline int
> -drmSetMaster(int drm_fd)
> -{
> - return 0;
> + return NULL;
> }
>
> -static inline int
> -is_drm_master(int drm_fd)
> +WL_EXPORT void
> +weston_launcher_destroy(struct weston_launcher *launcher)
> {
> - return 0;
> + launcher->iface->destroy(launcher);
> + free(launcher);
This results in a double free since the destroy vfuncs already free
launcher...
I like the series, seems a nice clean up/refactor to me.
With the double free fixed, the whole thing is
Reviewed-by: Derek Foreman <derekf at osg.samsung.com>
> }
>
> -#endif
> -
> -
> -union cmsg_data { unsigned char b[4]; int fd; };
> -
> -struct weston_launcher {
> - struct weston_compositor *compositor;
> - struct weston_logind *logind;
> - struct wl_event_loop *loop;
> - int fd;
> - struct wl_event_source *source;
> -
> - int kb_mode, tty, drm_fd;
> - struct wl_event_source *vt_source;
> -};
> -
> -int
> +WL_EXPORT int
> weston_launcher_open(struct weston_launcher *launcher,
> const char *path, int flags)
> {
> - int n, fd, ret = -1;
> - struct msghdr msg;
> - struct cmsghdr *cmsg;
> - struct iovec iov;
> - union cmsg_data *data;
> - char control[CMSG_SPACE(sizeof data->fd)];
> - ssize_t len;
> - struct weston_launcher_open *message;
> - struct stat s;
> -
> - /* We really don't want to be leaking fds to child processes so
> - * we force this flag here. If someone comes up with a legitimate
> - * reason to not CLOEXEC they'll need to unset the flag manually.
> - */
> - flags |= O_CLOEXEC;
> -
> - if (launcher->logind)
> - return weston_logind_open(launcher->logind, path, flags);
> -
> - if (launcher->fd == -1) {
> - fd = open(path, flags);
> - if (fd == -1)
> - return -1;
> -
> - if (fstat(fd, &s) == -1) {
> - close(fd);
> - return -1;
> - }
> -
> - if (major(s.st_rdev) == DRM_MAJOR) {
> - launcher->drm_fd = fd;
> - if (!is_drm_master(fd)) {
> - weston_log("drm fd not master\n");
> - close(fd);
> - return -1;
> - }
> - }
> -
> - return fd;
> - }
> -
> - n = sizeof(*message) + strlen(path) + 1;
> - message = malloc(n);
> - if (!message)
> - return -1;
> -
> - message->header.opcode = WESTON_LAUNCHER_OPEN;
> - message->flags = flags;
> - strcpy(message->path, path);
> -
> - do {
> - len = send(launcher->fd, message, n, 0);
> - } while (len < 0 && errno == EINTR);
> - free(message);
> -
> - memset(&msg, 0, sizeof msg);
> - iov.iov_base = &ret;
> - iov.iov_len = sizeof ret;
> - msg.msg_iov = &iov;
> - msg.msg_iovlen = 1;
> - msg.msg_control = control;
> - msg.msg_controllen = sizeof control;
> -
> - do {
> - len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
> - } while (len < 0 && errno == EINTR);
> -
> - if (len != sizeof ret ||
> - ret < 0)
> - return -1;
> -
> - cmsg = CMSG_FIRSTHDR(&msg);
> - if (!cmsg ||
> - cmsg->cmsg_level != SOL_SOCKET ||
> - cmsg->cmsg_type != SCM_RIGHTS) {
> - fprintf(stderr, "invalid control message\n");
> - return -1;
> - }
> -
> - data = (union cmsg_data *) CMSG_DATA(cmsg);
> - if (data->fd == -1) {
> - fprintf(stderr, "missing drm fd in socket request\n");
> - return -1;
> - }
> -
> - return data->fd;
> + return launcher->iface->open(launcher, path, flags);
> }
>
> -void
> +WL_EXPORT void
> weston_launcher_close(struct weston_launcher *launcher, int fd)
> {
> - if (launcher->logind)
> - weston_logind_close(launcher->logind, fd);
> -
> - close(fd);
> -}
> -
> -void
> -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");
> -
> - if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
> - weston_log("failed to set KD_TEXT mode on tty: %m\n");
> -
> - /* We have to drop master before we switch the VT back in
> - * VT_AUTO, so we don't risk switching to a VT with another
> - * display server, that will then fail to set drm master. */
> - drmDropMaster(launcher->drm_fd);
> -
> - mode.mode = VT_AUTO;
> - if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
> - weston_log("could not reset vt handling\n");
> -}
> -
> -static int
> -weston_launcher_data(int fd, uint32_t mask, void *data)
> -{
> - struct weston_launcher *launcher = data;
> - int len, ret;
> -
> - if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
> - weston_log("launcher socket closed, exiting\n");
> - /* Normally the weston-launch will reset the tty, but
> - * in this case it died or something, so do it here so
> - * we don't end up with a stuck vt. */
> - weston_launcher_restore(launcher);
> - exit(-1);
> - }
> -
> - do {
> - len = recv(launcher->fd, &ret, sizeof ret, 0);
> - } while (len < 0 && errno == EINTR);
> -
> - switch (ret) {
> - case WESTON_LAUNCHER_ACTIVATE:
> - launcher->compositor->session_active = 1;
> - wl_signal_emit(&launcher->compositor->session_signal,
> - launcher->compositor);
> - break;
> - case WESTON_LAUNCHER_DEACTIVATE:
> - launcher->compositor->session_active = 0;
> - wl_signal_emit(&launcher->compositor->session_signal,
> - launcher->compositor);
> - break;
> - default:
> - weston_log("unexpected event from weston-launch\n");
> - break;
> - }
> -
> - return 1;
> -}
> -
> -static int
> -vt_handler(int signal_number, void *data)
> -{
> - struct weston_launcher *launcher = data;
> - struct weston_compositor *compositor = launcher->compositor;
> -
> - if (compositor->session_active) {
> - compositor->session_active = 0;
> - wl_signal_emit(&compositor->session_signal, compositor);
> - drmDropMaster(launcher->drm_fd);
> - ioctl(launcher->tty, VT_RELDISP, 1);
> - } else {
> - ioctl(launcher->tty, VT_RELDISP, VT_ACKACQ);
> - drmSetMaster(launcher->drm_fd);
> - compositor->session_active = 1;
> - wl_signal_emit(&compositor->session_signal, compositor);
> - }
> -
> - return 1;
> -}
> -
> -static int
> -setup_tty(struct weston_launcher *launcher, int tty)
> -{
> - struct wl_event_loop *loop;
> - struct vt_mode mode = { 0 };
> - struct stat buf;
> - char tty_device[32] ="<stdin>";
> - int ret, kd_mode;
> -
> - if (tty == 0) {
> - launcher->tty = dup(tty);
> - if (launcher->tty == -1) {
> - weston_log("couldn't dup stdin: %m\n");
> - return -1;
> - }
> - } else {
> - snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty);
> - launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC);
> - if (launcher->tty == -1) {
> - weston_log("couldn't open tty %s: %m\n", tty_device);
> - return -1;
> - }
> - }
> -
> - if (fstat(launcher->tty, &buf) == -1 ||
> - major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) {
> - weston_log("%s not a vt\n", tty_device);
> - weston_log("if running weston from ssh, "
> - "use --tty to specify a tty\n");
> - goto err_close;
> - }
> -
> - ret = ioctl(launcher->tty, KDGETMODE, &kd_mode);
> - if (ret) {
> - weston_log("failed to get VT mode: %m\n");
> - return -1;
> - }
> - if (kd_mode != KD_TEXT) {
> - weston_log("%s is already in graphics mode, "
> - "is another display server running?\n", tty_device);
> - goto err_close;
> - }
> -
> - ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev));
> - ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev));
> -
> - if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) {
> - weston_log("failed to read keyboard mode: %m\n");
> - goto err_close;
> - }
> -
> - if (ioctl(launcher->tty, KDSKBMUTE, 1) &&
> - ioctl(launcher->tty, KDSKBMODE, K_OFF)) {
> - weston_log("failed to set K_OFF keyboard mode: %m\n");
> - goto err_close;
> - }
> -
> - ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS);
> - if (ret) {
> - weston_log("failed to set KD_GRAPHICS mode on tty: %m\n");
> - goto err_close;
> - }
> -
> - /*
> - * SIGRTMIN is used as global VT-acquire+release signal. Note that
> - * SIGRT* must be tested on runtime, as their exact values are not
> - * known at compile-time. POSIX requires 32 of them to be available.
> - */
> - if (SIGRTMIN > SIGRTMAX) {
> - weston_log("not enough RT signals available: %u-%u\n",
> - SIGRTMIN, SIGRTMAX);
> - ret = -EINVAL;
> - goto err_close;
> - }
> -
> - mode.mode = VT_PROCESS;
> - mode.relsig = SIGRTMIN;
> - mode.acqsig = SIGRTMIN;
> - if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) {
> - weston_log("failed to take control of vt handling\n");
> - goto err_close;
> - }
> -
> - loop = wl_display_get_event_loop(launcher->compositor->wl_display);
> - launcher->vt_source =
> - wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher);
> - if (!launcher->vt_source)
> - goto err_close;
> -
> - return 0;
> -
> - err_close:
> - close(launcher->tty);
> - return -1;
> + launcher->iface->close(launcher, fd);
> }
>
> -int
> +WL_EXPORT 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);
> + return launcher->iface->activate_vt(launcher, vt);
> }
>
> -struct weston_launcher *
> -weston_launcher_connect(struct weston_compositor *compositor, int tty,
> - const char *seat_id, bool sync_drm)
> -{
> - 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");
> - if (launcher->fd != -1) {
> - launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
> - /* We don't get a chance to read out the original kb
> - * mode for the tty, so just hard code K_UNICODE here
> - * in case we have to clean if weston-launch dies. */
> - launcher->kb_mode = K_UNICODE;
> -
> - loop = wl_display_get_event_loop(compositor->wl_display);
> - launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
> - WL_EVENT_READABLE,
> - weston_launcher_data,
> - launcher);
> - if (launcher->source == NULL) {
> - free(launcher);
> - return NULL;
> - }
> - } else {
> - r = weston_logind_connect(&launcher->logind, compositor,
> - seat_id, tty, sync_drm);
> - 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;
> -}
> -
> -void
> -weston_launcher_destroy(struct weston_launcher *launcher)
> +WL_EXPORT void
> +weston_launcher_restore(struct weston_launcher *launcher)
> {
> - if (launcher->logind) {
> - weston_logind_destroy(launcher->logind);
> - } else if (launcher->fd != -1) {
> - close(launcher->fd);
> - wl_event_source_remove(launcher->source);
> - } else {
> - weston_launcher_restore(launcher);
> - wl_event_source_remove(launcher->vt_source);
> - }
> -
> - if (launcher->tty >= 0)
> - close(launcher->tty);
> -
> - free(launcher);
> + launcher->iface->restore(launcher);
> }
> diff --git a/src/launcher-weston-launch.c b/src/launcher-weston-launch.c
> new file mode 100644
> index 0000000..09f671d
> --- /dev/null
> +++ b/src/launcher-weston-launch.c
> @@ -0,0 +1,302 @@
> +/*
> + * Copyright © 2012 Benjamin Franzke
> + * Copyright © 2013 Intel Corporation
> + *
> + * 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 <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <errno.h>
> +#include <signal.h>
> +#include <sys/socket.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/uio.h>
> +#include <sys/ioctl.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <linux/vt.h>
> +#include <linux/kd.h>
> +#include <linux/major.h>
> +
> +#include "compositor.h"
> +#include "weston-launch.h"
> +#include "launcher-impl.h"
> +
> +#define DRM_MAJOR 226
> +
> +#ifndef KDSKBMUTE
> +#define KDSKBMUTE 0x4B51
> +#endif
> +
> +#ifdef HAVE_LIBDRM
> +
> +#include <xf86drm.h>
> +
> +static inline int
> +is_drm_master(int drm_fd)
> +{
> + drm_magic_t magic;
> +
> + return drmGetMagic(drm_fd, &magic) == 0 &&
> + drmAuthMagic(drm_fd, magic) == 0;
> +}
> +
> +#else
> +
> +static inline int
> +drmDropMaster(int drm_fd)
> +{
> + return 0;
> +}
> +
> +static inline int
> +drmSetMaster(int drm_fd)
> +{
> + return 0;
> +}
> +
> +static inline int
> +is_drm_master(int drm_fd)
> +{
> + return 0;
> +}
> +
> +#endif
> +
> +
> +union cmsg_data { unsigned char b[4]; int fd; };
> +
> +struct launcher_weston_launch {
> + struct weston_launcher base;
> + struct weston_compositor *compositor;
> + struct wl_event_loop *loop;
> + int fd;
> + struct wl_event_source *source;
> +
> + int kb_mode, tty, drm_fd;
> + struct wl_event_source *vt_source;
> +};
> +
> +static int
> +launcher_weston_launch_open(struct weston_launcher *launcher_base,
> + const char *path, int flags)
> +{
> + struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
> + int n, ret;
> + struct msghdr msg;
> + struct cmsghdr *cmsg;
> + struct iovec iov;
> + union cmsg_data *data;
> + char control[CMSG_SPACE(sizeof data->fd)];
> + ssize_t len;
> + struct weston_launcher_open *message;
> +
> + n = sizeof(*message) + strlen(path) + 1;
> + message = malloc(n);
> + if (!message)
> + return -1;
> +
> + message->header.opcode = WESTON_LAUNCHER_OPEN;
> + message->flags = flags;
> + strcpy(message->path, path);
> +
> + do {
> + len = send(launcher->fd, message, n, 0);
> + } while (len < 0 && errno == EINTR);
> + free(message);
> +
> + memset(&msg, 0, sizeof msg);
> + iov.iov_base = &ret;
> + iov.iov_len = sizeof ret;
> + msg.msg_iov = &iov;
> + msg.msg_iovlen = 1;
> + msg.msg_control = control;
> + msg.msg_controllen = sizeof control;
> +
> + do {
> + len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
> + } while (len < 0 && errno == EINTR);
> +
> + if (len != sizeof ret ||
> + ret < 0)
> + return -1;
> +
> + cmsg = CMSG_FIRSTHDR(&msg);
> + if (!cmsg ||
> + cmsg->cmsg_level != SOL_SOCKET ||
> + cmsg->cmsg_type != SCM_RIGHTS) {
> + fprintf(stderr, "invalid control message\n");
> + return -1;
> + }
> +
> + data = (union cmsg_data *) CMSG_DATA(cmsg);
> + if (data->fd == -1) {
> + fprintf(stderr, "missing drm fd in socket request\n");
> + return -1;
> + }
> +
> + return data->fd;
> +}
> +
> +static void
> +launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
> +{
> + close(fd);
> +}
> +
> +static void
> +launcher_weston_launch_restore(struct weston_launcher *launcher_base)
> +{
> + struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
> + struct vt_mode mode = { 0 };
> +
> + if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
> + ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
> + weston_log("failed to restore kb mode: %m\n");
> +
> + if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
> + weston_log("failed to set KD_TEXT mode on tty: %m\n");
> +
> + /* We have to drop master before we switch the VT back in
> + * VT_AUTO, so we don't risk switching to a VT with another
> + * display server, that will then fail to set drm master. */
> + drmDropMaster(launcher->drm_fd);
> +
> + mode.mode = VT_AUTO;
> + if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
> + weston_log("could not reset vt handling\n");
> +}
> +
> +static int
> +launcher_weston_launch_data(int fd, uint32_t mask, void *data)
> +{
> + struct launcher_weston_launch *launcher = data;
> + int len, ret;
> +
> + if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
> + weston_log("launcher socket closed, exiting\n");
> + /* Normally the weston-launch will reset the tty, but
> + * in this case it died or something, so do it here so
> + * we don't end up with a stuck vt. */
> + launcher_weston_launch_restore(&launcher->base);
> + exit(-1);
> + }
> +
> + do {
> + len = recv(launcher->fd, &ret, sizeof ret, 0);
> + } while (len < 0 && errno == EINTR);
> +
> + switch (ret) {
> + case WESTON_LAUNCHER_ACTIVATE:
> + launcher->compositor->session_active = 1;
> + wl_signal_emit(&launcher->compositor->session_signal,
> + launcher->compositor);
> + break;
> + case WESTON_LAUNCHER_DEACTIVATE:
> + launcher->compositor->session_active = 0;
> + wl_signal_emit(&launcher->compositor->session_signal,
> + launcher->compositor);
> + break;
> + default:
> + weston_log("unexpected event from weston-launch\n");
> + break;
> + }
> +
> + return 1;
> +}
> +
> +static int
> +launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
> +{
> + struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
> + return ioctl(launcher->tty, VT_ACTIVATE, vt);
> +}
> +
> +static int
> +launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
> + int tty, const char *seat_id, bool sync_drm)
> +{
> + struct launcher_weston_launch *launcher;
> + struct wl_event_loop *loop;
> +
> + launcher = malloc(sizeof *launcher);
> + if (launcher == NULL)
> + return -ENOMEM;
> +
> + launcher->base.iface = &launcher_weston_launch_iface;
> + * (struct launcher_weston_launch **) out = launcher;
> + launcher->compositor = compositor;
> + launcher->drm_fd = -1;
> + launcher->fd = weston_environment_get_fd("WESTON_LAUNCH_SOCK");
> + if (launcher->fd != -1) {
> + launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
> + /* We don't get a chance to read out the original kb
> + * mode for the tty, so just hard code K_UNICODE here
> + * in case we have to clean if weston-launch dies. */
> + launcher->kb_mode = K_UNICODE;
> +
> + loop = wl_display_get_event_loop(compositor->wl_display);
> + launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
> + WL_EVENT_READABLE,
> + launcher_weston_launch_data,
> + launcher);
> + if (launcher->source == NULL) {
> + free(launcher);
> + return -ENOMEM;
> + }
> +
> + return 0;
> + } else {
> + return -1;
> + }
> +}
> +
> +static void
> +launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
> +{
> + struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
> +
> + if (launcher->fd != -1) {
> + close(launcher->fd);
> + wl_event_source_remove(launcher->source);
> + } else {
> + launcher_weston_launch_restore(&launcher->base);
> + wl_event_source_remove(launcher->vt_source);
> + }
> +
> + if (launcher->tty >= 0)
> + close(launcher->tty);
> +
> + free(launcher);
> +}
> +
> +struct launcher_interface launcher_weston_launch_iface = {
> + launcher_weston_launch_connect,
> + launcher_weston_launch_destroy,
> + launcher_weston_launch_open,
> + launcher_weston_launch_close,
> + launcher_weston_launch_activate_vt,
> + launcher_weston_launch_restore,
> +};
>
More information about the wayland-devel
mailing list