diff options
author | Kenny Levinsen <kl@kl.wtf> | 2020-07-31 00:22:18 +0200 |
---|---|---|
committer | Kenny Levinsen <kl@kl.wtf> | 2020-07-31 00:22:18 +0200 |
commit | 61716a2c77dfde9addf6b41a6d72d26a8584150e (patch) | |
tree | 537cd84661955497bdb304f88896e36896df4e5f /common/terminal.c | |
parent | f85434de666f10da0cbcaccdbb7d88917c5fa887 (diff) |
Initial implementation of seatd and libseat
Diffstat (limited to 'common/terminal.c')
-rw-r--r-- | common/terminal.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/common/terminal.c b/common/terminal.c new file mode 100644 index 0000000..c9ee758 --- /dev/null +++ b/common/terminal.c @@ -0,0 +1,202 @@ +#include "string.h" +#include <errno.h> +#include <fcntl.h> +#include <linux/kd.h> +#include <linux/vt.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include "log.h" +#include "terminal.h" + +#define TTYPATHLEN 64 + +int terminal_current_vt(void) { + struct vt_stat st; + int fd = open("/dev/tty0", O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not open tty0: %s", strerror(errno)); + return -1; + } + int res = ioctl(fd, VT_GETSTATE, &st); + close(fd); + if (res == -1) { + log_errorf("could not retrieve VT state: %s", strerror(errno)); + return -1; + } + return st.v_active; +} + +int terminal_setup(int vt) { + log_debugf("setting up vt %d", vt); + if (vt == -1) { + vt = 0; + } + char path[TTYPATHLEN]; + if (snprintf(path, TTYPATHLEN, "/dev/tty%d", vt) == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int fd = open(path, O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not open target tty: %s", strerror(errno)); + return -1; + } + + static struct vt_mode mode = { + .mode = VT_PROCESS, + .waitv = 0, + .relsig = SIGUSR1, + .acqsig = SIGUSR2, + .frsig = 0, + }; + + int res = ioctl(fd, VT_SETMODE, &mode); + close(fd); + if (res == -1) { + log_errorf("could not set VT mode: %s", strerror(errno)); + } + + return res; +} + +int terminal_teardown(int vt) { + log_debugf("tearing down vt %d", vt); + if (vt == -1) { + vt = 0; + } + char path[TTYPATHLEN]; + if (snprintf(path, TTYPATHLEN, "/dev/tty%d", vt) == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int fd = open(path, O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not open target tty: %s", strerror(errno)); + return -1; + } + if (ioctl(fd, KDSETMODE, KD_TEXT) == -1) { + log_errorf("could not set KD graphics mode: %s", strerror(errno)); + close(fd); + return -1; + } + if (ioctl(fd, KDSKBMODE, K_UNICODE) == -1) { + log_errorf("could not set KD keyboard mode: %s", strerror(errno)); + close(fd); + return -1; + } + + static struct vt_mode mode = { + .mode = VT_PROCESS, + .waitv = 0, + .relsig = SIGUSR1, + .acqsig = SIGUSR2, + .frsig = 0, + }; + if (ioctl(fd, VT_SETMODE, &mode) == -1) { + log_errorf("could not set VT mode: %s", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +int terminal_switch_vt(int vt) { + log_debugf("switching to vt %d", vt); + int fd = open("/dev/tty0", O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not open tty0: %s", strerror(errno)); + return -1; + } + + static struct vt_mode mode = { + .mode = VT_PROCESS, + .waitv = 0, + .relsig = SIGUSR1, + .acqsig = SIGUSR2, + .frsig = 0, + }; + + if (ioctl(fd, VT_SETMODE, &mode) == -1) { + log_errorf("could not set VT mode: %s", strerror(errno)); + close(fd); + return -1; + } + + if (ioctl(fd, VT_ACTIVATE, vt) == -1) { + log_errorf("could not activate VT: %s", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +int terminal_ack_switch(void) { + log_debug("acking vt switch"); + int fd = open("/dev/tty0", O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not open tty0: %s", strerror(errno)); + return -1; + } + + int res = ioctl(fd, VT_RELDISP, VT_ACKACQ); + close(fd); + if (res == -1) { + log_errorf("could not ack VT switch: %s", strerror(errno)); + } + + return res; +} + +int terminal_set_keyboard(int vt, bool enable) { + log_debugf("setting KD keyboard state to %d on vt %d", enable, vt); + if (vt == -1) { + vt = 0; + } + char path[TTYPATHLEN]; + if (snprintf(path, TTYPATHLEN, "/dev/tty%d", vt) == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int fd = open(path, O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int res = ioctl(fd, KDSKBMODE, enable ? K_UNICODE : K_OFF); + close(fd); + if (res == -1) { + log_errorf("could not set KD keyboard mode: %s", strerror(errno)); + } + return res; +} + +int terminal_set_graphics(int vt, bool enable) { + log_debugf("setting KD graphics state to %d on vt %d", enable, vt); + if (vt == -1) { + vt = 0; + } + char path[TTYPATHLEN]; + if (snprintf(path, TTYPATHLEN, "/dev/tty%d", vt) == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int fd = open(path, O_RDWR | O_NOCTTY); + if (fd == -1) { + log_errorf("could not generate tty path: %s", strerror(errno)); + return -1; + } + int res = ioctl(fd, KDSETMODE, enable ? KD_GRAPHICS : KD_TEXT); + close(fd); + if (res == -1) { + log_errorf("could not set KD graphics mode: %s", strerror(errno)); + } + return res; +} |