// SPDX-License-Identifier: ISC #include #include #include #include #include #include struct tty_reset_list { int fd; struct termios tcattr; struct tty_reset_list *prev; }; static struct tty_reset_list *tty_reset_head; static void term_resetconf(void) { struct tty_reset_list *cur = tty_reset_head; while (cur) { if (tcsetattr(cur->fd, TCSANOW, &cur->tcattr) < 0) warn("warning: unable to restore the terminal settings for %d", cur->fd); cur = cur->prev; } } int term_setconf_init(void) { /* TODO: signal handlers */ if (atexit(term_resetconf) < 0) return -1; return 0; } int term_setconf_raw(int fd, speed_t speed) { struct tty_reset_list *next; struct termios tcattr; int errsv; next = calloc(1, sizeof(*next)); if (!next) return -1; next->fd = fd; if (tcgetattr(next->fd, &next->tcattr) < 0) goto fail; tcattr = next->tcattr; cfmakeraw(&tcattr); if (cfsetspeed(&tcattr, speed) < 0) goto fail; tcattr.c_cflag &= ~(CSTOPB|CRTSCTS); tcattr.c_cflag |= (CLOCAL|CREAD); tcattr.c_cc[VTIME] = 1; tcattr.c_cc[VMIN] = 1; if (tcsetattr(next->fd, TCSAFLUSH, &tcattr) < 0) goto fail; next->prev = tty_reset_head; tty_reset_head = next; return 0; fail: errsv = errno; free(next); errno = errsv; return -1; } int term_speed_parse(const char *name, speed_t *speed) { /* from termios(3), only the portable subset */ static const struct { speed_t speed; const char *name; } speed_tbl[] = { { B0, "0" }, { B50, "50" }, { B75, "75" }, { B110, "110" }, { B134, "134" }, { B150, "150" }, { B200, "200" }, { B300, "300" }, { B600, "600" }, { B1200, "1200" }, { B1800, "1800" }, { B2400, "2400" }, { B4800, "4800" }, { B9600, "9600" }, { B19200, "19200" }, { B38400, "38400" }, { B57600, "57600" }, { B115200, "115200" }, { B230400, "230400" }, { B460800, "460800" }, { B500000, "500000" }, { B576000, "576000" }, { B921600, "921600" }, { B1000000, "1000000" }, { B1152000, "1152000" }, { B1500000, "1500000" }, { B2000000, "2000000" }, }; for (size_t i = 0; i < ARRAY_SIZE(speed_tbl); ++i) { if (!strcmp(speed_tbl[i].name, name)) { *speed = speed_tbl[i].speed; return 0; } } errno = ENOENT; return -1; }