Applications now could call iscygtty(STDIN_FILENO)
in order to detect whether they are running from
Cygwin/MSys terminal.

Without that, they have no choice but to think that
stdin is redirected from a named pipe.

Signed-off-by: Mihail Konev <k....@ya.ru>
Moved-from: https://github.com/Alexpux/mingw-w64/pull/3
Adapted-from: https://cygwin.com/ml/cygwin-developers/2016-11/msg00002.html
---
v7:
- set errno if returning false
- do not depend on ntdll.dll being linked, use GetProcAddress
- stricter name check
- act as cygwin.dll isatty()
  I.e. is-it-mintty-or-cmd?
  To get the previous is-it-mintty? behaviour, just omit the "if (_isatty)".

The is-it-mintty? is actually a leftover from initial example;
the "real" version could as well aggressively alias the stanard api
(especially given that applications could still call the is-it-cmd? _isatty() 
if they want to).

Don't know how to make it a substitute for isatty(), through.
Putting this into io.h results in implicit declarations and errors.

Should all used types be declared locally in the function,
or headers be rearranged (but how?)?

Also typedef proc_NtQueryObject could be broken in some compiler; should
it not be used?

This function is intended for:
- "mingw64-" Cygwin packages
- "mingw-w64-" MSYS packages
Both should be built using mingw-w64 toolchain, and currenly have isatty() 
being _isatty().

 mingw-w64-headers/include/iscygtty.c | 96 ++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100644 mingw-w64-headers/include/iscygtty.c

diff --git a/mingw-w64-headers/include/iscygtty.c 
b/mingw-w64-headers/include/iscygtty.c
new file mode 100644
index 000000000000..1c7a394d965b
--- /dev/null
+++ b/mingw-w64-headers/include/iscygtty.c
@@ -0,0 +1,96 @@
+#ifndef __ISCYGTTY_C__
+#define __ISCYGTTY_C__
+
+#include <io.h>
+#include <winternl.h>
+
+#include <wchar.h>
+#include <windows.h>
+
+static int iscygtty(int fd) {
+    typedef NTSTATUS (NTAPI proc_NtQueryObject) (HANDLE, 
OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+    proc_NtQueryObject *pNtQueryObject;
+
+    HANDLE h_fd;
+
+    /* NtQueryObject needs space for OBJECT_NAME_INFORMATION.Name->Buffer 
also. */
+    char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * 
sizeof(WCHAR)];
+
+    OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes;
+    NTSTATUS status;
+    ULONG ntfn_size = sizeof(ntfn_bytes);
+
+    wchar_t c, *s;
+    USHORT i;
+
+    h_fd = (HANDLE) _get_osfhandle(fd);
+    if (!h_fd || h_fd == INVALID_HANDLE_VALUE) {
+        errno = EBADF;
+        return 0;
+    }
+
+    pNtQueryObject = (proc_NtQueryObject*) 
GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryObject");
+    if (!pNtQueryObject)
+        goto no_tty;
+
+    memset(ntfn, 0, ntfn_size);
+    status = pNtQueryObject((HANDLE)h_fd, ObjectNameInformation,
+            ntfn, ntfn_size, &ntfn_size);
+
+    if (!NT_SUCCESS(status)) {
+        /* If it is not NUL (i.e. \Device\Null, which would succeed),
+         * then normal isatty() could be consulted.
+         * */
+        if (_isatty(fd))
+            return 1;
+        goto no_tty;
+    }
+
+    s = ntfn->Name.Buffer;
+    s[ntfn->Name.Length / sizeof(WCHAR)] = 0;
+
+    /* Look for 
\Device\NamedPipe\(cygwin|msys)-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg)
 */
+
+    if (wcsncmp(s, L"\\Device\\NamedPipe\\", 18))
+        goto no_tty;
+    s += 18;
+
+    if (!wcsncmp(s, L"cygwin-", 7))
+        s += 7;
+    else if (!wcsncmp(s, L"msys-", 5))
+        s += 5;
+    else
+        goto no_tty;
+
+    for (i = 0; i < 16; i++) {
+        c = *s++;
+        if (!( (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' 
&& c <= '9') ))
+            goto no_tty;
+    }
+
+    if (wcsncmp(s, L"-pty", 4))
+        goto no_tty;
+    s += 4;
+
+    for (i = 0; i < 4; i++, s++) {
+        c = *s;
+        if (!( c >= '0' && c <= '9' ))
+            break;
+    }
+
+    if (i == 0)
+        goto no_tty;
+
+    if (wcscmp(s, L"-from-master") &&
+            wcscmp(s, L"-to-master") &&
+            wcscmp(s, L"-to-master-cyg"))
+        goto no_tty;
+
+    return 1;
+
+no_tty:
+    errno = EINVAL;
+    return 0;
+}
+
+#endif /* __ISCYGTTY_C__ */
-- 
2.9.2


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to