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 <info@bnoordhuis.nl>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
Kevin Adler 2020-03-24 11:32:51 -05:00 committed by Richard Lau
parent 0ed9692a80
commit 5f1ac8ee36
No known key found for this signature in database
GPG Key ID: C43CEC45C17AB93C

View File

@ -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))