aboutsummaryrefslogtreecommitdiff
path: root/session/direct.c
diff options
context:
space:
mode:
Diffstat (limited to 'session/direct.c')
-rw-r--r--session/direct.c244
1 files changed, 0 insertions, 244 deletions
diff --git a/session/direct.c b/session/direct.c
deleted file mode 100644
index 1247663b..00000000
--- a/session/direct.c
+++ /dev/null
@@ -1,244 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <linux/kd.h>
-#include <linux/major.h>
-#include <linux/input.h>
-#include <linux/vt.h>
-#include <wayland-server.h>
-#include <wlr/session/interface.h>
-#include <wlr/util/log.h>
-#include "session/direct-ipc.h"
-
-enum { DRM_MAJOR = 226 };
-
-const struct session_impl session_direct;
-
-struct direct_session {
- struct wlr_session base;
- int tty_fd;
- int old_kbmode;
- int sock;
- pid_t child;
-
- struct wl_event_source *vt_source;
-};
-
-static int direct_session_open(struct wlr_session *base, const char *path) {
- struct direct_session *session = wl_container_of(base, session, base);
-
- int fd = direct_ipc_open(session->sock, path);
- if (fd < 0) {
- wlr_log(L_ERROR, "Failed to open %s: %s%s", path, strerror(-fd),
- fd == -EINVAL ? "; is another display server running?" : "");
- return fd;
- }
-
- struct stat st;
- if (fstat(fd, &st) < 0) {
- close(fd);
- return -errno;
- }
-
- if (major(st.st_rdev) == DRM_MAJOR) {
- session->base.drm_fd = fd;
- }
-
- return fd;
-}
-
-static void direct_session_close(struct wlr_session *base, int fd) {
- struct direct_session *session = wl_container_of(base, session, base);
-
- struct stat st;
- if (fstat(fd, &st) < 0) {
- wlr_log_errno(L_ERROR, "Stat failed");
- close(fd);
- return;
- }
-
- if (major(st.st_rdev) == DRM_MAJOR) {
- direct_ipc_dropmaster(session->sock, session->base.drm_fd);
- session->base.drm_fd = -1;
- } else if (major(st.st_rdev) == INPUT_MAJOR) {
- ioctl(fd, EVIOCREVOKE, 0);
- }
-
- close(fd);
-}
-
-static bool direct_change_vt(struct wlr_session *base, unsigned vt) {
- struct direct_session *session = wl_container_of(base, session, base);
- return ioctl(session->tty_fd, VT_ACTIVATE, (int)vt) == 0;
-}
-
-static void direct_session_finish(struct wlr_session *base) {
- struct direct_session *session = wl_container_of(base, session, base);
- struct vt_mode mode = {
- .mode = VT_AUTO,
- };
-
- errno = 0;
-
- ioctl(session->tty_fd, KDSKBMODE, session->old_kbmode);
- ioctl(session->tty_fd, KDSETMODE, KD_TEXT);
- ioctl(session->tty_fd, VT_SETMODE, &mode);
-
- if (errno) {
- wlr_log(L_ERROR, "Failed to restore tty");
- }
-
- direct_ipc_finish(session->sock, session->child);
- close(session->sock);
-
- wl_event_source_remove(session->vt_source);
- close(session->tty_fd);
- free(session);
-}
-
-static int vt_handler(int signo, void *data) {
- struct direct_session *session = data;
-
- if (session->base.active) {
- session->base.active = false;
- wl_signal_emit(&session->base.session_signal, session);
- direct_ipc_dropmaster(session->sock, session->base.drm_fd);
- ioctl(session->tty_fd, VT_RELDISP, 1);
- } else {
- ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ);
- direct_ipc_setmaster(session->sock, session->base.drm_fd);
- session->base.active = true;
- wl_signal_emit(&session->base.session_signal, session);
- }
-
- return 1;
-}
-
-static bool setup_tty(struct direct_session *session, struct wl_display *display) {
- int fd = dup(STDIN_FILENO);
- if (fd == -1) {
- wlr_log_errno(L_ERROR, "Cannot open tty");
- return false;
- }
-
- struct stat st;
- if (fstat(fd, &st) == -1 || major(st.st_rdev) != TTY_MAJOR || minor(st.st_rdev) == 0) {
- wlr_log(L_ERROR, "Not running from a virtual terminal");
- goto error;
- }
-
- int tty = minor(st.st_rdev);
- int ret, kd_mode, old_kbmode;
-
- ret = ioctl(fd, KDGETMODE, &kd_mode);
- if (ret) {
- wlr_log_errno(L_ERROR, "Failed to get tty mode");
- goto error;
- }
-
- if (kd_mode != KD_TEXT) {
- wlr_log(L_ERROR,
- "tty already in graphics mode; is another display server running?");
- goto error;
- }
-
- ioctl(fd, VT_ACTIVATE, tty);
- ioctl(fd, VT_WAITACTIVE, tty);
-
- if (ioctl(fd, KDGKBMODE, &old_kbmode)) {
- wlr_log_errno(L_ERROR, "Failed to read keyboard mode");
- goto error;
- }
-
- if (ioctl(fd, KDSKBMODE, K_OFF)) {
- wlr_log_errno(L_ERROR, "Failed to set keyboard mode");
- goto error;
- }
-
- if (ioctl(fd, KDSETMODE, KD_GRAPHICS)) {
- wlr_log_errno(L_ERROR, "Failed to set graphics mode on tty");
- goto error;
- }
-
- struct vt_mode mode = {
- .mode = VT_PROCESS,
- .relsig = SIGUSR1,
- .acqsig = SIGUSR1,
- };
-
- if (ioctl(fd, VT_SETMODE, &mode) < 0) {
- wlr_log(L_ERROR, "Failed to take control of tty");
- goto error;
- }
-
- struct wl_event_loop *loop = wl_display_get_event_loop(display);
- session->vt_source = wl_event_loop_add_signal(loop, SIGUSR1,
- vt_handler, session);
- if (!session->vt_source) {
- goto error;
- }
-
- session->base.vtnr = tty;
- session->tty_fd = fd;
- session->old_kbmode = old_kbmode;
-
- return true;
-
-error:
- close(fd);
- return false;
-}
-
-static struct wlr_session *direct_session_start(struct wl_display *disp) {
- struct direct_session *session = calloc(1, sizeof(*session));
- if (!session) {
- wlr_log_errno(L_ERROR, "Allocation failed");
- return NULL;
- }
-
- session->sock = direct_ipc_start(&session->child);
- if (session->sock == -1) {
- goto error_session;
- }
-
- if (!setup_tty(session, disp)) {
- goto error_ipc;
- }
-
- // XXX: Is it okay to trust the environment like this?
- const char *seat = getenv("XDG_SEAT");
- if (!seat) {
- seat = "seat0";
- }
-
- wlr_log(L_INFO, "Successfully loaded direct session");
-
- snprintf(session->base.seat, sizeof(session->base.seat), "%s", seat);
- session->base.drm_fd = -1;
- session->base.impl = &session_direct;
- session->base.active = true;
- wl_signal_init(&session->base.session_signal);
- return &session->base;
-
-error_ipc:
- direct_ipc_finish(session->sock, session->child);
- close(session->sock);
-error_session:
- free(session);
- return NULL;
-}
-
-const struct session_impl session_direct = {
- .start = direct_session_start,
- .finish = direct_session_finish,
- .open = direct_session_open,
- .close = direct_session_close,
- .change_vt = direct_change_vt,
-};