Skip to content

Commit b2cbfdc

Browse files
committed
Support TTY detection without ext-posix
1 parent c4e17d7 commit b2cbfdc

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

src/Stdin.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Clue\React\Stdio;
44

5-
use React\Stream\ReadableStream;
65
use React\Stream\Stream;
76
use React\EventLoop\LoopInterface;
87

@@ -43,8 +42,35 @@ private function restore()
4342
}
4443
}
4544

45+
/**
46+
* @return bool
47+
* @codeCoverageIgnore
48+
*/
4649
private function isTty()
4750
{
48-
return (is_resource(STDIN) && function_exists('posix_isatty') && posix_isatty(STDIN));
51+
if (PHP_VERSION_ID >= 70200) {
52+
// Prefer `stream_isatty()` (available as of PHP 7.2 only)
53+
return stream_isatty(STDIN);
54+
} elseif (function_exists('posix_isatty')) {
55+
// Otherwise use `posix_isatty` if available (requires `ext-posix`)
56+
return posix_isatty(STDIN);
57+
}
58+
59+
// otherwise try to guess based on stat file mode and device major number
60+
// Must be special character device: ($mode & S_IFMT) === S_IFCHR
61+
// And device major number must be allocated to TTYs (2-5 and 128-143)
62+
// For what it's worth, checking for device gid 5 (tty) is less reliable.
63+
// @link http://man7.org/linux/man-pages/man7/inode.7.html
64+
// @link https://www.kernel.org/doc/html/v4.11/admin-guide/devices.html#terminal-devices
65+
if (is_resource(STDIN)) {
66+
$stat = fstat(STDIN);
67+
$mode = isset($stat['mode']) ? ($stat['mode'] & 0170000) : 0;
68+
$major = isset($stat['dev']) ? (($stat['dev'] >> 8) & 0xff) : 0;
69+
70+
if ($mode === 0020000 && $major >= 2 && $major <= 143 && ($major <=5 || $major >= 128)) {
71+
return true;
72+
}
73+
}
74+
return false;
4975
}
5076
}

0 commit comments

Comments
 (0)