static SavedTermiosMode setRawTerminalMode()

in src/unix-adapter/main.cc [73:139]


static SavedTermiosMode setRawTerminalMode(
    bool allowNonTtys, bool setStdout, bool setStderr)
{
    SavedTermiosMode ret;
    const char *const kNames[3] = { "stdin", "stdout", "stderr" };

    ret.valid[0] = true;
    ret.valid[1] = setStdout;
    ret.valid[2] = setStderr;

    for (int i = 0; i < 3; ++i) {
        if (!ret.valid[i]) {
            continue;
        }
        if (!isatty(i)) {
            ret.valid[i] = false;
            if (!allowNonTtys) {
                fprintf(stderr, "%s is not a tty\n", kNames[i]);
                exit(1);
            }
        } else {
            ret.valid[i] = true;
            if (tcgetattr(i, &ret.mode[i]) < 0) {
                perror("tcgetattr failed");
                exit(1);
            }
        }
    }

    if (ret.valid[STDIN_FILENO]) {
        termios buf;
        if (tcgetattr(STDIN_FILENO, &buf) < 0) {
            perror("tcgetattr failed");
            exit(1);
        }
        buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
        buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        buf.c_cflag &= ~(CSIZE | PARENB);
        buf.c_cflag |= CS8;
        buf.c_cc[VMIN] = 1;  // blocking read
        buf.c_cc[VTIME] = 0;
        if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &buf) < 0) {
            fprintf(stderr, "tcsetattr failed\n");
            exit(1);
        }
    }

    for (int i = STDOUT_FILENO; i <= STDERR_FILENO; ++i) {
        if (!ret.valid[i]) {
            continue;
        }
        termios buf;
        if (tcgetattr(i, &buf) < 0) {
            perror("tcgetattr failed");
            exit(1);
        }
        buf.c_cflag &= ~(CSIZE | PARENB);
        buf.c_cflag |= CS8;
        buf.c_oflag &= ~OPOST;
        if (tcsetattr(i, TCSAFLUSH, &buf) < 0) {
            fprintf(stderr, "tcsetattr failed\n");
            exit(1);
        }
    }

    return ret;
}