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