Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
unix: allow tty raw mode to be turned off
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Sep 30, 2011
1 parent e53d125 commit 153d3c7
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 24 deletions.
6 changes: 4 additions & 2 deletions include/uv-private/uv-unix.h
Expand Up @@ -37,7 +37,7 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <termios.h>

/* Note: May be cast to struct iovec. See writev(2). */
typedef struct {
Expand Down Expand Up @@ -184,6 +184,8 @@ typedef int uv_file;
#define UV_WORK_PRIVATE_FIELDS \
eio_req* eio;

#define UV_TTY_PRIVATE_FIELDS /* empty */
#define UV_TTY_PRIVATE_FIELDS \
struct termios orig_termios; \
int mode;

#endif /* UV_UNIX_H */
57 changes: 35 additions & 22 deletions src/unix/tty.c
Expand Up @@ -34,38 +34,51 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd) {
uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY);
uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE | UV_WRITABLE);
loop->counters.tty_init++;
tty->mode = 0;
return 0;
}


int uv_tty_set_mode(uv_tty_t* tty, int mode) {
int fd = tty->fd;
struct termios orig_termios; /* in order to restore at exit */
struct termios raw;

if (tcgetattr(fd, &orig_termios) == -1) goto fatal;

raw = orig_termios; /* modify the original mode */
/* input modes: no break, no CR to NL, no parity check, no strip char,
* no start/stop output control. */
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/* output modes */
raw.c_oflag |= (ONLCR);
/* control modes - set 8 bit chars */
raw.c_cflag |= (CS8);
/* local modes - echoing off, canonical off, no extended functions,
* no signal chars (^Z,^C) */
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
/* control chars - set return condition: min number of bytes and timer.
* We want read to return every single byte, without timeout. */
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */

/* put terminal in raw mode after flushing */
if (tcsetattr(fd, TCSAFLUSH, &raw) < 0) goto fatal;
return 0;
if (mode && tty->mode == 0) {
/* on */

if (tcgetattr(fd, &tty->orig_termios)) {
goto fatal;
}

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 flushing */
if (tcsetattr(fd, TCSAFLUSH, &raw)) {
goto fatal;
}

tty->mode = 1;
return 0;
} else if (mode == 0 && tty->mode) {
/* off */

/* Put terminal in original mode after flushing */
if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios)) {
goto fatal;
}

tty->mode = 0;
return 0;
}

fatal:
uv__set_sys_error(tty->loop, ENOTTY);
uv__set_sys_error(tty->loop, errno);
return -1;
}

Expand Down
10 changes: 10 additions & 0 deletions test/test-tty.c
Expand Up @@ -48,6 +48,16 @@ TEST_IMPL(tty) {
ASSERT(width > 10);
ASSERT(height > 10);

/* Turn on raw mode. */
r = uv_tty_set_mode(&tty, 1);
ASSERT(r == 0);

/* Turn off raw mode. */
r = uv_tty_set_mode(&tty, 0);
ASSERT(r == 0);

/* TODO check the actual mode! */

uv_close((uv_handle_t*)&tty, NULL);

uv_run(loop);
Expand Down

0 comments on commit 153d3c7

Please sign in to comment.