diff --git a/main.c b/main.c index f3c4fac..f532de2 100644 --- a/main.c +++ b/main.c @@ -789,6 +789,7 @@ int main(int argc, char *argv[], char *envp[]) { opts.tty = 1; opts.ttyopts.ptmx = tty_default_ptmx; + opts.ttyopts.drain = true; /* 128 is enough to support everything */ struct kvlist kvlist[128]; diff --git a/man/bst.1.scd b/man/bst.1.scd index 6195402..f25f1b2 100644 --- a/man/bst.1.scd +++ b/man/bst.1.scd @@ -371,6 +371,9 @@ spacetime process. - *ptmx*=: use the specified ptmx device (relative to the target root) to allocated the pty. + - *drain*: whether to drain the tty on stdin closure. The default is true, + so prepend a _'-'_ to this option to prevent draining. + By default bst inherits the parent's terminal device (or lack thereof). Use the --tty option to allocate a new pty for the child process. diff --git a/tty.c b/tty.c index 2f0237f..61fce81 100644 --- a/tty.c +++ b/tty.c @@ -39,8 +39,10 @@ static struct tty_parent_info_s { int termfd; struct termios orig; bool stdinIsatty; + bool drain; } info = { .termfd = -1, + .drain = true, }; static ssize_t io_copy(int out_fd, int in_fd, struct buffer *buf) @@ -145,15 +147,17 @@ static void tty_parent_resetterm(void) static void tty_parent_drain(void) { - /* Drain any remaining data in the terminal buffer */ - set_nonblock(STDOUT_FILENO, 0); - set_nonblock(info.termfd, 0); - struct buffer drain = { - .size = 0, - }; + if (info.drain) { + /* Drain any remaining data in the terminal buffer */ + set_nonblock(STDOUT_FILENO, 0); + set_nonblock(info.termfd, 0); + struct buffer drain = { + .size = 0, + }; - if (io_copy(STDOUT_FILENO, info.termfd, &drain) == -1 && errno != EIO) { - warn("copy tty -> stdout"); + if (io_copy(STDOUT_FILENO, info.termfd, &drain) == -1 && errno != EIO) { + warn("copy tty -> stdout"); + } } close_null(STDOUT_FILENO); @@ -358,6 +362,8 @@ void tty_parent_setup(struct tty_opts *opts, int epollfd, int socket) struct termios tios; + info.drain = opts->drain; + info.stdinIsatty = tcgetattr(STDIN_FILENO, &tios) == 0; if (!info.stdinIsatty && errno != ENOTTY) { err(1, "tty_parent: tcgetattr"); @@ -656,6 +662,14 @@ static void parse_ptmx(struct tty_opts *opts, const char *key, const char *val, opts->ptmx = val; } +static void parse_drain(struct tty_opts *opts, const char *key, const char *val, const void *cookie) +{ + if (val != NULL) { + errx(2, "tty option '%s' must have no value", key); + } + opts->drain = (key[0] != '-'); +} + static int cmp_flag(const void *key, const void *elem) { return strcmp(key, ((const struct valmap *)elem)->name); @@ -675,6 +689,7 @@ void tty_opt_parse(struct tty_opts *opts, const char *key, const char *val) { "cread", parse_flag, .cookie = &(const struct termios) { .c_cflag = CREAD } }, { "crtscts", parse_flag, .cookie = &(const struct termios) { .c_cflag = CRTSCTS } }, { "cstopb", parse_flag, .cookie = &(const struct termios) { .c_cflag = CSTOPB } }, + { "drain", parse_drain, .cookie = NULL }, { "echo", parse_flag, .cookie = &(const struct termios) { .c_lflag = ECHO } }, { "echoctl", parse_flag, .cookie = &(const struct termios) { .c_lflag = ECHOCTL } }, { "echoe", parse_flag, .cookie = &(const struct termios) { .c_lflag = ECHOE } }, diff --git a/tty.h b/tty.h index aabba80..fc0fc35 100644 --- a/tty.h +++ b/tty.h @@ -15,6 +15,7 @@ struct tty_opts { const char *ptmx; struct termios termios; struct termios neg_termios; + bool drain; }; extern const char *tty_default_ptmx;