Skip to content

Commit

Permalink
Implement Blinkenlights fixes for Cygwin
Browse files Browse the repository at this point in the history
  • Loading branch information
Justine Tunney committed Jan 8, 2023
1 parent 7c27fac commit 75b11e2
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 33 deletions.
99 changes: 74 additions & 25 deletions blink/blinkenlights.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,19 +713,17 @@ static void TuiRejuvinate(void) {
term.c_cflag &= ~(CSIZE | PARENB);
term.c_cflag |= CS8 | CREAD;
term.c_oflag |= OPOST | ONLCR;
term.c_lflag &= ~ECHOK;
#ifdef IMAXBEL
term.c_iflag &= ~IMAXBEL;
#endif
#ifdef ECHOK
term.c_lflag &= ~ECHOK;
#endif
#ifdef PENDIN
term.c_lflag &= ~PENDIN;
#endif
#ifdef IUTF8
term.c_iflag |= IUTF8;
#endif
ioctl(ttyout, TCSETS, &term);
tcsetattr(ttyout, TCSANOW, &term);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = OnSigBusted;
sa.sa_flags = SA_NODEFER;
Expand Down Expand Up @@ -775,7 +773,7 @@ static void TtyRestore1(void) {

static void TtyRestore2(void) {
LOGF("TtyRestore2");
ioctl(ttyout, TCSETS, &oldterm);
tcsetattr(ttyout, TCSANOW, &oldterm);
DisableMouseTracking();
}

Expand Down Expand Up @@ -896,7 +894,7 @@ void TuiSetup(void) {
if (!once) {
/* LOGF("loaded program %s\n%s", codepath, gc(FormatPml4t(m))); */
CommonSetup();
ioctl(ttyout, TCGETS, &oldterm);
tcgetattr(ttyout, &oldterm);
atexit(TtyRestore2);
once = true;
report = true;
Expand Down Expand Up @@ -2350,15 +2348,81 @@ static int OnPtyFdTiocgwinsz(int fd, struct winsize *ws) {
return 0;
}

static int OnPtyFdTcgets(int fd, struct termios *c) {
static int OnPtyFdTcsets(int fd, u64 request, struct termios *c) {
return 0;
}

static int OnPtyFdIoctl(int fd, unsigned long request, ...) {
va_list va;
struct winsize *ws;
if (request == TIOCGWINSZ) {
va_start(va, request);
ws = va_arg(va, struct winsize *);
va_end(va);
return OnPtyFdTiocgwinsz(fd, ws);
} else {
return einval();
}
}

static int OnPtyTcgetattr(int fd, struct termios *c) {
// TODO(jart): We should just use the Linux ABI for these.
memset(c, 0, sizeof(*c));
c->c_iflag = ICRNL | IXON
#ifdef IUTF8
| IUTF8
#endif
;
c->c_oflag = 0
#ifdef ONLCR
| ONLCR
#endif
;
c->c_cflag = CREAD | CS8;
c->c_lflag = ISIG | ECHOE | IEXTEN | ECHOK
#ifdef ECHOCTL
| ECHOCTL
#endif
#ifdef ECHOKE
| ECHOKE
#endif
;
c->c_cc[VMIN] = 1;
c->c_cc[VTIME] = 0;
c->c_cc[VINTR] = Ctrl('C');
c->c_cc[VQUIT] = Ctrl('\\');
c->c_cc[VERASE] = Ctrl('?');
c->c_cc[VKILL] = Ctrl('U');
c->c_cc[VEOF] = Ctrl('D');
c->c_cc[VSTART] = Ctrl('Q');
c->c_cc[VSTOP] = Ctrl('S');
c->c_cc[VSUSP] = Ctrl('Z');
c->c_cc[VEOL] = Ctrl('@');
#ifdef VSWTC
c->c_cc[VSWTC] = Ctrl('@');
#endif
#ifdef VREPRINT
c->c_cc[VREPRINT] = Ctrl('R');
#endif
#ifdef VDISCARD
c->c_cc[VDISCARD] = Ctrl('O');
#endif
#ifdef VWERASE
c->c_cc[VWERASE] = Ctrl('W');
#endif
#ifdef VLNEXT
c->c_cc[VLNEXT] = Ctrl('V');
#endif
#ifdef VEOL2
c->c_cc[VEOL2] = Ctrl('@');
#endif
if (!(pty->conf & kPtyNocanon)) c->c_iflag |= ICANON;
if (!(pty->conf & kPtyNoecho)) c->c_iflag |= ECHO;
if (!(pty->conf & kPtyNoopost)) c->c_oflag |= OPOST;
return 0;
}

static int OnPtyFdTcsets(int fd, u64 request, struct termios *c) {
static int OnPtyTcsetattr(int fd, int cmd, const struct termios *c) {
if (c->c_iflag & ICANON) {
pty->conf &= ~kPtyNocanon;
} else {
Expand All @@ -2377,29 +2441,14 @@ static int OnPtyFdTcsets(int fd, u64 request, struct termios *c) {
return 0;
}

static int OnPtyFdIoctl(int fd, unsigned long request, ...) {
va_list va;
va_start(va, request);
if (request == TIOCGWINSZ) {
return OnPtyFdTiocgwinsz(fd, va_arg(va, struct winsize *));
} else if (request == TCGETS) {
return OnPtyFdTcgets(fd, va_arg(va, struct termios *));
} else if (request == TCSETS || request == TCSETSW || request == TCSETSF) {
return OnPtyFdTcsets(fd, request, va_arg(va, struct termios *));
} else {
errno = EINVAL;
return -1;
}
va_end(va);
return 0;
}

static const struct FdCb kFdCbPty = {
.close = OnPtyFdClose,
.readv = OnPtyFdReadv,
.writev = OnPtyFdWritev,
.ioctl = OnPtyFdIoctl,
.poll = OnPtyFdPoll,
.tcgetattr = OnPtyTcgetattr,
.tcsetattr = OnPtyTcsetattr,
};

static void LaunchDebuggerReactively(void) {
Expand Down
3 changes: 3 additions & 0 deletions blink/fds.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <poll.h>
#include <pthread.h>
#include <sys/uio.h>
#include <termios.h>

#include "blink/dll.h"
#include "blink/types.h"
Expand All @@ -17,6 +18,8 @@ struct FdCb {
ssize_t (*writev)(int, const struct iovec *, int);
int (*ioctl)(int, unsigned long, ...);
int (*poll)(struct pollfd *, nfds_t, int);
int (*tcgetattr)(int, struct termios *);
int (*tcsetattr)(int, int, const struct termios *);
};

struct Fd {
Expand Down
22 changes: 14 additions & 8 deletions blink/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ const struct FdCb kFdCbHost = {
.writev = writev,
.ioctl = SystemIoctl,
.poll = poll,
.tcgetattr = tcgetattr,
.tcsetattr = tcsetattr,
};

void AddStdFd(struct Fds *fds, int fildes) {
Expand Down Expand Up @@ -1330,19 +1332,19 @@ static int IoctlTiocgwinsz(struct Machine *m, int fd, i64 addr,
}

static int IoctlTcgets(struct Machine *m, int fd, i64 addr,
int fn(int, unsigned long, ...)) {
int fn(int, struct termios *)) {
int rc;
struct termios tio;
struct termios_linux gtio;
if ((rc = fn(fd, TCGETS, &tio)) != -1) {
if ((rc = fn(fd, &tio)) != -1) {
XlatTermiosToLinux(&gtio, &tio);
CopyToUserWrite(m, addr, &gtio, sizeof(gtio));
}
return rc;
}

static int IoctlTcsets(struct Machine *m, int fd, unsigned long request,
i64 addr, int fn(int, unsigned long, ...)) {
static int IoctlTcsets(struct Machine *m, int fd, int request, i64 addr,
int fn(int, int, const struct termios *)) {
struct termios tio;
struct termios_linux gtio;
CopyFromUserRead(m, &gtio, addr, sizeof(gtio));
Expand Down Expand Up @@ -1429,10 +1431,14 @@ static int SysIoctl(struct Machine *m, int fildes, u64 request, i64 addr) {
int rc;
struct Fd *fd;
int (*ioctl_impl)(int, unsigned long, ...);
int (*tcgetattr_impl)(int, struct termios *);
int (*tcsetattr_impl)(int, int, const struct termios *);
LockFds(&m->system->fds);
if ((fd = GetFd(&m->system->fds, fildes))) {
unassert(fd->cb);
unassert(ioctl_impl = fd->cb->ioctl);
unassert(tcgetattr_impl = fd->cb->tcgetattr);
unassert(tcsetattr_impl = fd->cb->tcsetattr);
} else {
ioctl_impl = 0;
}
Expand All @@ -1443,16 +1449,16 @@ static int SysIoctl(struct Machine *m, int fildes, u64 request, i64 addr) {
rc = IoctlTiocgwinsz(m, fildes, addr, ioctl_impl);
break;
case TCGETS_LINUX:
rc = IoctlTcgets(m, fildes, addr, ioctl_impl);
rc = IoctlTcgets(m, fildes, addr, tcgetattr_impl);
break;
case TCSETS_LINUX:
rc = IoctlTcsets(m, fildes, TCSETS, addr, ioctl_impl);
rc = IoctlTcsets(m, fildes, TCSANOW, addr, tcsetattr_impl);
break;
case TCSETSW_LINUX:
rc = IoctlTcsets(m, fildes, TCSETSW, addr, ioctl_impl);
rc = IoctlTcsets(m, fildes, TCSADRAIN, addr, tcsetattr_impl);
break;
case TCSETSF_LINUX:
rc = IoctlTcsets(m, fildes, TCSETSF, addr, ioctl_impl);
rc = IoctlTcsets(m, fildes, TCSAFLUSH, addr, tcsetattr_impl);
break;
case SIOCGIFCONF_LINUX:
rc = IoctlSiocgifconf(m, fildes, addr);
Expand Down

0 comments on commit 75b11e2

Please sign in to comment.