From 72dea06d7952e3ce8dd8057f7106186da4fa2678 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" <jstpierre@mecheye.net> Date: Wed, 23 Sep 2015 10:46:47 -0700 Subject: [PATCH] launcher: Split out launcher implementations into three distinct ones 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. Reviewed-by: Derek Foreman <derekf@osg.samsung.com> update: Dropped redundant free() in weston_launcher_destroy() --- 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 | 440 +++-------------------------------- src/launcher-weston-launch.c | 302 ++++++++++++++++++++++++ 7 files changed, 795 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 79a442cdb..94a824be0 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 000000000..29d9c28be --- /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 000000000..742721bf0 --- /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 4fab9a475..c148b24ba 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 1bc4961b0..000000000 --- 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 dc02dff43..e1beef6bb 100644 --- a/src/launcher-util.c +++ b/src/launcher-util.c @@ -26,440 +26,66 @@ #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); } -#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; + launcher->iface->close(launcher, fd); } -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; -} - -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); -} - -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; + return launcher->iface->activate_vt(launcher, vt); } -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 000000000..09f671d01 --- /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, +}; -- GitLab