From 5f1ac8ee360813e91821adfe845123e27e2c43e2 Mon Sep 17 00:00:00 2001 From: Kevin Adler Date: Tue, 24 Mar 2020 11:32:51 -0500 Subject: [PATCH] ibmi: Fix isatty EBADF handling and refactor In e14c56b, support was added to implement true isatty() support when running in the IBM i PASE environment, but it did not handle EBADF properly. This commit fixes the EBADF handling, but because the handling was a bit more complicated than previously, it was moved to a separate isatty function to keep the mainline code simpler. This also documents why we can't just use isatty on PASE a little more completely. PR-URL: https://github.com/libuv/libuv/pull/2753 Reviewed-By: Ben Noordhuis Reviewed-By: Richard Lau --- src/unix/tty.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/unix/tty.c b/src/unix/tty.c index ff7d3b17..6f60abaa 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -34,6 +34,34 @@ #define IMAXBEL 0 #endif +#if defined(__PASE__) +/* On IBM i PASE, for better compatibility with running interactive programs in + * a 5250 environment, isatty() will return true for the stdin/stdout/stderr + * streams created by QSH/QP2TERM. + * + * For more, see docs on PASE_STDIO_ISATTY in + * https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/apis/pase_environ.htm + * + * This behavior causes problems for Node as it expects that if isatty() returns + * true that TTY ioctls will be supported by that fd (which is not an + * unreasonable expectation) and when they don't it crashes with assertion + * errors. + * + * Here, we create our own version of isatty() that uses ioctl() to identify + * whether the fd is *really* a TTY or not. + */ +static int isreallyatty(int file) { + int rc; + + rc = !ioctl(file, TXISATTY + 0x81, NULL); + if (!rc && errno != EBADF) + errno = ENOTTY; + + return rc; +} +#define isatty(fd) isreallyatty(fd) +#endif + static int orig_termios_fd = -1; static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; @@ -293,14 +321,7 @@ uv_handle_type uv_guess_handle(uv_file file) { if (file < 0) return UV_UNKNOWN_HANDLE; -#if defined(__PASE__) - /* On IBMi PASE isatty() always returns true for stdin, stdout and stderr. - * Use ioctl() instead to identify whether it's actually a TTY. - */ - if (!ioctl(file, TXISATTY + 0x81, NULL) || errno != ENOTTY) -#else if (isatty(file)) -#endif return UV_TTY; if (fstat(file, &s))