xref: /kvmtool/term.c (revision 629ad9d3b8a1e9cb447bac41e7372145f1e8b3fc)
1b4405289SAsias He #include <poll.h>
2b4405289SAsias He #include <stdbool.h>
3b4405289SAsias He #include <termios.h>
4b4405289SAsias He #include <stdio.h>
5b4405289SAsias He #include <unistd.h>
6b4405289SAsias He #include <sys/uio.h>
7f2a0b6a7SAnton Vorontsov #include <signal.h>
8b4405289SAsias He 
9b4405289SAsias He #include "kvm/read-write.h"
10b4405289SAsias He #include "kvm/term.h"
11b4405289SAsias He #include "kvm/util.h"
125358b0e6SSasha Levin #include "kvm/kvm.h"
13*629ad9d3SSasha Levin #include "kvm/kvm-cpu.h"
14b4405289SAsias He 
155358b0e6SSasha Levin extern struct kvm *kvm;
16b4405289SAsias He static struct termios	orig_term;
17b4405289SAsias He 
1816588013SAsias He int term_escape_char	= 0x01; /* ctrl-a is used for escape */
1916588013SAsias He bool term_got_escape	= false;
2016588013SAsias He 
219aa4a0ebSAsias He int active_console;
22b4405289SAsias He 
23b4405289SAsias He int term_getc(int who)
24b4405289SAsias He {
25b4405289SAsias He 	int c;
26b4405289SAsias He 
27b4405289SAsias He 	if (who != active_console)
28b4405289SAsias He 		return -1;
29b4405289SAsias He 
30b4405289SAsias He 	if (read_in_full(STDIN_FILENO, &c, 1) < 0)
31b4405289SAsias He 		return -1;
3216588013SAsias He 
3316588013SAsias He 	c &= 0xff;
3416588013SAsias He 
3516588013SAsias He 	if (term_got_escape) {
3616588013SAsias He 		term_got_escape = false;
3716588013SAsias He 		if (c == 'x') {
38*629ad9d3SSasha Levin 			kvm_cpu__reboot();
395358b0e6SSasha Levin 			kvm__delete(kvm);
4016588013SAsias He 			printf("\n  # KVM session terminated.\n");
4116588013SAsias He 			exit(1);
4216588013SAsias He 		}
4316588013SAsias He 		if (c == term_escape_char)
4416588013SAsias He 			return c;
4516588013SAsias He 	}
4616588013SAsias He 
4716588013SAsias He 	if (c == term_escape_char) {
4816588013SAsias He 		term_got_escape = true;
4916588013SAsias He 		return -1;
5016588013SAsias He 	}
5116588013SAsias He 
52b4405289SAsias He 	return c;
53b4405289SAsias He }
54b4405289SAsias He 
55b4405289SAsias He int term_putc(int who, char *addr, int cnt)
56b4405289SAsias He {
57b4405289SAsias He 	if (who != active_console)
58b4405289SAsias He 		return -1;
59b4405289SAsias He 
600ea58e5bSPekka Enberg 	while (cnt--)
61b4405289SAsias He 		fprintf(stdout, "%c", *addr++);
62b4405289SAsias He 
63b4405289SAsias He 	fflush(stdout);
64b4405289SAsias He 	return cnt;
65b4405289SAsias He }
66b4405289SAsias He 
67b4405289SAsias He int term_getc_iov(int who, struct iovec *iov, int iovcnt)
68b4405289SAsias He {
6916588013SAsias He 	int c;
70b4405289SAsias He 
7116588013SAsias He 	if (who != active_console)
7216588013SAsias He 		return 0;
7316588013SAsias He 
7416588013SAsias He 	c = term_getc(who);
7516588013SAsias He 
7616588013SAsias He 	if (c < 0)
7716588013SAsias He 		return 0;
7816588013SAsias He 
7916588013SAsias He 	*((int *)iov[0].iov_base)	= c;
8016588013SAsias He 
81fbf15b30SAsias He 	return sizeof(char);
82b4405289SAsias He }
83b4405289SAsias He 
84b4405289SAsias He int term_putc_iov(int who, struct iovec *iov, int iovcnt)
85b4405289SAsias He {
86b4405289SAsias He 	if (who != active_console)
8716588013SAsias He 		return 0;
88b4405289SAsias He 
89b4405289SAsias He 	return writev(STDOUT_FILENO, iov, iovcnt);
90b4405289SAsias He }
91b4405289SAsias He 
92b4405289SAsias He bool term_readable(int who)
93b4405289SAsias He {
94b4405289SAsias He 	struct pollfd pollfd = (struct pollfd) {
95b4405289SAsias He 		.fd	= STDIN_FILENO,
96b4405289SAsias He 		.events	= POLLIN,
97b4405289SAsias He 		.revents = 0,
98b4405289SAsias He 	};
99b4405289SAsias He 
100b4405289SAsias He 	if (who != active_console)
101b4405289SAsias He 		return false;
102b4405289SAsias He 
103b4405289SAsias He 	return poll(&pollfd, 1, 0) > 0;
104b4405289SAsias He }
105b4405289SAsias He 
106b4405289SAsias He static void term_cleanup(void)
107b4405289SAsias He {
108b4405289SAsias He 	tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
109b4405289SAsias He }
110b4405289SAsias He 
111f2a0b6a7SAnton Vorontsov static void term_sig_cleanup(int sig)
112f2a0b6a7SAnton Vorontsov {
113f2a0b6a7SAnton Vorontsov 	term_cleanup();
114f2a0b6a7SAnton Vorontsov 	signal(sig, SIG_DFL);
115f2a0b6a7SAnton Vorontsov 	raise(sig);
116f2a0b6a7SAnton Vorontsov }
117f2a0b6a7SAnton Vorontsov 
118b4405289SAsias He void term_init(void)
119b4405289SAsias He {
120b4405289SAsias He 	struct termios term;
121b4405289SAsias He 
122b4405289SAsias He 	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
123b4405289SAsias He 		die("unable to save initial standard input settings");
124b4405289SAsias He 
125b4405289SAsias He 	term = orig_term;
126b4405289SAsias He 	term.c_lflag &= ~(ICANON | ECHO | ISIG);
127b4405289SAsias He 	tcsetattr(STDIN_FILENO, TCSANOW, &term);
128b4405289SAsias He 
129f2a0b6a7SAnton Vorontsov 	signal(SIGTERM, term_sig_cleanup);
130b4405289SAsias He 	atexit(term_cleanup);
131b4405289SAsias He }
132