/* Initialise a key tree from the table. */ void tty_keys_build(struct tty *tty) { const struct tty_default_key_raw *tdkr; const struct tty_default_key_code *tdkc; u_int i; const char *s; if (tty->key_tree != NULL) tty_keys_free(tty); tty->key_tree = NULL; for (i = 0; i < nitems(tty_default_raw_keys); i++) { tdkr = &tty_default_raw_keys[i]; s = tdkr->string; if (*s != '\0') tty_keys_add(tty, s, tdkr->key); } for (i = 0; i < nitems(tty_default_code_keys); i++) { tdkc = &tty_default_code_keys[i]; s = tty_term_string(tty->term, tdkc->code); if (*s != '\0') tty_keys_add(tty, s, tdkc->key); } }
void tty_stop_tty(struct tty *tty) { struct winsize ws; /* * Be flexible about error handling and try not kill the server just * because the fd is invalid. Things like ssh -t can easily leave us * with a dead tty. */ if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) return; if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) return; tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); if (tty_term_has(tty->term, TTYC_KMOUS)) tty_raw(tty, "\033[?1000l"); }
void tty_stop_tty(struct tty *tty) { struct winsize ws; if (!(tty->flags & TTY_STARTED)) return; tty->flags &= ~TTY_STARTED; bufferevent_disable(tty->event, EV_READ|EV_WRITE); /* * Be flexible about error handling and try not kill the server just * because the fd is invalid. Things like ssh -t can easily leave us * with a dead tty. */ if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) return; if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) return; setblocking(tty->fd, 1); tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1)); if (tty_use_acs(tty)) tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); if (tty_term_has(tty->term, TTYC_CS1) && tty->cstyle != 0) { if (tty_term_has(tty->term, TTYC_CSR1)) tty_raw(tty, tty_term_string(tty->term, TTYC_CSR1)); else tty_raw(tty, tty_term_string1(tty->term, TTYC_CS1, 0)); } tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); if (tty_term_has(tty->term, TTYC_KMOUS)) tty_raw(tty, "\033[?1000l"); tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); if (tty->xterm_version > 270) tty_raw(tty, "\033[61;1\"p"); }
void tty_fill_acs(struct tty *tty) { const char *ptr; memset(tty->acs, 0, sizeof tty->acs); if (!tty_term_has(tty->term, TTYC_ACSC)) return; ptr = tty_term_string(tty->term, TTYC_ACSC); if (strlen(ptr) % 2 != 0) return; for (; *ptr != '\0'; ptr += 2) tty->acs[(u_char) ptr[0]] = ptr[1]; }
/* Initialise a key tree from the table. */ void tty_keys_init(struct tty *tty) { const struct tty_key_ent *tke; u_int i; const char *s; tty->key_tree = NULL; for (i = 0; i < nitems(tty_keys); i++) { tke = &tty_keys[i]; if (tke->flags & TTYKEY_RAW) s = tke->string; else { if (!tty_term_has(tty->term, tke->code)) continue; s = tty_term_string(tty->term, tke->code); } if (s[0] != '\033' || s[1] == '\0') continue; tty_keys_add(tty, s + 1, tke->key); } }
void tty_stop_tty(struct tty *tty) { struct winsize ws; int mode; if (!(tty->flags & TTY_STARTED)) return; tty->flags &= ~TTY_STARTED; bufferevent_disable(tty->event, EV_READ|EV_WRITE); /* * Be flexible about error handling and try not kill the server just * because the fd is invalid. Things like ssh -t can easily leave us * with a dead tty. */ if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) return; if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) return; tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); if (tty_term_has(tty->term, TTYC_KMOUS)) tty_raw(tty, "\033[?1000l"); tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); if ((mode = fcntl(tty->fd, F_GETFL)) != -1) fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK); }
void tty_putcode(struct tty *tty, enum tty_code_code code) { tty_puts(tty, tty_term_string(tty->term, code)); }
void tty_detect_utf8(struct tty *tty) { struct pollfd pfd; char buf[7]; size_t len; ssize_t n; int nfds; struct termios tio, old_tio; #ifdef TIOCFLUSH int what; #endif if (tty->flags & TTY_UTF8) return; /* * If the terminal looks reasonably likely to support this, try to * write a three-byte UTF-8 wide character to the terminal, then read * the cursor position. * * XXX This entire function is a hack. */ /* Check if the terminal looks sort of vt100. */ if (strstr(tty_term_string(tty->term, TTYC_CLEAR), "[2J") == NULL || strstr(tty_term_string(tty->term, TTYC_CUP), "H") == NULL) return; if (tcgetattr(tty->fd, &old_tio) != 0) fatal("tcgetattr failed"); cfmakeraw(&tio); if (tcsetattr(tty->fd, TCSANOW, &tio) != 0) fatal("tcsetattr failed"); #ifdef TIOCFLUSH what = 0; if (ioctl(tty->fd, TIOCFLUSH, &what) != 0) fatal("ioctl(TIOCFLUSH)"); #endif #define UTF8_TEST_DATA "\033[H\357\277\246\033[6n" if (write(tty->fd, UTF8_TEST_DATA, (sizeof UTF8_TEST_DATA) - 1) == -1) fatal("write failed"); #undef UTF8_TEST_DATA len = 0; for (;;) { pfd.fd = tty->fd; pfd.events = POLLIN; nfds = poll(&pfd, 1, 500); if (nfds == -1) { if (errno == EAGAIN || errno == EINTR) continue; fatal("poll failed"); } if (nfds == 0) break; #ifdef HAVE_POLL if (pfd.revents & (POLLERR|POLLNVAL|POLLHUP)) break; #endif if (!(pfd.revents & POLLIN)) continue; if ((n = read(tty->fd, buf + len, 1)) != 1) break; buf[++len] = '\0'; if (len == (sizeof buf) - 1) { if (strcmp(buf, "\033[1;3R") == 0) tty->flags |= TTY_UTF8; break; } } if (tcsetattr(tty->fd, TCSANOW, &old_tio) != 0) fatal("tcsetattr failed"); }