diff options
Diffstat (limited to 'session/direct.c')
-rw-r--r-- | session/direct.c | 244 |
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, -}; |