tty: implement binary I/O terminal mode
Introduce a uv_tty_mode_t enum for uv_tty_set_mode(), with backward compatible values. Add a new mode UV_TTY_MODE_IO, which uses cfmakeraw() internally. PR-URL: https://github.com/libuv/libuv/pull/86 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
751ac48baa
commit
025602da13
@ -16,6 +16,22 @@ Data types
|
|||||||
|
|
||||||
TTY handle type.
|
TTY handle type.
|
||||||
|
|
||||||
|
.. c:type:: uv_tty_mode_t
|
||||||
|
|
||||||
|
TTY mode type:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Initial/normal terminal mode */
|
||||||
|
UV_TTY_MODE_NORMAL,
|
||||||
|
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
|
||||||
|
UV_TTY_MODE_RAW,
|
||||||
|
/* Binary-safe I/O mode for IPC (Unix-only) */
|
||||||
|
UV_TTY_MODE_IO
|
||||||
|
} uv_tty_mode_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Public members
|
Public members
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
@ -43,9 +59,9 @@ API
|
|||||||
.. note::
|
.. note::
|
||||||
TTY streams which are not readable have blocking writes.
|
TTY streams which are not readable have blocking writes.
|
||||||
|
|
||||||
.. c:function:: int uv_tty_set_mode(uv_tty_t*, int mode)
|
.. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode)
|
||||||
|
|
||||||
Set the TTY mode. 0 for normal, 1 for raw.
|
Set the TTY using the specified terminal mode.
|
||||||
|
|
||||||
.. c:function:: int uv_tty_reset_mode(void)
|
.. c:function:: int uv_tty_reset_mode(void)
|
||||||
|
|
||||||
|
|||||||
21
include/uv.h
21
include/uv.h
@ -628,11 +628,30 @@ struct uv_tty_s {
|
|||||||
UV_TTY_PRIVATE_FIELDS
|
UV_TTY_PRIVATE_FIELDS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Initial/normal terminal mode */
|
||||||
|
UV_TTY_MODE_NORMAL,
|
||||||
|
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
|
||||||
|
UV_TTY_MODE_RAW,
|
||||||
|
/* Binary-safe I/O mode for IPC (Unix-only) */
|
||||||
|
UV_TTY_MODE_IO
|
||||||
|
} uv_tty_mode_t;
|
||||||
|
|
||||||
UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
|
UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
|
||||||
UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode);
|
UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode);
|
||||||
UV_EXTERN int uv_tty_reset_mode(void);
|
UV_EXTERN int uv_tty_reset_mode(void);
|
||||||
UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
|
UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
|
||||||
|
inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
|
||||||
|
return uv_tty_set_mode(handle, static_cast<uv_tty_mode_t>(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
|
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -98,19 +98,19 @@ skip:
|
|||||||
uv__nonblock(fd, 1);
|
uv__nonblock(fd, 1);
|
||||||
|
|
||||||
uv__stream_open((uv_stream_t*) tty, fd, flags);
|
uv__stream_open((uv_stream_t*) tty, fd, flags);
|
||||||
tty->mode = 0;
|
tty->mode = UV_TTY_MODE_NORMAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_tty_set_mode(uv_tty_t* tty, int mode) {
|
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
||||||
struct termios raw;
|
struct termios tmp;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = uv__stream_fd(tty);
|
fd = uv__stream_fd(tty);
|
||||||
|
|
||||||
if (mode && tty->mode == 0) { /* on */
|
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
|
||||||
if (tcgetattr(fd, &tty->orig_termios))
|
if (tcgetattr(fd, &tty->orig_termios))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
@ -121,27 +121,30 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
|
|||||||
orig_termios_fd = fd;
|
orig_termios_fd = fd;
|
||||||
}
|
}
|
||||||
uv_spinlock_unlock(&termios_spinlock);
|
uv_spinlock_unlock(&termios_spinlock);
|
||||||
|
|
||||||
raw = tty->orig_termios;
|
|
||||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
|
||||||
raw.c_oflag |= (ONLCR);
|
|
||||||
raw.c_cflag |= (CS8);
|
|
||||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
|
||||||
raw.c_cc[VMIN] = 1;
|
|
||||||
raw.c_cc[VTIME] = 0;
|
|
||||||
|
|
||||||
/* Put terminal in raw mode after draining */
|
|
||||||
if (tcsetattr(fd, TCSADRAIN, &raw))
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
tty->mode = 1;
|
|
||||||
} else if (mode == 0 && tty->mode) { /* off */
|
|
||||||
/* Put terminal in original mode after flushing */
|
|
||||||
if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios))
|
|
||||||
return -errno;
|
|
||||||
tty->mode = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmp = tty->orig_termios;
|
||||||
|
switch (mode) {
|
||||||
|
case UV_TTY_MODE_NORMAL:
|
||||||
|
break;
|
||||||
|
case UV_TTY_MODE_RAW:
|
||||||
|
tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||||
|
tmp.c_oflag |= (ONLCR);
|
||||||
|
tmp.c_cflag |= (CS8);
|
||||||
|
tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||||
|
tmp.c_cc[VMIN] = 1;
|
||||||
|
tmp.c_cc[VTIME] = 0;
|
||||||
|
break;
|
||||||
|
case UV_TTY_MODE_IO:
|
||||||
|
cfmakeraw(&tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply changes after draining */
|
||||||
|
if (tcsetattr(fd, TCSADRAIN, &tmp))
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
tty->mode = mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -170,7 +170,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_tty_set_mode(uv_tty_t* tty, int mode) {
|
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
unsigned char was_reading;
|
unsigned char was_reading;
|
||||||
uv_alloc_cb alloc_cb;
|
uv_alloc_cb alloc_cb;
|
||||||
@ -185,12 +185,15 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode) {
|
switch (mode) {
|
||||||
/* Raw input */
|
case UV_TTY_MODE_NORMAL:
|
||||||
flags = ENABLE_WINDOW_INPUT;
|
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
|
||||||
} else {
|
break;
|
||||||
/* Line-buffered mode. */
|
case UV_TTY_MODE_RAW:
|
||||||
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
|
flags = ENABLE_WINDOW_INPUT;
|
||||||
|
break;
|
||||||
|
case UV_TTY_MODE_IO:
|
||||||
|
return UV_ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetConsoleMode(tty->handle, flags)) {
|
if (!SetConsoleMode(tty->handle, flags)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user