Before, isatty() was an alias for WinAPI _isatty().
This resulted in wrong result for mintty.

Implement a pipe name check in a static isatty().
This makes io.h include NT and Windows APIs.

The change isn't strictly standard, as it adds
'static' to the isatty() signature.

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
---
v1: moved from v7
v2: edit description

 mingw-w64-headers/crt/io.h | 94 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h
index c61e94ab8743..5e64352df6b4 100644
--- a/mingw-w64-headers/crt/io.h
+++ b/mingw-w64-headers/crt/io.h
@@ -9,6 +9,13 @@
 #include <crtdefs.h>
 #include <string.h>
 
+/* for cygwin-compatible isatty */
+#include <wchar.h>
+#include <errno.h>
+#include <io.h>
+#include <winternl.h>
+#include <windows.h>
+
 #pragma pack(push,_CRT_PACKING)
 
 #ifdef __cplusplus
@@ -322,7 +329,6 @@ _CRTIMP char* __cdecl _getcwd (char*, int);
   int __cdecl dup2(int _FileHandleSrc,int _FileHandleDst) 
__MINGW_ATTRIB_DEPRECATED_MSVC2005;
   int __cdecl eof(int _FileHandle) __MINGW_ATTRIB_DEPRECATED_MSVC2005;
   long __cdecl filelength(int _FileHandle) __MINGW_ATTRIB_DEPRECATED_MSVC2005;
-  int __cdecl isatty(int _FileHandle) __MINGW_ATTRIB_DEPRECATED_MSVC2005;
   int __cdecl locking(int _FileHandle,int _LockMode,long _NumOfBytes) 
__MINGW_ATTRIB_DEPRECATED_MSVC2005;
   long __cdecl lseek(int _FileHandle,long _Offset,int _Origin) 
__MINGW_ATTRIB_DEPRECATED_MSVC2005;
   char *__cdecl mktemp(char *_TemplateName)  
__MINGW_ATTRIB_DEPRECATED_MSVC2005;
@@ -335,6 +341,92 @@ _CRTIMP char* __cdecl _getcwd (char*, int);
   int __cdecl write(int _Filehandle,const void *_Buf,unsigned int 
_MaxCharCount) __MINGW_ATTRIB_DEPRECATED_MSVC2005;
 #endif
 
+static int __cdecl isatty(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;
+}
+
 #ifndef _FILE_OFFSET_BITS_SET_LSEEK
 #define _FILE_OFFSET_BITS_SET_LSEEK
 #if (defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64))
-- 
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