blob: 689d52dfefb673e284238f8148538cdf1a8c0f24 [file] [log] [blame]
#include <poll.h>
#include <stdbool.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/uio.h>
#include "kvm/read-write.h"
#include "kvm/term.h"
#include "kvm/util.h"
static struct termios orig_term;
int term_escape_char = 0x01; /* ctrl-a is used for escape */
bool term_got_escape = false;
int active_console;
int term_getc(int who)
{
int c;
if (who != active_console)
return -1;
if (read_in_full(STDIN_FILENO, &c, 1) < 0)
return -1;
c &= 0xff;
if (term_got_escape) {
term_got_escape = false;
if (c == 'x') {
printf("\n # KVM session terminated.\n");
exit(1);
}
if (c == term_escape_char)
return c;
}
if (c == term_escape_char) {
term_got_escape = true;
return -1;
}
return c;
}
int term_putc(int who, char *addr, int cnt)
{
if (who != active_console)
return -1;
while (cnt--)
fprintf(stdout, "%c", *addr++);
fflush(stdout);
return cnt;
}
int term_getc_iov(int who, struct iovec *iov, int iovcnt)
{
int c;
if (who != active_console)
return 0;
c = term_getc(who);
if (c < 0)
return 0;
*((int *)iov[0].iov_base) = c;
return sizeof(char);
}
int term_putc_iov(int who, struct iovec *iov, int iovcnt)
{
if (who != active_console)
return 0;
return writev(STDOUT_FILENO, iov, iovcnt);
}
bool term_readable(int who)
{
struct pollfd pollfd = (struct pollfd) {
.fd = STDIN_FILENO,
.events = POLLIN,
.revents = 0,
};
if (who != active_console)
return false;
return poll(&pollfd, 1, 0) > 0;
}
static void term_cleanup(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
}
void term_init(void)
{
struct termios term;
if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
die("unable to save initial standard input settings");
term = orig_term;
term.c_lflag &= ~(ICANON | ECHO | ISIG);
tcsetattr(STDIN_FILENO, TCSANOW, &term);
atexit(term_cleanup);
}