aboutsummaryrefslogtreecommitdiff
path: root/seatd/seat.c
diff options
context:
space:
mode:
authorKenny Levinsen <kl@kl.wtf>2020-08-02 20:21:19 +0200
committerKenny Levinsen <kl@kl.wtf>2020-08-02 21:46:10 +0200
commitb751481e5c0bed1b81b7c769923e772e9fd84e9d (patch)
treea08c88eb9b3755afb9b9ba70535ef98944de9301 /seatd/seat.c
parentb731b18e0a086e65aa25ed2a5e53488076f5ad37 (diff)
seat: Open/close tty on activation/deactivation
The VT and KD ioctl's are picky about the tty fd used. In order to satisfy these, and to improve state cleanup, we now only and store the current tty when opening a client, and use this fd to perform teardown later. The presence of the fd is also used to signal that teardown is needed.
Diffstat (limited to 'seatd/seat.c')
-rw-r--r--seatd/seat.c105
1 files changed, 78 insertions, 27 deletions
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;
}