2020-07-31 00:22:18 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
2020-08-02 20:21:19 +02:00
|
|
|
#include <string.h>
|
2020-07-31 00:22:18 +02:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2020-08-01 00:18:50 +00:00
|
|
|
#if defined(__linux__)
|
|
|
|
#include <linux/kd.h>
|
|
|
|
#include <linux/vt.h>
|
2020-08-02 20:21:19 +02:00
|
|
|
#define TTYF "/dev/tty%d"
|
|
|
|
#define K_ENABLE K_UNICODE
|
|
|
|
#define K_DISABLE K_OFF
|
|
|
|
#define FRSIG 0
|
2020-08-01 00:18:50 +00:00
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
#include <sys/consio.h>
|
|
|
|
#include <sys/kbio.h>
|
2020-08-26 22:57:27 +00:00
|
|
|
#include <termios.h>
|
2020-08-02 20:21:19 +02:00
|
|
|
#define TTYF "/dev/ttyv%d"
|
|
|
|
#define K_ENABLE K_XLATE
|
2020-08-26 22:57:27 +00:00
|
|
|
#define K_DISABLE K_RAW
|
2020-08-02 20:21:19 +02:00
|
|
|
#define FRSIG SIGIO
|
2020-08-01 00:18:50 +00:00
|
|
|
#else
|
|
|
|
#error Unsupported platform
|
|
|
|
#endif
|
|
|
|
|
2020-07-31 00:22:18 +02:00
|
|
|
#include "log.h"
|
|
|
|
#include "terminal.h"
|
|
|
|
|
|
|
|
#define TTYPATHLEN 64
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_open(int vt) {
|
|
|
|
char path[TTYPATHLEN];
|
|
|
|
if (snprintf(path, TTYPATHLEN, TTYF, vt) == -1) {
|
|
|
|
log_errorf("could not generate tty path: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
int fd = open(path, O_RDWR | O_NOCTTY);
|
2020-07-31 00:22:18 +02:00
|
|
|
if (fd == -1) {
|
2020-08-02 20:21:19 +02:00
|
|
|
log_errorf("could not open target tty: %s", strerror(errno));
|
2020-07-31 00:22:18 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2020-08-02 20:21:19 +02:00
|
|
|
return fd;
|
|
|
|
}
|
2020-08-01 00:18:50 +00:00
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_current_vt(int fd) {
|
2020-08-01 00:18:50 +00:00
|
|
|
#if defined(__linux__)
|
|
|
|
struct vt_stat st;
|
2020-07-31 00:22:18 +02:00
|
|
|
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;
|
2020-08-01 00:18:50 +00:00
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
int vt;
|
|
|
|
int res = ioctl(fd, VT_GETACTIVE, &vt);
|
|
|
|
close(fd);
|
|
|
|
if (res == -1) {
|
|
|
|
log_errorf("could not retrieve VT state: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return vt;
|
|
|
|
#else
|
|
|
|
#error Unsupported platform
|
|
|
|
#endif
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_set_process_switching(int fd, bool enable) {
|
|
|
|
log_debug("setting process switching");
|
|
|
|
struct vt_mode mode = {
|
|
|
|
.mode = enable ? VT_PROCESS : VT_AUTO,
|
2020-07-31 00:22:18 +02:00
|
|
|
.waitv = 0,
|
2020-08-02 20:21:19 +02:00
|
|
|
.relsig = enable ? SIGUSR1 : 0,
|
|
|
|
.acqsig = enable ? SIGUSR2 : 0,
|
2020-08-01 00:18:50 +00:00
|
|
|
.frsig = FRSIG,
|
2020-07-31 00:22:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
if (ioctl(fd, VT_SETMODE, &mode) == -1) {
|
|
|
|
log_errorf("could not set VT mode: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_switch_vt(int fd, int vt) {
|
2020-07-31 00:22:18 +02:00
|
|
|
log_debugf("switching to vt %d", vt);
|
|
|
|
if (ioctl(fd, VT_ACTIVATE, vt) == -1) {
|
|
|
|
log_errorf("could not activate VT: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_ack_switch(int fd) {
|
2020-07-31 00:22:18 +02:00
|
|
|
log_debug("acking vt switch");
|
2020-08-02 20:21:19 +02:00
|
|
|
if (ioctl(fd, VT_RELDISP, VT_ACKACQ) == -1) {
|
2020-07-31 00:22:18 +02:00
|
|
|
log_errorf("could not ack VT switch: %s", strerror(errno));
|
2020-08-02 20:21:19 +02:00
|
|
|
return -1;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
return 0;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_set_keyboard(int fd, bool enable) {
|
|
|
|
log_debugf("setting KD keyboard state to %d", enable);
|
|
|
|
if (ioctl(fd, KDSKBMODE, enable ? K_ENABLE : K_DISABLE) == -1) {
|
2020-07-31 00:22:18 +02:00
|
|
|
log_errorf("could not set KD keyboard mode: %s", strerror(errno));
|
2020-08-02 20:21:19 +02:00
|
|
|
return -1;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
2020-08-26 22:57:27 +00:00
|
|
|
#if defined(__FreeBSD__)
|
|
|
|
struct termios tios;
|
|
|
|
if (tcgetattr(fd, &tios) == -1) {
|
|
|
|
log_errorf("could not set get terminal mode: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (enable) {
|
|
|
|
cfmakesane(&tios);
|
|
|
|
} else {
|
|
|
|
cfmakeraw(&tios);
|
|
|
|
}
|
|
|
|
if (tcsetattr(fd, TCSAFLUSH, &tios) == -1) {
|
|
|
|
log_errorf("could not set terminal mode: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
2020-08-02 20:21:19 +02:00
|
|
|
return 0;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
|
|
|
|
2020-08-02 20:21:19 +02:00
|
|
|
int terminal_set_graphics(int fd, bool enable) {
|
|
|
|
log_debugf("setting KD graphics state to %d", enable);
|
|
|
|
if (ioctl(fd, KDSETMODE, enable ? KD_GRAPHICS : KD_TEXT) == -1) {
|
2020-07-31 00:22:18 +02:00
|
|
|
log_errorf("could not set KD graphics mode: %s", strerror(errno));
|
2020-08-02 20:21:19 +02:00
|
|
|
return -1;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|
2020-08-02 20:21:19 +02:00
|
|
|
return 0;
|
2020-07-31 00:22:18 +02:00
|
|
|
}
|