[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