version 1.243, 2017/02/08 23:53:03 |
version 1.244, 2017/02/10 12:59:18 |
|
|
|
|
static int tty_log_fd = -1; |
static int tty_log_fd = -1; |
|
|
static void tty_init_termios(int, struct termios *, struct bufferevent *); |
|
|
|
static void tty_read_callback(struct bufferevent *, void *); |
|
static void tty_error_callback(struct bufferevent *, short, void *); |
|
|
|
static int tty_client_ready(struct client *, struct window_pane *); |
static int tty_client_ready(struct client *, struct window_pane *); |
|
|
static void tty_set_italics(struct tty *); |
static void tty_set_italics(struct tty *); |
|
|
return (1); |
return (1); |
} |
} |
|
|
|
static void |
|
tty_read_callback(__unused int fd, __unused short events, void *data) |
|
{ |
|
struct tty *tty = data; |
|
size_t size = EVBUFFER_LENGTH(tty->in); |
|
int nread; |
|
|
|
nread = evbuffer_read(tty->in, tty->fd, -1); |
|
if (nread == -1) |
|
return; |
|
log_debug("%s: read %d bytes (already %zu)", tty->path, nread, size); |
|
|
|
while (tty_keys_next(tty)) |
|
; |
|
} |
|
|
|
static void |
|
tty_write_callback(__unused int fd, __unused short events, void *data) |
|
{ |
|
struct tty *tty = data; |
|
size_t size = EVBUFFER_LENGTH(tty->out); |
|
int nwrite; |
|
|
|
nwrite = evbuffer_write(tty->out, tty->fd); |
|
if (nwrite == -1) |
|
return; |
|
log_debug("%s: wrote %d bytes (of %zu)", tty->path, nwrite, size); |
|
|
|
if (EVBUFFER_LENGTH(tty->out) == 0) |
|
event_del(&tty->event_out); |
|
} |
|
|
int |
int |
tty_open(struct tty *tty, char **cause) |
tty_open(struct tty *tty, char **cause) |
{ |
{ |
|
|
} |
} |
tty->flags |= TTY_OPENED; |
tty->flags |= TTY_OPENED; |
|
|
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_TIMER); |
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE); |
|
|
tty->event = bufferevent_new(tty->fd, tty_read_callback, NULL, |
event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, |
tty_error_callback, tty); |
tty_read_callback, tty); |
|
tty->in = evbuffer_new(); |
|
|
|
event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty); |
|
tty->out = evbuffer_new(); |
|
|
tty_start_tty(tty); |
tty_start_tty(tty); |
|
|
tty_keys_build(tty); |
tty_keys_build(tty); |
|
|
return (0); |
return (0); |
} |
} |
|
|
static void |
void |
tty_read_callback(__unused struct bufferevent *bufev, void *data) |
tty_start_tty(struct tty *tty) |
{ |
{ |
struct tty *tty = data; |
|
|
|
while (tty_keys_next(tty)) |
|
; |
|
} |
|
|
|
static void |
|
tty_error_callback(__unused struct bufferevent *bufev, __unused short what, |
|
__unused void *data) |
|
{ |
|
} |
|
|
|
static void |
|
tty_init_termios(int fd, struct termios *orig_tio, struct bufferevent *bufev) |
|
{ |
|
struct termios tio; |
struct termios tio; |
|
|
if (fd == -1 || tcgetattr(fd, orig_tio) != 0) |
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) { |
return; |
setblocking(tty->fd, 0); |
|
event_add(&tty->event_in, NULL); |
|
|
setblocking(fd, 0); |
memcpy(&tio, &tty->tio, sizeof tio); |
|
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP); |
|
tio.c_iflag |= IGNBRK; |
|
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); |
|
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL| |
|
ECHOPRT|ECHOKE|ISIG); |
|
tio.c_cc[VMIN] = 1; |
|
tio.c_cc[VTIME] = 0; |
|
if (tcsetattr(tty->fd, TCSANOW, &tio) == 0) |
|
tcflush(tty->fd, TCIOFLUSH); |
|
} |
|
|
if (bufev != NULL) |
|
bufferevent_enable(bufev, EV_READ|EV_WRITE); |
|
|
|
memcpy(&tio, orig_tio, sizeof tio); |
|
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP); |
|
tio.c_iflag |= IGNBRK; |
|
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); |
|
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL| |
|
ECHOPRT|ECHOKE|ISIG); |
|
tio.c_cc[VMIN] = 1; |
|
tio.c_cc[VTIME] = 0; |
|
if (tcsetattr(fd, TCSANOW, &tio) == 0) |
|
tcflush(fd, TCIOFLUSH); |
|
} |
|
|
|
void |
|
tty_start_tty(struct tty *tty) |
|
{ |
|
tty_init_termios(tty->fd, &tty->tio, tty->event); |
|
|
|
tty_putcode(tty, TTYC_SMCUP); |
tty_putcode(tty, TTYC_SMCUP); |
|
|
tty_putcode(tty, TTYC_RMKX); |
tty_putcode(tty, TTYC_RMKX); |
|
|
return; |
return; |
tty->flags &= ~TTY_STARTED; |
tty->flags &= ~TTY_STARTED; |
|
|
bufferevent_disable(tty->event, EV_READ|EV_WRITE); |
event_del(&tty->event_in); |
|
event_del(&tty->event_out); |
|
|
/* |
/* |
* Be flexible about error handling and try not kill the server just |
* Be flexible about error handling and try not kill the server just |
|
|
tty_stop_tty(tty); |
tty_stop_tty(tty); |
|
|
if (tty->flags & TTY_OPENED) { |
if (tty->flags & TTY_OPENED) { |
bufferevent_free(tty->event); |
evbuffer_free(tty->in); |
|
event_del(&tty->event_in); |
|
evbuffer_free(tty->out); |
|
event_del(&tty->event_out); |
|
|
tty_term_free(tty->term); |
tty_term_free(tty->term); |
tty_keys_free(tty); |
tty_keys_free(tty); |
|
|
static void |
static void |
tty_add(struct tty *tty, const char *buf, size_t len) |
tty_add(struct tty *tty, const char *buf, size_t len) |
{ |
{ |
bufferevent_write(tty->event, buf, len); |
evbuffer_add(tty->out, buf, len); |
log_debug("%s: %.*s", tty->path, (int)len, buf); |
log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf); |
|
|
if (tty_log_fd != -1) |
if (tty_log_fd != -1) |
write(tty_log_fd, buf, len); |
write(tty_log_fd, buf, len); |
|
if (tty->flags & TTY_STARTED) |
|
event_add(&tty->event_out, NULL); |
} |
} |
|
|
void |
void |
|
|
{ |
{ |
if (c->session == NULL || c->tty.term == NULL) |
if (c->session == NULL || c->tty.term == NULL) |
return (0); |
return (0); |
if (c->flags & CLIENT_SUSPENDED) |
if (c->flags & (CLIENT_REDRAW|CLIENT_SUSPENDED)) |
return (0); |
return (0); |
if (c->tty.flags & TTY_FREEZE) |
if (c->tty.flags & TTY_FREEZE) |
return (0); |
return (0); |