aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/terminal.c191
-rw-r--r--include/seat.h1
-rw-r--r--include/terminal.h13
-rw-r--r--seatd/seat.c105
4 files changed, 128 insertions, 182 deletions
diff --git a/common/terminal.c b/common/terminal.c
index bcd843d..da66143 100644
--- a/common/terminal.c
+++ b/common/terminal.c
@@ -1,27 +1,26 @@
-#include "string.h"
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
+#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#if defined(__linux__)
#include <linux/kd.h>
#include <linux/vt.h>
-#define TTY0 "/dev/tty0"
-#define TTYF "/dev/tty%d"
-#define K_ON K_UNICODE
-#define FRSIG 0
+#define TTYF "/dev/tty%d"
+#define K_ENABLE K_UNICODE
+#define K_DISABLE K_OFF
+#define FRSIG 0
#elif defined(__FreeBSD__)
#include <sys/consio.h>
#include <sys/kbio.h>
-#define TTY0 "/dev/ttyv0"
-#define TTYF "/dev/ttyv%d"
-#define K_ON K_XLATE
-#define K_OFF K_CODE
-#define FRSIG SIGIO
+#define TTYF "/dev/ttyv%d"
+#define K_ENABLE K_XLATE
+#define K_DISABLE K_CODE
+#define FRSIG SIGIO
#else
#error Unsupported platform
#endif
@@ -31,13 +30,21 @@
#define TTYPATHLEN 64
-int terminal_current_vt(void) {
- int fd = open(TTY0, O_RDWR | O_NOCTTY);
+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);
if (fd == -1) {
- log_errorf("could not open tty0: %s", strerror(errno));
+ log_errorf("could not open target tty: %s", strerror(errno));
return -1;
}
+ return fd;
+}
+int terminal_current_vt(int fd) {
#if defined(__linux__)
struct vt_stat st;
int res = ioctl(fd, VT_GETSTATE, &st);
@@ -61,173 +68,57 @@ int terminal_current_vt(void) {
#endif
}
-int terminal_setup(int vt) {
- log_debugf("setting up vt %d", vt);
- if (vt == -1) {
- vt = 0;
- }
- 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);
- if (fd == -1) {
- log_errorf("could not open target tty: %s", strerror(errno));
- return -1;
- }
-
- static struct vt_mode mode = {
- .mode = VT_PROCESS,
+int terminal_set_process_switching(int fd, bool enable) {
+ log_debug("setting process switching");
+ struct vt_mode mode = {
+ .mode = enable ? VT_PROCESS : VT_AUTO,
.waitv = 0,
- .relsig = SIGUSR1,
- .acqsig = SIGUSR2,
+ .relsig = enable ? SIGUSR1 : 0,
+ .acqsig = enable ? SIGUSR2 : 0,
.frsig = FRSIG,
};
- 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, TTYF, 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_ON) == -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 = FRSIG,
- };
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) {
+int terminal_switch_vt(int fd, int vt) {
log_debugf("switching to vt %d", vt);
- int fd = open(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 = FRSIG,
- };
-
- 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) {
+int terminal_ack_switch(int fd) {
log_debug("acking vt switch");
- int fd = open(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) {
+ if (ioctl(fd, VT_RELDISP, VT_ACKACQ) == -1) {
log_errorf("could not ack VT switch: %s", strerror(errno));
+ return -1;
}
- return res;
+ return 0;
}
-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, TTYF, 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_ON : K_OFF);
- close(fd);
- if (res == -1) {
+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) {
log_errorf("could not set KD keyboard mode: %s", strerror(errno));
+ return -1;
}
- return res;
+ return 0;
}
-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, TTYF, 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) {
+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) {
log_errorf("could not set KD graphics mode: %s", strerror(errno));
+ return -1;
}
- return res;
+ return 0;
}
diff --git a/include/seat.h b/include/seat.h
index e0d3533..5a6c273 100644
--- a/include/seat.h
+++ b/include/seat.h
@@ -32,6 +32,7 @@ struct seat {
bool vt_bound;
bool vt_pending_ack;
int next_vt;
+ int curttyfd;
};
struct seat *seat_create(const char *name, bool vt_bound);
diff --git a/include/terminal.h b/include/terminal.h
index c2a49ff..208d6b2 100644
--- a/include/terminal.h
+++ b/include/terminal.h
@@ -3,12 +3,15 @@
#include <stdbool.h>
+int terminal_open(int vt);
+
+int terminal_set_process_switching(int fd, bool enable);
int terminal_setup(int vt);
int terminal_teardown(int vt);
-int terminal_current_vt(void);
-int terminal_switch_vt(int vt);
-int terminal_ack_switch(void);
-int terminal_set_keyboard(int vt, bool enable);
-int terminal_set_graphics(int vt, bool enable);
+int terminal_current_vt(int fd);
+int terminal_switch_vt(int fd, int vt);
+int terminal_ack_switch(int fd);
+int terminal_set_keyboard(int fd, bool enable);
+int terminal_set_graphics(int fd, bool enable);
#endif
diff --git a/seatd/seat.c b/seatd/seat.c
index e876ccf..f9756dc 100644
--- a/seatd/seat.c
+++ b/seatd/seat.c
@@ -25,13 +25,12 @@ struct seat *seat_create(const char *seat_name, bool vt_bound) {
}
list_init(&seat->clients);
seat->vt_bound = vt_bound;
-
+ seat->curttyfd = -1;
seat->seat_name = strdup(seat_name);
if (seat->seat_name == NULL) {
free(seat);
return NULL;
}
-
log_debugf("created seat '%s' (vt_bound: %d)", seat_name, vt_bound);
return seat;
}
@@ -44,6 +43,7 @@ void seat_destroy(struct seat *seat) {
assert(client->seat);
client_kill(client);
}
+ assert(seat->curttyfd == -1);
free(seat->seat_name);
free(seat);
@@ -331,7 +331,18 @@ int seat_open_client(struct seat *seat, struct client *client) {
assert(client);
if (seat->vt_bound && client->seat_vt == 0) {
- client->seat_vt = terminal_current_vt();
+ int tty0fd = terminal_open(0);
+ if (tty0fd == -1) {
+ log_errorf("unable to open tty0: %s", strerror(errno));
+ return -1;
+ }
+ client->seat_vt = terminal_current_vt(tty0fd);
+ close(tty0fd);
+ if (client->seat_vt == -1) {
+ log_errorf("unable to get current VT for client: %s", strerror(errno));
+ client->seat_vt = 0;
+ return -1;
+ }
}
if (seat->active_client != NULL) {
@@ -341,8 +352,16 @@ int seat_open_client(struct seat *seat, struct client *client) {
}
if (seat->vt_bound) {
- terminal_setup(client->seat_vt);
- terminal_set_keyboard(client->seat_vt, false);
+ int ttyfd = terminal_open(client->seat_vt);
+ if (ttyfd == -1) {
+ log_errorf("unable to open tty for vt %d: %s", client->seat_vt,
+ strerror(errno));
+ return -1;
+ }
+ terminal_set_process_switching(ttyfd, true);
+ terminal_set_keyboard(ttyfd, false);
+ terminal_set_graphics(ttyfd, true);
+ seat->curttyfd = ttyfd;
}
for (size_t idx = 0; idx < client->devices.length; idx++) {
@@ -387,17 +406,19 @@ int seat_close_client(struct seat *seat, struct client *client) {
log_debugf("deactivated %zd devices", client->devices.length);
- int vt = seat->active_client->seat_vt;
seat->active_client = NULL;
- if (seat->vt_bound) {
- if (seat->vt_pending_ack) {
- log_debug("acking pending VT switch");
- seat->vt_pending_ack = false;
- terminal_teardown(vt);
- terminal_ack_switch();
- return 0;
- }
+ if (seat->vt_bound && seat->vt_pending_ack) {
+ log_debug("acking pending VT switch");
+ seat->vt_pending_ack = false;
+ assert(seat->curttyfd != -1);
+ terminal_set_process_switching(seat->curttyfd, true);
+ terminal_set_keyboard(seat->curttyfd, true);
+ terminal_set_graphics(seat->curttyfd, false);
+ terminal_ack_switch(seat->curttyfd);
+ close(seat->curttyfd);
+ seat->curttyfd = -1;
+ return 0;
}
seat_activate(seat);
@@ -457,17 +478,31 @@ int seat_activate(struct seat *seat) {
return 0;
}
- // If we're asked to do a simple VT switch, do that
- if (seat->vt_bound && seat->next_vt > 0) {
- log_info("executing VT switch");
- terminal_switch_vt(seat->next_vt);
- seat->next_vt = 0;
- return 0;
- }
-
int vt = -1;
if (seat->vt_bound) {
- vt = terminal_current_vt();
+ int ttyfd = terminal_open(0);
+ if (ttyfd == -1) {
+ log_errorf("unable to open tty0: %s", strerror(errno));
+ return -1;
+ }
+
+ // If we're asked to do a simple VT switch, do that
+ if (seat->next_vt > 0) {
+ log_info("executing VT switch");
+ terminal_switch_vt(ttyfd, seat->next_vt);
+ seat->next_vt = 0;
+ close(ttyfd);
+ return 0;
+ }
+
+ // We'll need the VT below
+ vt = terminal_current_vt(ttyfd);
+ if (vt == -1) {
+ log_errorf("unable to get vt: %s", strerror(errno));
+ close(ttyfd);
+ return -1;
+ }
+ close(ttyfd);
}
// Try to pick a client for activation
@@ -492,15 +527,25 @@ int seat_activate(struct seat *seat) {
if (next_client == NULL) {
// No suitable client found
log_info("no client suitable for activation");
- if (seat->vt_bound) {
- terminal_teardown(vt);
+ if (seat->vt_bound && seat->curttyfd != -1) {
+ terminal_set_process_switching(seat->curttyfd, false);
+ terminal_set_keyboard(seat->curttyfd, true);
+ terminal_set_graphics(seat->curttyfd, false);
+ close(seat->curttyfd);
+ seat->curttyfd = -1;
}
return -1;
}
log_info("activating next client");
if (seat->vt_bound && next_client->seat_vt != vt) {
- terminal_switch_vt(next_client->seat_vt);
+ int ttyfd = terminal_open(0);
+ if (ttyfd == -1) {
+ log_errorf("unable to open tty0: %s", strerror(errno));
+ return -1;
+ }
+ terminal_switch_vt(ttyfd, next_client->seat_vt);
+ close(ttyfd);
}
return seat_open_client(seat, next_client);
@@ -511,7 +556,13 @@ int seat_prepare_vt_switch(struct seat *seat) {
if (seat->active_client == NULL) {
log_info("no active client, performing switch immediately");
- terminal_ack_switch();
+ int tty0fd = terminal_open(0);
+ if (tty0fd == -1) {
+ log_errorf("unable to open tty0: %s", strerror(errno));
+ return -1;
+ }
+ terminal_ack_switch(tty0fd);
+ close(tty0fd);
return 0;
}