From 3f97bb7d4eb37bfca97cd630c670ba80310b05fe Mon Sep 17 00:00:00 2001 From: Matt Story Date: Mon, 23 Dec 2024 09:52:57 -0500 Subject: [PATCH] add an option to skip draining on tty close (#105) * add an option to skip draining on tty close When ssh connections to buses are terminated bst is blocking while draining the pty. The signal handler does to run in this case and the process hangs around until the bus is rebooted. Added an option to control whether or not the pty is drained when stdin is closed. The b5c bst invocation will pass --tty=-drain. --- main.c | 1 + man/bst.1.scd | 3 +++ tty.c | 31 +++++++++++++++++++++++-------- tty.h | 1 + 4 files changed, 28 insertions(+), 8 deletions(-) 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;