version 1.379, 2020/05/22 15:08:38 |
version 1.380, 2020/05/24 09:13:06 |
|
|
} |
} |
|
|
int |
int |
tty_init(struct tty *tty, struct client *c, int fd) |
tty_init(struct tty *tty, struct client *c) |
{ |
{ |
if (!isatty(fd)) |
if (!isatty(c->fd)) |
return (-1); |
return (-1); |
|
|
memset(tty, 0, sizeof *tty); |
memset(tty, 0, sizeof *tty); |
|
|
tty->fd = fd; |
|
tty->client = c; |
tty->client = c; |
|
|
tty->cstyle = 0; |
tty->cstyle = 0; |
tty->ccolour = xstrdup(""); |
tty->ccolour = xstrdup(""); |
|
|
|
if (tcgetattr(c->fd, &tty->tio) != 0) |
|
return (-1); |
return (0); |
return (0); |
} |
} |
|
|
|
|
struct winsize ws; |
struct winsize ws; |
u_int sx, sy, xpixel, ypixel; |
u_int sx, sy, xpixel, ypixel; |
|
|
if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) { |
if (ioctl(c->fd, TIOCGWINSZ, &ws) != -1) { |
sx = ws.ws_col; |
sx = ws.ws_col; |
if (sx == 0) { |
if (sx == 0) { |
sx = 80; |
sx = 80; |
|
|
size_t size = EVBUFFER_LENGTH(tty->in); |
size_t size = EVBUFFER_LENGTH(tty->in); |
int nread; |
int nread; |
|
|
nread = evbuffer_read(tty->in, tty->fd, -1); |
nread = evbuffer_read(tty->in, c->fd, -1); |
if (nread == 0 || nread == -1) { |
if (nread == 0 || nread == -1) { |
if (nread == 0) |
if (nread == 0) |
log_debug("%s: read closed", name); |
log_debug("%s: read closed", name); |
|
|
size_t size = EVBUFFER_LENGTH(tty->out); |
size_t size = EVBUFFER_LENGTH(tty->out); |
int nwrite; |
int nwrite; |
|
|
nwrite = evbuffer_write(tty->out, tty->fd); |
nwrite = evbuffer_write(tty->out, c->fd); |
if (nwrite == -1) |
if (nwrite == -1) |
return; |
return; |
log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size); |
log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size); |
|
|
struct client *c = tty->client; |
struct client *c = tty->client; |
|
|
tty->term = tty_term_create(tty, c->term_name, &c->term_features, |
tty->term = tty_term_create(tty, c->term_name, &c->term_features, |
tty->fd, cause); |
c->fd, cause); |
if (tty->term == NULL) { |
if (tty->term == NULL) { |
tty_close(tty); |
tty_close(tty); |
return (-1); |
return (-1); |
|
|
|
|
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER); |
tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER); |
|
|
event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ, |
event_set(&tty->event_in, c->fd, EV_PERSIST|EV_READ, |
tty_read_callback, tty); |
tty_read_callback, tty); |
tty->in = evbuffer_new(); |
tty->in = evbuffer_new(); |
if (tty->in == NULL) |
if (tty->in == NULL) |
fatal("out of memory"); |
fatal("out of memory"); |
|
|
event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty); |
event_set(&tty->event_out, c->fd, EV_WRITE, tty_write_callback, tty); |
tty->out = evbuffer_new(); |
tty->out = evbuffer_new(); |
if (tty->out == NULL) |
if (tty->out == NULL) |
fatal("out of memory"); |
fatal("out of memory"); |
|
|
struct termios tio; |
struct termios tio; |
struct timeval tv = { .tv_sec = 1 }; |
struct timeval tv = { .tv_sec = 1 }; |
|
|
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) { |
setblocking(c->fd, 0); |
setblocking(tty->fd, 0); |
event_add(&tty->event_in, NULL); |
event_add(&tty->event_in, NULL); |
|
|
|
memcpy(&tio, &tty->tio, sizeof tio); |
memcpy(&tio, &tty->tio, sizeof tio); |
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP); |
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP); |
tio.c_iflag |= IGNBRK; |
tio.c_iflag |= IGNBRK; |
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); |
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); |
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL| |
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|ECHOPRT| |
ECHOPRT|ECHOKE|ISIG); |
ECHOKE|ISIG); |
tio.c_cc[VMIN] = 1; |
tio.c_cc[VMIN] = 1; |
tio.c_cc[VTIME] = 0; |
tio.c_cc[VTIME] = 0; |
if (tcsetattr(tty->fd, TCSANOW, &tio) == 0) |
if (tcsetattr(c->fd, TCSANOW, &tio) == 0) |
tcflush(tty->fd, TCIOFLUSH); |
tcflush(c->fd, TCIOFLUSH); |
} |
|
|
|
tty_putcode(tty, TTYC_SMCUP); |
tty_putcode(tty, TTYC_SMCUP); |
|
|
|
|
void |
void |
tty_stop_tty(struct tty *tty) |
tty_stop_tty(struct tty *tty) |
{ |
{ |
struct winsize ws; |
struct client *c = tty->client; |
|
struct winsize ws; |
|
|
if (!(tty->flags & TTY_STARTED)) |
if (!(tty->flags & TTY_STARTED)) |
return; |
return; |
|
|
* because the fd is invalid. Things like ssh -t can easily leave us |
* because the fd is invalid. Things like ssh -t can easily leave us |
* with a dead tty. |
* with a dead tty. |
*/ |
*/ |
if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) |
if (ioctl(c->fd, TIOCGWINSZ, &ws) == -1) |
return; |
return; |
if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) |
if (tcsetattr(c->fd, TCSANOW, &tty->tio) == -1) |
return; |
return; |
|
|
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1)); |
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1)); |
|
|
tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG)); |
tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG)); |
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); |
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); |
|
|
setblocking(tty->fd, 1); |
setblocking(c->fd, 1); |
} |
} |
|
|
void |
void |
|
|
|
|
tty->flags &= ~TTY_OPENED; |
tty->flags &= ~TTY_OPENED; |
} |
} |
|
|
if (tty->fd != -1) { |
|
close(tty->fd); |
|
tty->fd = -1; |
|
} |
|
} |
} |
|
|
void |
void |
|
|
void |
void |
tty_raw(struct tty *tty, const char *s) |
tty_raw(struct tty *tty, const char *s) |
{ |
{ |
ssize_t n, slen; |
struct client *c = tty->client; |
u_int i; |
ssize_t n, slen; |
|
u_int i; |
|
|
slen = strlen(s); |
slen = strlen(s); |
for (i = 0; i < 5; i++) { |
for (i = 0; i < 5; i++) { |
n = write(tty->fd, s, slen); |
n = write(c->fd, s, slen); |
if (n >= 0) { |
if (n >= 0) { |
s += n; |
s += n; |
slen -= n; |
slen -= n; |