aboutsummaryrefslogtreecommitdiffstats
path: root/vt.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2016-03-24 09:12:54 +0100
committerGerd Hoffmann <kraxel@redhat.com>2016-03-24 09:12:54 +0100
commit519d0b165c38854e9ece43907e1dffc1c659dbb4 (patch)
treebf22247eb2d6a02771b351df421ee647128b2446 /vt.c
parent4ab7eba10ce61c902ee8949d71359a4f9878ed36 (diff)
downloadfbida-519d0b165c38854e9ece43907e1dffc1c659dbb4.tar.gz
move console handling to vt.c
Diffstat (limited to 'vt.c')
-rw-r--r--vt.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/vt.c b/vt.c
new file mode 100644
index 0000000..75559fb
--- /dev/null
+++ b/vt.c
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#include <linux/kd.h>
+#include <linux/vt.h>
+
+#include "vt.h"
+
+/* -------------------------------------------------------------------- */
+
+#define CONSOLE_ACTIVE 0
+#define CONSOLE_REL_REQ 1
+#define CONSOLE_INACTIVE 2
+#define CONSOLE_ACQ_REQ 3
+
+int console_visible = 1;
+
+extern int debug;
+
+static int switch_last, tty;
+static int console_switch_state = CONSOLE_ACTIVE;
+static struct vt_mode vt_mode;
+static int orig_vt_no = 0;
+static void (*console_redraw)(void);
+
+static void console_switch_signal(int signal)
+{
+ if (signal == SIGUSR1) {
+ /* release */
+ console_switch_state = CONSOLE_REL_REQ;
+ if (debug)
+ write(2,"vt: SIGUSR1\n",12);
+ }
+ if (signal == SIGUSR2) {
+ /* acquisition */
+ console_switch_state = CONSOLE_ACQ_REQ;
+ if (debug)
+ write(2,"vt: SIGUSR2\n",12);
+ }
+}
+
+static void console_switch_release(void)
+{
+ ioctl(tty, VT_RELDISP, 1);
+ console_switch_state = CONSOLE_INACTIVE;
+ if (debug)
+ write(2,"vt: release\n",12);
+}
+
+static void console_switch_acquire(void)
+{
+ ioctl(tty, VT_RELDISP, VT_ACKACQ);
+ console_switch_state = CONSOLE_ACTIVE;
+ if (debug)
+ write(2,"vt: acquire\n",12);
+}
+
+int console_switch_init(int tty_fd, void (*redraw)(void))
+{
+ struct sigaction act,old;
+
+ tty = tty_fd;
+ console_redraw = redraw;
+
+ memset(&act,0,sizeof(act));
+ act.sa_handler = console_switch_signal;
+ sigemptyset(&act.sa_mask);
+ sigaction(SIGUSR1,&act,&old);
+ sigaction(SIGUSR2,&act,&old);
+
+ if (-1 == ioctl(tty, VT_GETMODE, &vt_mode)) {
+ perror("ioctl VT_GETMODE");
+ exit(1);
+ }
+ vt_mode.mode = VT_PROCESS;
+ vt_mode.waitv = 0;
+ vt_mode.relsig = SIGUSR1;
+ vt_mode.acqsig = SIGUSR2;
+
+ if (-1 == ioctl(tty, VT_SETMODE, &vt_mode)) {
+ perror("ioctl VT_SETMODE");
+ exit(1);
+ }
+ return 0;
+}
+
+int check_console_switch(void)
+{
+ if (switch_last == console_switch_state)
+ return 0;
+
+ switch (console_switch_state) {
+ case CONSOLE_REL_REQ:
+ console_switch_release();
+ case CONSOLE_INACTIVE:
+ console_visible = 0;
+ break;
+ case CONSOLE_ACQ_REQ:
+ console_switch_acquire();
+ case CONSOLE_ACTIVE:
+ console_visible = 1;
+ console_redraw();
+ break;
+ default:
+ break;
+ }
+ switch_last = console_switch_state;
+ return 1;
+}
+
+void console_set_vt(int vtno)
+{
+ struct vt_stat vts;
+ char vtname[12];
+
+ if (vtno < 0) {
+ if (-1 == ioctl(tty,VT_OPENQRY, &vtno) || vtno == -1) {
+ perror("ioctl VT_OPENQRY");
+ exit(1);
+ }
+ }
+
+ vtno &= 0xff;
+ sprintf(vtname, "/dev/tty%d", vtno);
+ chown(vtname, getuid(), getgid());
+ if (-1 == access(vtname, R_OK | W_OK)) {
+ fprintf(stderr,"access %s: %s\n",vtname,strerror(errno));
+ exit(1);
+ }
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ perror("fork");
+ exit(1);
+ default:
+ exit(0);
+ }
+ close(tty);
+ close(0);
+ close(1);
+ close(2);
+ setsid();
+ open(vtname,O_RDWR);
+ dup(0);
+ dup(0);
+
+ if (-1 == ioctl(tty,VT_GETSTATE, &vts)) {
+ perror("ioctl VT_GETSTATE");
+ exit(1);
+ }
+ orig_vt_no = vts.v_active;
+ if (-1 == ioctl(tty,VT_ACTIVATE, vtno)) {
+ perror("ioctl VT_ACTIVATE");
+ exit(1);
+ }
+ if (-1 == ioctl(tty,VT_WAITACTIVE, vtno)) {
+ perror("ioctl VT_WAITACTIVE");
+ exit(1);
+ }
+}
+
+void console_restore_vt(void)
+{
+ if (!orig_vt_no)
+ return;
+
+ if (ioctl(tty, VT_ACTIVATE, orig_vt_no) < 0)
+ perror("ioctl VT_ACTIVATE");
+ if (ioctl(tty, VT_WAITACTIVE, orig_vt_no) < 0)
+ perror("ioctl VT_WAITACTIVE");
+}