From 95d303d2dccae7b7fcca7a5212ccf03bfdc0c6f7 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Mon, 3 Apr 2023 13:20:05 -0300 Subject: vt-switch Signed-off-by: Anna (navi) Figueiredo Gomes --- libseat/backend/noop.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 4 deletions(-) diff --git a/libseat/backend/noop.c b/libseat/backend/noop.c index 18f26c3..3b63616 100644 --- a/libseat/backend/noop.c +++ b/libseat/backend/noop.c @@ -5,11 +5,13 @@ #include #include #include +#include #include #include #include "backend.h" #include "log.h" +#include "terminal.h" struct backend_noop { struct libseat base; @@ -18,10 +20,29 @@ struct backend_noop { bool initial_setup; int sockets[2]; + }; +static int vt; +bool should_reenable; + extern const struct seat_impl noop_impl; +static int vt_toggle(int vt, bool enable) { + int ttyfd = terminal_open(vt); + if (ttyfd == -1) { + log_errorf("Could not open terminal to switch to VT %d: %s", vt, strerror(errno)); + return -1; + } + + terminal_set_process_switching(ttyfd, true); + terminal_set_keyboard(ttyfd, !enable); + terminal_set_graphics(ttyfd, enable); + + close(ttyfd); + return 0; +} + static struct backend_noop *backend_noop_from_libseat_backend(struct libseat *base) { assert(base->impl == &noop_impl); return (struct backend_noop *)base; @@ -33,6 +54,35 @@ static void destroy(struct backend_noop *backend) { free(backend); } +static void vt_acq(int signal) { + (void)signal; + int ttyfd = terminal_open(vt); + if (ttyfd == -1) { + log_errorf("Could not open terminal to switch to VT %d: %s", vt, strerror(errno)); + return; + } + + terminal_ack_acquire(ttyfd); + + close(ttyfd); +} + +static void vt_rel(int signal) { + (void)signal; + int ttyfd = terminal_open(vt); + if (ttyfd == -1) { + log_errorf("Could not open terminal to switch to VT %d: %s", + vt, strerror(errno)); + return; + } + + terminal_ack_release(ttyfd); + + vt_toggle(vt, false); + + close(ttyfd); +} + static int close_seat(struct libseat *base) { struct backend_noop *backend = backend_noop_from_libseat_backend(base); destroy(backend); @@ -69,10 +119,21 @@ static int close_device(struct libseat *base, int device_id) { } static int switch_session(struct libseat *base, int s) { - (void)base; - (void)s; - log_errorf("No-op backend cannot switch to session %d", s); - return -1; + struct backend_noop *backend = backend_noop_from_libseat_backend(base); + + int ttyfd = terminal_open(vt); + if (ttyfd == -1) { + log_errorf("Could not open terminal to switch to VT %d: %s", vt, strerror(errno)); + return -1; + } + + backend->seat_listener->disable_seat(&backend->base, backend->seat_listener_data); + + int ret = terminal_switch_vt(ttyfd, s); + should_reenable = false; + + close(ttyfd); + return ret; } static int get_fd(struct libseat *base) { @@ -80,6 +141,10 @@ static int get_fd(struct libseat *base) { return backend->sockets[0]; } +static void noop(int signal) { + log_debugf("Handling sig %d", signal); +} + static int dispatch_background(struct libseat *base, int timeout) { struct backend_noop *backend = backend_noop_from_libseat_backend(base); @@ -88,6 +153,12 @@ static int dispatch_background(struct libseat *base, int timeout) { backend->seat_listener->enable_seat(&backend->base, backend->seat_listener_data); } + if (should_reenable) { + backend->seat_listener->enable_seat(&backend->base, backend->seat_listener_data); + vt_toggle(vt, true); + should_reenable = false; + } + struct pollfd fd = { .fd = backend->sockets[0], .events = POLLIN, @@ -115,10 +186,38 @@ static struct libseat *noop_open_seat(const struct libseat_seat_listener *listen return NULL; } + int _vt; + const char *vt_env = getenv("LIBSEAT_VT"); + if (!vt_env || (_vt = atoi(vt_env)) == 0) { + log_error("LIBSEAT_VT must be set to the current VT for the noop backend"); + free(backend); + return NULL; + } + + vt = _vt; + + vt_toggle(vt, true); + + { + struct sigaction sa; + sa.sa_handler = vt_rel; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGUSR1, &sa, NULL); + } + { + struct sigaction sa; + sa.sa_handler = vt_acq; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGUSR2, &sa, NULL); + } + backend->initial_setup = true; backend->seat_listener = listener; backend->seat_listener_data = data; backend->base.impl = &noop_impl; + should_reenable = false; return &backend->base; } -- cgit v1.2.3