Spike, a RISC-V ISA Simulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

88 lines
1.7 KiB

#include "term.h"
#include "common.h"
#include <termios.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
static int tcsetattr_ttou(int fd, int optional_actions, const struct termios *p);
class canonical_termios_t
{
public:
canonical_termios_t()
: restore_tios(false)
{
if (tcgetattr(0, &old_tios) == 0)
{
struct termios new_tios = old_tios;
new_tios.c_lflag &= ~(ICANON | ECHO);
if (tcsetattr_ttou(0, TCSANOW, &new_tios) == 0)
restore_tios = true;
}
}
~canonical_termios_t()
{
if (restore_tios)
tcsetattr_ttou(0, TCSANOW, &old_tios);
}
private:
struct termios old_tios;
bool restore_tios;
};
static canonical_termios_t tios; // exit() will clean up for us
int canonical_terminal_t::read()
{
struct pollfd pfd;
pfd.fd = 0;
pfd.events = POLLIN;
int ret = poll(&pfd, 1, 0);
if (ret <= 0 || !(pfd.revents & POLLIN))
return -1;
unsigned char ch;
ret = ::read(0, &ch, 1);
return ret <= 0 ? -1 : ch;
}
void canonical_terminal_t::write(char ch)
{
if (::write(1, &ch, 1) != 1)
abort();
}
static volatile sig_atomic_t sigttou_caught;
static void sigttou_handler(int UNUSED signum) {
sigttou_caught = 1;
}
static int tcsetattr_ttou(int fd, int optional_actions, const struct termios *p)
{
struct sigaction sa, old_sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigttou_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGTTOU, &sa, &old_sa))
abort();
sigttou_caught = 0;
int result = tcsetattr(fd, optional_actions, p);
if (sigttou_caught) {
sigaction(SIGTTOU, &old_sa, NULL);
return -1;
}
if (sigaction(SIGTTOU, &old_sa, NULL))
abort();
return result;
}