diff options
| -rw-r--r-- | common/terminal.c | 191 | ||||
| -rw-r--r-- | include/seat.h | 1 | ||||
| -rw-r--r-- | include/terminal.h | 13 | ||||
| -rw-r--r-- | seatd/seat.c | 105 | 
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;  	} | 
