Re: [Mingw-w64-public] [PATCH v11] crt: Recognize cygwin ptys in isatty
On Thu, Jan 19, 2017 at 12:54:33AM +0500, Mihail Konev wrote: > On Sat, Jan 07, 2017 at 10:52:40AM +0500, Mihail Konev wrote: > > Signed-off-by: Mihail Konev <k@ya.ru> > > Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 > > Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html > > --- > > v11: const the exported isatty > > > > mingw-w64-crt/Makefile.am | 1 + > > mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- > > mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- > > mingw-w64-crt/stdio/isatty.c | 111 > > + > > mingw-w64-headers/crt/io.h | 1 + > > 5 files changed, 115 insertions(+), 2 deletions(-) > > create mode 100644 mingw-w64-crt/stdio/isatty.c > > > > Maybe making Cygwin present Win32 applications with a Windows Console > (which mirrors pty stdout and drives pty stdin) would be more correct > (as it allows smoother interoperability)? > That is, this should be solvable without having to touch MinGW. (By instead improving winpty and/or its support on Cygwin/MSYS). -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH v11] crt: Recognize cygwin ptys in isatty
On Sat, Jan 07, 2017 at 10:52:40AM +0500, Mihail Konev wrote: > Signed-off-by: Mihail Konev <k@ya.ru> > Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 > Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html > --- > v11: const the exported isatty > > mingw-w64-crt/Makefile.am | 1 + > mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- > mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- > mingw-w64-crt/stdio/isatty.c | 111 > + > mingw-w64-headers/crt/io.h | 1 + > 5 files changed, 115 insertions(+), 2 deletions(-) > create mode 100644 mingw-w64-crt/stdio/isatty.c > Maybe making Cygwin present Win32 applications with a Windows Console (which mirrors pty stdout and drives pty stdin) would be more correct (as it allows smoother interoperability)? -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] [PATCH v11] crt: Recognize cygwin ptys in isatty
Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v11: const the exported isatty mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 111 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..00c0467b5437 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +;isatty ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..3a15de703762 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +;isatty itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..126cfefc0dd4 --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +int __cdecl (* const __MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + const wchar_t expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + const wchar_t expect_pty[] = L"-pty"; + + typedef NTSTATUS (NTAPI proc_NtQueryObject) (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG); + proc_NtQueryObject *pNtQueryObject; + + HANDLE h_fd, h_ntdll; + + /* 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 *s; + int l; + + h_fd = (HANDLE) _get_osfhandle(fd); + if (!h_fd || h_fd == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + h_ntdll = GetModuleHandle("ntdll.dll"); + if (!h_ntdll || h_ntdll == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + pNtQueryObject = (proc_NtQueryObject*) GetProcAddress(h_ntdll, "NtQueryObject"); + if (!pNtQueryObject) { +goto no_tty; + } + + memset(ntfn, 0, ntfn_size); + status = pNtQueryObject((HANDLE)h_fd, ObjectNameInformation, + ntfn, ntfn_size, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no_tty: + errno = EINVAL; + return 0; +} diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..97b26762f831 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -191,6 +191,7 @@ _CRTIMP char* __cdecl _getcwd (char*, int); _CR
Re: [Mingw-w64-public] [PATCH v10] crt: Recognize cygwin ptys in isatty
On Sat, Dec 10, 2016 at 05:30:32AM +0500, Mihail Konev wrote: > > mingw-w64-crt/Makefile.am | 1 + > mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- > mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- > mingw-w64-crt/stdio/isatty.c | 111 > + > mingw-w64-headers/crt/io.h | 1 + > 5 files changed, 115 insertions(+), 2 deletions(-) > create mode 100644 mingw-w64-crt/stdio/isatty.c > > +/* Cygwin-compatible isatty. > Ping. Test program and makefile below: --- main.c #include #include int main(int argc, char **argv) { printf("isatty(): %s\n", isatty(STDIN_FILENO) ? "yes" : "no"); return 0; } --- Makefile # Run this from Cygwin/MSYS shell all: test a.exe: main.c $(CC) -Wall -Wextra main.c test: a.exe @echo @echo " -- Test not a tty --" @echo ls | ./a.exe @echo @echo " -- Test a cygwin pty --" @echo ./a.exe @echo @echo " -- Test a named pipe --" @echo @rm .named_pipe 2>/dev/null || true mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe @echo @echo " -- Test a cmd.exe --" @echo echo "a.exe" | cmd @echo @echo @echo " -- Test cmd.exe console --" @echo start //wait //min cmd //c "a.exe > .con_out" @cat .con_out @rm .con_out @echo @echo " -- Test /dev/null --" @echo ./a.exe < /dev/null @echo @echo @echo " -- Test cmd.exe NUL --" @echo ./a.exe < //NUL @echo clean: rm a.exe 2>/dev/null || true -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] [PATCH v10] crt: Recognize cygwin ptys in isatty
Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v8-v10: Change comment-outs in def files. Error-check GetModuleHandle. Edit description. mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 111 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..00c0467b5437 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +;isatty ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..3a15de703762 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +;isatty itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..bf940d6f225f --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + typedef NTSTATUS (NTAPI proc_NtQueryObject) (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG); + proc_NtQueryObject *pNtQueryObject; + + HANDLE h_fd, h_ntdll; + + /* 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 *s; + int l; + + h_fd = (HANDLE) _get_osfhandle(fd); + if (!h_fd || h_fd == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + h_ntdll = GetModuleHandle("ntdll.dll"); + if (!h_ntdll || h_ntdll == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + pNtQueryObject = (proc_NtQueryObject*) GetProcAddress(h_ntdll, "NtQueryObject"); + if (!pNtQueryObject) { +goto no_tty; + } + + memset(ntfn, 0, ntfn_size); + status = pNtQueryObject((HANDLE)h_fd, ObjectNameInformation, + ntfn, ntfn_size, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no_tty: + errno = EINVAL; + return 0; +} diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..97b26762f831 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -191,6 +19
[Mingw-w64-public] [PATCH] Fix typos for -DCOMPILE_MULTIMON_STUBS
>From 6918551906f65025b008e17398982e0352038a84 Mon Sep 17 00:00:00 2001 From: Mario Kleiner <mario.kleiner...@gmail.com> Date: Tue, 22 Nov 2016 03:35:56 +0100 Subject: [PATCH] Fix typos for -DCOMPILE_MULTIMON_STUBS Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/4/ --- mingw-w64-headers/include/multimon.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mingw-w64-headers/include/multimon.h b/mingw-w64-headers/include/multimon.h index 1aefb104dc48..e025915b81cb 100644 --- a/mingw-w64-headers/include/multimon.h +++ b/mingw-w64-headers/include/multimon.h @@ -127,7 +127,7 @@ extern "C" { WINBOOL IsPlatformNT() { OSVERSIONINFOA oi = { 0 }; -oi.dwOSVersionInfoSize = sizeof (osvi); +oi.dwOSVersionInfoSize = sizeof (oi); GetVersionExA ((OSVERSIONINFOA *) ); return (oi.dwPlatformId == VER_PLATFORM_WIN32_NT); } @@ -241,7 +241,7 @@ extern "C" { f = g_pfnGetMonitorInfo (hmon, pmi); #ifdef UNICODE if (f && !g_fMultimonPlatformNT && pmi->cbSize >= sizeof (MONITORINFOEX)) - MultiByteToWideChar (CP_ACP, 0, (LPSTR) c.ex->szDevice, -1, c.ex->szDevice, (sizeof (c.ex->szDevice) / 2)); + MultiByteToWideChar (CP_ACP, 0, (LPSTR) c.ex.szDevice, -1, c.ex.szDevice, (sizeof (c.ex.szDevice) / 2)); #endif return f; } @@ -255,9 +255,9 @@ extern "C" { pmi->dwFlags = MONITORINFOF_PRIMARY; if (pmi->cbSize >= sizeof (MONITORINFOEX)) { #ifdef UNICODE - MultiByteToWideChar (CP_ACP, 0, "DISPLAY", -1, c.ex->szDevice, (sizeof (c.ex->szDevice) / 2)); + MultiByteToWideChar (CP_ACP, 0, "DISPLAY", -1, c.ex.szDevice, (sizeof (c.ex.szDevice) / 2)); #else - lstrcpyn (c.ex->szDevice, "DISPLAY", sizeof (c.ex->szDevice)); + lstrcpyn (c.ex.szDevice, "DISPLAY", sizeof (c.ex.szDevice)); #endif } -- 2.9.2 -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] [PATCH v9] Make isatty Cygwin-compatible
Before, isatty() was an alias for WinAPI _isatty(). This resulted in wrong result for mintty. Implement pipe name check in crt isatty(). Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 111 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..44ebccb49d46 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +; isatty replaced for cygwin ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..30b45c3a71ca 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +; isatty replaced for cygwin itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..bf940d6f225f --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + typedef NTSTATUS (NTAPI proc_NtQueryObject) (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG); + proc_NtQueryObject *pNtQueryObject; + + HANDLE h_fd, h_ntdll; + + /* 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 *s; + int l; + + h_fd = (HANDLE) _get_osfhandle(fd); + if (!h_fd || h_fd == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + h_ntdll = GetModuleHandle("ntdll.dll"); + if (!h_ntdll || h_ntdll == INVALID_HANDLE_VALUE) { +errno = EBADF; +return 0; + } + + pNtQueryObject = (proc_NtQueryObject*) GetProcAddress(h_ntdll, "NtQueryObject"); + if (!pNtQueryObject) { +goto no_tty; + } + + memset(ntfn, 0, ntfn_size); + status = pNtQueryObject((HANDLE)h_fd, ObjectNameInformation, + ntfn, ntfn_size, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no_tty: + errno = EINVAL; + return 0; +} diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..97b26762f831 100644
[Mingw-w64-public] [PATCH v8] Make isatty Cygwin-compatible
Before, isatty() was an alias for WinAPI _isatty(). This resulted in wrong result for mintty. Implement pipe name check in crt isatty(). Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v8: fix missing _CRTIMP __cdecl in io.h isatty() declaration mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 105 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..d14a8c9c3639 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +; isatty) ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..30b45c3a71ca 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +; isatty replaced for cygwin itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..05cd83944b53 --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + 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 *s; + int l; + + 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, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no_tty: + errno = EINVAL; + return 0; +} diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..97b26762f831 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -191,6 +19
[Mingw-w64-public] [PATCH v7] Make isatty Cygwin-compatible
Before, isatty() was an alias for WinAPI _isatty(). This resulted in wrong result for mintty. Implement pipe name check in crt isatty(). Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v7: remove debug print mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 105 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..d14a8c9c3639 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +; isatty) ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..30b45c3a71ca 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +; isatty replaced for cygwin itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..05cd83944b53 --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + 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 *s; + int l; + + 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, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no_tty: + errno = EINVAL; + return 0; +} diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..c33a24c0f5ea 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -191,6 +191,7 @@ _CRTIMP char* __cdecl _getcwd
Re: [Mingw-w64-public] [PATCH v6] Make isatty Cygwin-compatible
On Fri, Nov 18, 2016 at 08:37:33AM +0500, Mihail Konev wrote: > > all: test > > a.exe: main.c > $(CC) -Wall -Wextra main.c > > test: a.exe > @echo > @echo " -- Test not a tty --" > @echo Sorry, forgot 'all: clean test'. But ran it manually prior anyway. -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] [PATCH v6] Make isatty Cygwin-compatible
Before, isatty() was an alias for WinAPI _isatty(). This resulted in wrong result for mintty. Implement pipe name check in crt isatty(). Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v5 was not working because autoreconf results were overwritten by subsequent git reset --hard. v6: - remove unused variable Test: u@PC MINGW64 ~ $ cd isatty u@PC MINGW64 ~/isatty $ ls a.exe main.c Makefile u@PC MINGW64 ~/isatty $ cat Makefile CC = /mingw64/bin/gcc all: test a.exe: main.c $(CC) -Wall -Wextra main.c test: a.exe @echo @echo " -- Test not a tty --" @echo ls | ./a.exe @echo @echo " -- Test a tty --" @echo ./a.exe @echo @echo " -- Test a named pipe --" @echo @rm .named_pipe 2>/dev/null || true mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe @echo @echo " -- Test a cmd.exe --" @echo echo "a.exe" | cmd @echo @echo @echo " -- Test a console --" @echo start //wait //min cmd //c "a.exe > .con_out" @cat .con_out @rm .con_out @echo @echo " -- Test /dev/null --" @echo ./a.exe < /dev/null @echo @echo @echo " -- Test NUL --" @echo ./a.exe < //NUL @echo clean: rm a.exe 2>/dev/null || true u@PC MINGW64 ~/isatty $ cat main.c #include #include int main(int argc, char **argv) { printf("isatty(): %s\n", isatty(STDIN_FILENO) ? "yes" : "no"); printf("_isatty(): %s\n", _isatty(STDIN_FILENO) ? "yes" : "no"); return 0; } u@PC MINGW64 ~/isatty $ make -- Test not a tty -- ls | ./a.exe isatty-ing 0 isatty(): no _isatty(): no -- Test a tty -- ./a.exe isatty-ing 0 isatty(): yes _isatty(): no -- Test a named pipe -- mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe isatty-ing 0 isatty(): no _isatty(): no -- Test a cmd.exe -- echo "a.exe" | cmd Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. J:\msys_dev\home\u\isatty>a.exe isatty-ing 0 isatty(): no _isatty(): no J:\msys_dev\home\u\isatty> -- Test a console -- start //wait //min cmd //c "a.exe > .con_out" isatty-ing 0 isatty(): yes _isatty(): yes -- Test /dev/null -- ./a.exe < /dev/null isatty-ing 0 isatty(): no _isatty(): yes -- Test NUL -- ./a.exe < //NUL isatty-ing 0 isatty(): no _isatty(): yes u@PC MINGW64 ~/isatty $ mingw-w64-crt/Makefile.am | 1 + mingw-w64-crt/def-include/msvcrt-common.def.in | 2 +- mingw-w64-crt/lib64/moldname-msvcrt.def| 2 +- mingw-w64-crt/stdio/isatty.c | 110 + mingw-w64-headers/crt/io.h | 1 + 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/isatty.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0c..49f7f58 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa3..d14a8c9 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +; isatty) ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518..30b45c3 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +; isatty replaced for cygwin itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index 000..734b8ec --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +/* testing only */ +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Devic
Re: [Mingw-w64-public] [PATCH v4] Make isatty Cygwin-compatible
Aside from the patch, with crt build directory located next to mingw-w64/, 'make' does not trigger a partial rebuild upon editing stdio/isatty.c: make all-am Entering dir ... Leaving dir ... So 'make distclean && ../mingw-w64/mingw-w64-crt/configure ... && make && make install' must be performed. Should be a makefile bug. This gives undefined reference to 'isatty' when compiling hello-isatty program: Commenting all _isatty-s except ADD_UNDERSCORE one gives msvcrt _isatty being called. commit a0e3a797e29638803a8ff9b621e9ba5f6f12c1b8 Author: Mihail Konev <k@ya.ru> Date: Tue Nov 15 09:12:37 2016 +0500 Make isatty Cygwin-compatible Before, isatty() was an alias for WinAPI _isatty(). This resulted in wrong result for mintty. Implement pipe name check in crt isatty(). Signed-off-by: Mihail Konev <k@ya.ru> Moved-from: https://github.com/Alexpux/mingw-w64/pull/3 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 581af0cc5811..49f7f58289c7 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -211,6 +211,7 @@ src_msvcrt=\ secapi/vsprintf_s.c \ secapi/wmemcpy_s.c \ secapi/wmemmove_s.c \ + stdio/isatty.c \ stdio/mingw_lock.c src_msvcrt32=\ diff --git a/mingw-w64-crt/def-include/msvcrt-common.def.in b/mingw-w64-crt/def-include/msvcrt-common.def.in index 76e1fa37e8b2..d14a8c9c3639 100644 --- a/mingw-w64-crt/def-include/msvcrt-common.def.in +++ b/mingw-w64-crt/def-include/msvcrt-common.def.in @@ -47,7 +47,7 @@ ADD_UNDERSCORE(getcwd) ADD_UNDERSCORE(getpid) ADD_UNDERSCORE(getw) ADD_UNDERSCORE(heapwalk) -ADD_UNDERSCORE(isatty) +; isatty) ADD_UNDERSCORE(itoa) ADD_UNDERSCORE(kbhit) ADD_UNDERSCORE(lfind) diff --git a/mingw-w64-crt/lib64/moldname-msvcrt.def b/mingw-w64-crt/lib64/moldname-msvcrt.def index 6f31518d5c82..30b45c3a71ca 100644 --- a/mingw-w64-crt/lib64/moldname-msvcrt.def +++ b/mingw-w64-crt/lib64/moldname-msvcrt.def @@ -64,7 +64,7 @@ getcwd getpid getw heapwalk -isatty +; isatty replaced for cygwin itoa kbhit lfind diff --git a/mingw-w64-crt/stdio/isatty.c b/mingw-w64-crt/stdio/isatty.c new file mode 100644 index ..df4cacf19c82 --- /dev/null +++ b/mingw-w64-crt/stdio/isatty.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +/* testing only */ +#include + +int __cdecl (*__MINGW_IMP_SYMBOL(isatty))(int) = isatty; + +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + printf("isatty-ing %d\n", 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; + int l; + + 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, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +w
[Mingw-w64-public] [PATCH v4] Make isatty Cygwin-compatible
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 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v4: - do not check for msys-* pipe name - fix typos This would only work for MSYS once it is patched to revert pipe names. mingw-w64-headers/crt/io.h | 105 - 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..9fa776c8c9b1 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -9,6 +9,12 @@ #include #include +/* for cygwin-compatible isatty */ +#include +#include +#include +#include + #pragma pack(push,_CRT_PACKING) #ifdef __cplusplus @@ -322,7 +328,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 +340,104 @@ _CRTIMP char* __cdecl _getcwd (char*, int); int __cdecl write(int _Filehandle,const void *_Buf,unsigned int _MaxCharCount) __MINGW_ATTRIB_DEPRECATED_MSVC2005; #endif +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch [absolute] fd's NT object path (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\cygwin-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +static int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\cygwin-"; + wchar_t const expect_pty[] = L"-pty"; + + 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; + int l; + + 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, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +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 -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH v3] Make isatty Cygwin-compatible
On Sun, Nov 13, 2016 at 09:44:49PM +0100, Corinna Vinschen wrote: > On Nov 14 00:31, Mihail Konev wrote: > > I'm opposed to checking the pipes for *-msys-* additionally to > *-cygwin-* for no good reason. You're adding just another test to the > checking code and potentially introduce hard to track down backward > incompatibilities. There's really no gain for MSYS2 to rename the > pipes, except breaking interoperability, so hopefully this will never > happen anyway. > Do you want MSYS to rename the pipes back? https://github.com/Alexpux/MSYS2-packages/search?utf8=%E2%9C%93=PIPE_INTRO Because of msys runtime 2.5.2-2, it is a necessity. -- 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
[Mingw-w64-public] [PATCH v3] Make isatty Cygwin-compatible
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 Reference: https://cygwin.com/ml/cygwin-developers/2016-11/msg2.html --- v3: - use wide strlen + const strings - brace one-line if branches - describe the function mingw-w64-headers/crt/io.h | 127 - 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/mingw-w64-headers/crt/io.h b/mingw-w64-headers/crt/io.h index c61e94ab8743..0376a4ff596d 100644 --- a/mingw-w64-headers/crt/io.h +++ b/mingw-w64-headers/crt/io.h @@ -9,6 +9,13 @@ #include #include +/* for cygwin-compatible isatty */ +#include +#include +#include +#include +#include + #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,125 @@ _CRTIMP char* __cdecl _getcwd (char*, int); int __cdecl write(int _Filehandle,const void *_Buf,unsigned int _MaxCharCount) __MINGW_ATTRIB_DEPRECATED_MSVC2005; #endif +/* Cygwin-compatible isatty. + * + * Cygwin pty is a specially-named named pipe. + * Fetch absolute device namespace path to fd (if any), + * and check it for the following pattern: + * + * \Device\NamedPipe\(cygwin|msys)-[a-fA-F0-9]{16}-pty[0-9]{1,4}-(from-master|to-master|to-master-cyg) + * + * [a-fA-F0-9] is the cygwin installation key, 16 characters long. + * pty[0-9] is the pty name. Its index is of type int, but is safe to be limited to 4 characters. + * + * */ + +static int __cdecl isatty(int fd) { + wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\"; + wchar_t const expect_cyg[] = L"cygwin-"; + wchar_t const expect_msy[] = L"msys-"; + wchar_t const expect_pty[] = L"-pty"; + wchar_t const expect_tmr[] = L"-to-master"; + wchar_t const expect_fmc[] = L"-to-master-cyg"; + wchar_t const expect_fmr[] = L"-from-master"; + + 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; + int l; + + 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, _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; + + l = wcslen(expect_dev); + if (wcsncmp(s, expect_dev, l) != 0) { +goto no_tty; + } + s += l; + + do { +l = wcslen(expect_cyg); +if (wcsncmp(s, expect_cyg, l) == 0) { + s += l; + break; +} + +l = wcslen(expect_msy); +if (wcsncmp(s, expect_msy, l) == 0) { + s += l; + break; +} + +goto no_tty; + } while (0); + + l = wcsspn(s, L"0123456789abcdefABCDEF"); + if (l != 16) { +goto no_tty; + } + s += l; + + l = wcslen(expect_pty); + if (wcsncmp(s, expect_pty, l) != 0) { +goto no_tty; + } + s += l; + + l = wcsspn(s, L"0123456789"); + if (l < 1 || l > 4) { +goto no_tty; + } + s += l; + + if (wcscmp(s, L"-from-master") != 0 && +wcscmp(s, L"-to-master") != 0 && +wcscmp(s, L"-to-master-cyg") != 0) + { +goto no_tty; + } + + return 1; + +no
[Mingw-w64-public] [PATCH v2] Make isatty Cygwin-compatible
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/msg2.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 #include +/* for cygwin-compatible isatty */ +#include +#include +#include +#include +#include + #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, _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
[Mingw-w64-public] [PATCH] Make isatty Cygwin-compatible
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 wchar.h, errno.h, io.h, winternl.h, and windows.h. 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/msg2.html --- 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 #include +/* for cygwin-compatible isatty */ +#include +#include +#include +#include +#include + #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, _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
Re: [Mingw-w64-public] [PATCH v7] Add include/iscygtty.c
On Sun, Nov 13, 2016 at 07:16:01AM +0100, Vincent Torri wrote: > i still don't understand why not using GetConsoleMode() and see if it > fails or not. > > if it fails : redirection is done with named pipes Redirection is then done, but is it a file or mintty stdin ? > if not : it's standard win32 I/O The CMD.exe console stdin. > > it's simple and works in my tests (DOS console, MSYS1, mintty, MSYS2 > and cygwin terminal >= 1.8) > This must be the same as standard _isatty(), except not returning true for NUL or /dev/null. -- 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
[Mingw-w64-public] [PATCH v7] Add include/iscygtty.c
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/msg2.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 ..1c7a394d965b --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,96 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +#include +#include + +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, _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
Re: [Mingw-w64-public] [PATCH v2] Add include/iscygtty.c
On Sat, Nov 12, 2016 at 12:06:02PM +0500, Mihail Konev wrote: > > Doing it through shared memory should be depenedent on cygwin headers > (if reliable at all for not-a-cygwin-process-child). > Oh. We *are* cygwin-fork()-ed if running from a mintty ;) But still this should be more cygwin-dependent than a name check. (Althrough perhaps not NT-dependent ... ). -- 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
[Mingw-w64-public] [PATCH v6] Add include/iscygtty.c
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 --- v6: - use wide string functions - flatten variable scopes - const the strings (was it a security issue :?) - do not use wchar.h Maybe io.h or winternl.h include this mingw-w64-headers/include/iscygtty.c | 80 1 file changed, 80 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 ..28be38a56bb5 --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,80 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +wchar_t const expect_dev[] = L"\\Device\\NamedPipe\\"; +wchar_t const expect_frm[] = L"-from-master"; +wchar_t const expect_pty[] = L"pty"; + +intptr_t h_fd = _get_osfhandle(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); + +USHORT i, l, l1, part; +wchar_t c, *s; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +l1 = wcslen(expect_dev); +if (wcsncmp(s, expect_dev, l1)) +return 0; +s += l1; + +/* Look for "[a-z0-9]+-[a-z0-9]+-pty[0-9]+-from-master" */ +part = 0; +for (i = 0; i < l; i++) { +c = s[i]; + +if (!c) +break; + +if (c == L'-') { +part++; + +/* Look for -pty%d-from-master */ +if (part == 2) { +s += i + 1; + +l1 = wcslen(expect_pty); +if (wcsncmp(s, expect_pty, l1)) +return 0; + +s += l1; +c = *s; +if (!(c >= L'0' && c <= L'9')) +return 0; + +while ((c = *s) && (c >= L'0') && (c <= L'9')) +s++; + +if (wcsncmp(s, expect_frm, wcslen(expect_frm))) +return 0; + +return 1; +} +} else if (!(c >= L'a' && c <= L'z') && !(c >= L'0' && c <= L'9')) { +return 0; +} +} + +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
Re: [Mingw-w64-public] [PATCH v2] Add include/iscygtty.c
On Sat, Nov 12, 2016 at 06:34:54AM +0500, Mihail Konev wrote: > On Fri, Nov 11, 2016 at 11:19:45AM -0500, Earnie wrote: > > On 11/10/2016 5:43 PM, Mihail Konev wrote: > > > Applications now could call iscygtty(STDIN_FILENO) > > > in order to detect whether they are running from > > > Cygwin/MSys terminal. > > > > > > > Should this be shared with Cygwin so that a similar function exists in > > its C API? > > > It would then be an alias to isatty(). > > But for cygwin.dll (or msys.dll) support headers, the call is just irrelevant. > If it was a misinterpretation, then: Cygwin maintains a shared memory area for all (its) processes, which is used to store tty handles or something. Its isatty() should, in the end, use this information to work the way it does (returns non-zero only for cmd and mintty). The isatty actually calls a const method on a virtual stdin wrapper class ... and it is which-class-to-construct that should determined by the shared memory area info ... Doing it through shared memory should be depenedent on cygwin headers (if reliable at all for not-a-cygwin-process-child). -- 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
[Mingw-w64-public] [PATCH v5] Add include/iscygtty.c
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 --- v5: - stricter check (follows cygwin tty.cc) - drop \\?\, as the name shouldn't be long mingw-w64-headers/include/iscygtty.c | 104 +++ 1 file changed, 104 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 ..1fbd8a6cba3d --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,104 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +for (i = 0; i < l; i++) { +wchar_t e = expect[i]; +c = s0[i]; +if (!e) +break; +if (c != e) { +return 0; +} +} + +l -= i; +s0 += i; +} + +/* Look for "[a-z0-9]+-[a-z0-9]+-pty[0-9]+-from-master" */ +{ +int part = 0; + +for (i = 0; i < l; i++) { +c = s0[i]; + +if (!c) +break; + +if (c == L'-') { +part++; + +/* handle -pty%d- */ +if (part == 2) { +wchar_t *s = s0 + i + 1; + +if (s[0] == L'p' && s[1] == L't' && s[2] == L'y' && +(c = s[3]) && (c >= L'0') && (c <= L'9')) +{ +s += 4; +while ((c = *s) && (c >= L'0') && (c <= L'9')) +s++; +if (c != L'-') { +return 0; +} +part++; + +{ +wchar_t expect[] = L"-from-master"; +int j; + +j = 0; +while (1) { +wchar_t e = expect[j]; +c = s[j]; +if (!e) { +return 1; +} +if (c != e) { +return 0; +} +j++; +} +} +} else { +return 0; +} +} +} else if (!(c >= L'a' && c <= L'z') && !(c >= L'0' && c <= L'9')) { +return 0; +} +} +} + +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
[Mingw-w64-public] [PATCH v4] Add include/iscygtty.c
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 --- Sorry, the v3 "\\.\" check is incorrect. A \\.\pipe\*-pty%d-* should be looked for, not the \\?\Device\NamedPipe\*-pty%d-* . Reverted the change, as the old way, it still works. mingw-w64-headers/include/iscygtty.c | 69 1 file changed, 69 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 ..51e8b0e7319b --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,69 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +USHORT l1 = l; +wchar_t *s1 = s0; +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +if (s0[0] == L'\\' && s0[1] == L'\\' && s0[2] == L'?' && s0[3] == L'\\') { +l1 -= 4; +s1 += 4; +} + +for (i = 0; i < l1; i++) { +wchar_t e = expect[i]; +c = s1[i]; +if (!e) +break; +if (c != e) +return 0; +} +} + +/* Look for "-pty%d-" */ +for (i = 0; i < l; i++) { +c = s0[i]; +if (c == L'-') { +wchar_t *s = s0 + i + 1; +if (s[0] == L'p' && s[1] == L't' && s[2] == L'y' && +(c = s[3]) && (c >= L'0') && (c <= L'9')) +{ +s += 4; +while ((c = *s) && (c >= L'0') && (c <= L'9')) +s++; +if (c == L'-') +return 1; +} +} +} + +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
[Mingw-w64-public] [PATCH v3] Add include/iscygtty.c
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 --- v3: - make name check stricter; require a dash after "-pty%d" - look for '\\.\' in front of name, not just '\\?\' mingw-w64-headers/include/iscygtty.c | 72 1 file changed, 72 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 ..1c59bbfd018a --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,72 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +USHORT l1 = l; +wchar_t *s1 = s0; +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +if (s0[0] == L'\\' && s0[1] == L'\\' && +(s0[2] == L'?' || s0[2] == L'.') && +s0[3] == L'\\') +{ +l1 -= 4; +s1 += 4; +} + +for (i = 0; i < l1; i++) { +wchar_t e = expect[i]; +c = s1[i]; +if (!e) +break; +if (c != e) +return 0; +} +} + +/* Look for "-pty%d-" */ +for (i = 0; i < l; i++) { +c = s0[i]; +if (c == L'-') { +wchar_t *s = s0 + i + 1; +if (s[0] == L'p' && s[1] == L't' && s[2] == L'y' && +(c = s[3]) && (c >= L'0') && (c <= L'9')) +{ +s += 4; +while ((c = *s) && (c >= L'0') && (c <= L'9')) +s++; +if (c == L'-') +return 1; +} +} +} + +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
Re: [Mingw-w64-public] [PATCH v2] Add include/iscygtty.c
On Fri, Nov 11, 2016 at 11:19:45AM -0500, Earnie wrote: > On 11/10/2016 5:43 PM, Mihail Konev wrote: > > Applications now could call iscygtty(STDIN_FILENO) > > in order to detect whether they are running from > > Cygwin/MSys terminal. > > > > Should this be shared with Cygwin so that a similar function exists in > its C API? > It would then be an alias to isatty(). The call is only needed for mingw apps that are launched from msys or cygwin terminals (through mintty, conemu, or possibly anything else). The msys and cygwin projects do have packages built with mingw-w64 toolchain, so they would benefit from the change. But for cygwin.dll (or msys.dll) support headers, the call is just irrelevant. -- 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
[Mingw-w64-public] [PATCH v2] Add include/iscygtty.c
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 --- This is the patch that was catenated into a forwarded message. Typo in preceding message: > It doesn't harm to check, but adding L-s decreases readability It doesn't harm to add L-s, but they decrease readability. mingw-w64-headers/include/iscygtty.c | 68 1 file changed, 68 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 ..3eb344bbb142 --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,68 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +USHORT l1 = l; +wchar_t *s1 = s0; +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +if (s0[0] == L'\\' && s0[1] == L'\\' && s0[2] == L'?' && s0[3] == L'\\') { +l1 -= 4; +s1 += 4; +} +for (i = 0; i < l1; i++) { +wchar_t e = expect[i]; +c = s1[i]; +if (!e) +break; +if (c != e) +return 0; +} +} + +/* Look for "-pty%d-" */ +for (i = 0; i < l; i++) { +c = s0[i]; +if (c == L'-') { +wchar_t *s = s0 + i + 1; +if (s[0] == L'p' && s[1] == L't' && s[2] == L'y' && +(c = s[3]) && (c >= L'0') && (c <= L'9')) +{ +s += 4; +while ((c = *s) && (c >= L'0') && (c <= L'9')) +s++; +if (c == L'-' || c == 0) +return 1; +} +} +} + +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
Re: [Mingw-w64-public] [PATCH mingw-w64] Add include/iscygtty.c
There are files that were catenated. Running curses in conemu should be possible with https://conemu.github.io/en/CygwinMsysConnector.html But even then, the iscygtty() is supposed to check whether it is present with a mintty-like stdin, and nothing else. all: test a.exe: main.c $(CC) -Wall -Wextra main.c -lntdll test: a.exe @echo @echo " -- Test not a tty --" @echo ls | ./a.exe @echo @echo " -- Test a tty --" @echo ./a.exe @echo @echo " -- Test a named pipe --" @echo @rm .named_pipe 2>/dev/null || true mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe @echo @echo " -- Test a cmd.exe --" @echo echo "a.exe" | cmd @echo @echo @echo " -- Test a console --" @echo start //wait //min cmd //c "a.exe > .con_out" @cat .con_out @rm .con_out @echo clean: rm a.exe 2>/dev/null || true -- Test not a tty -- ls | ./a.exe h_stdin: 508 len 106 name \Device\NamedPipe\msys-65762b9fcd7dbfea-1952-pipe-0x1 is stdin a cygwin tty: no console title: invisible cygwin console failed to GetConsoleMode() (return code 0) is stdin a console: no -- Test a tty -- ./a.exe h_stdin: 464 len 112 name \Device\NamedPipe\msys-65762b9fcd7dbfea-pty0-from-master -pty%d [+39]: 'pty0-from-master' is stdin a cygwin tty: yes console title: invisible cygwin console failed to GetConsoleMode() (return code 0) is stdin a console: no -- Test a named pipe -- mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe h_stdin: 292 len 140 name \Device\NamedPipe\msys-65762b9fcd7dbfea-fifo.00C4.0061009F is stdin a cygwin tty: no console title: invisible cygwin console failed to GetConsoleMode() (return code 0) is stdin a console: no -- Test a cmd.exe -- echo "a.exe" | cmd Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. J:\msys\home\u\mingw-isatty>a.exe h_stdin: 508 len 104 name \Device\NamedPipe\msys-65762b9fcd7dbfea-400-pipe-0x1 is stdin a cygwin tty: no console title: invisible cygwin console - a.exe failed to GetConsoleMode() (return code 0) is stdin a console: no J:\msys\home\u\mingw-isatty> -- Test a console -- start //wait //min cmd //c "a.exe > .con_out" h_stdin: 3 failed to NtQueryObject h_stdin ObjectNameInformation (return code -1073741816) is stdin a cygwin tty: no console title: C:\Windows\System32\cmd.exe is stdin a console: yes -- 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
[Mingw-w64-public] [k....@ya.ru: Re: [PATCH mingw-w64] Add include/iscygtty.c]
Wrong destination address :) I didn't tried ConEmu. Is it possible to run cygwin curses app in it, like a text editor, btw? But with msys mintty and standard Console results do differ. - Forwarded message from Mihail Konev <k@ya.ru> - From: Mihail Konev <k@ya.ru> To: Vincent Torri <vincent.to...@gmail.com> Date: Thu, 10 Nov 2016 23:13:15 +0500 Subject: Re: [Mingw-w64-public] [PATCH mingw-w64] Add include/iscygtty.c On Thu, Nov 10, 2016 at 06:16:38AM +0100, Vincent Torri wrote: > just call GetConsoleMode() and check its result to know if the > redirection is with a pipe or a console handle The result would then differ in two cases: - stdin is Cygwin/MSys terminal - stdin is Windows console Attached are test program source, Makefile, and 'make' output when run from MSys2-MINGW64 shell. #include #include #include #ifndef STDIN_FILENO #define STDIN_FILENO 0 #endif #ifndef NO_CONSOLE_MODE #include #endif static int isacygtty(int fd) { intptr_t h_stdin = _get_osfhandle(fd); printf("h_stdin: %ld\n", (long)h_stdin); char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; NTSTATUS status; ULONG ntfn_size = sizeof(ntfn_bytes); memset(ntfn, 0, ntfn_size); status = NtQueryObject((HANDLE)h_stdin, ObjectNameInformation, ntfn, ntfn_size, _size); if (!NT_SUCCESS(status)) { printf("failed to NtQueryObject h_stdin ObjectNameInformation (return code %ld)\n", (long)status); return 0; } printf("len %d\n", ntfn->Name.Length); printf("name %ls\n", ntfn->Name.Buffer); USHORT i, l = ntfn->Name.Length; wchar_t c, *s0 = ntfn->Name.Buffer; /* Check for "\Device\NamedPipe" */ { USHORT l1 = l; wchar_t *s1 = s0; wchar_t expect[] = L"\\Device\\NamedPipe\\"; if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') { l1 -= 4; s1 += 4; } for (i = 0; i < l1; i++) { wchar_t e = expect[i]; c = s1[i]; if (!e) break; if (c != e) return 0; } } /* Look for "-pty%d-" */ for (i = 0; i < l; i++) { c = s0[i]; if (c == '-') { wchar_t *s = s0 + i + 1; if (s[0] == 'p' && s[1] == 't' && s[2] == 'y' && (c = s[3]) && (c >= '0') && (c <= '9')) { printf("-pty%%d [+%d]: '%ls'\n", (int)i, s); s += 4; while ((c = *s) && (c >= '0') && (c <= '9')) s++; if (c == '-' || c == 0) return 1; } } } return 0; } #ifndef NO_CONSOLE_MODE int isaconsole(DWORD std_handle) { { size_t l = 256; WCHAR console_title[l]; memset(console_title, 0, l); if (!GetConsoleTitleW(console_title, l)) { printf("failed to GetConsoleTitleW()\n"); return 0; } else { printf("console title: %ls\n", console_title); } } { HANDLE h_std = GetStdHandle(std_handle); DWORD console_mode; long rc; if (h_std == INVALID_HANDLE_VALUE) { printf("failed to GetStdHandle()\n"); return 0; } rc = GetConsoleMode(h_std, _mode); if (!rc) { printf("failed to GetConsoleMode() (return code %ld)\n", rc); return 0; } } return 1; } #endif int main(int argc, char **argv) { (void) argc; (void) argv; printf("is stdin a cygwin tty: %s\n", isacygtty(STDIN_FILENO) ? "yes" : "no"); #ifndef NO_CONSOLE_MODE printf("is stdin a console: %s\n", isaconsole(STD_INPUT_HANDLE) ? "yes" : "no"); #endif return 0; } all: test a.exe: main.c $(CC) -Wall -Wextra main.c -lntdll test: a.exe @echo @echo " -- Test not a tty --" @echo ls | ./a.exe @echo @echo " -- Test a tty --" @echo ./a.exe @echo @echo " -- Test a named pipe --" @echo @rm .named_pipe 2>/dev/null || true mkfifo .named_pipe ( sleep 0.2; echo abc > .named_pipe; ) & \ ./a.exe < .named_pipe @echo @echo " -- Test a cmd.exe --" @echo echo "a.exe" | cmd @echo @echo @echo " -- Test a console --" @echo start //wait //min cmd //c "a.exe > .con_out" @cat
[Mingw-w64-public] [k....@ya.ru: Re: Fwd: [PATCH mingw-w64] Add include/iscygtty.c]
- Forwarded message from Mihail Konev <k@ya.ru> - From: Mihail Konev <k@ya.ru> To: David Wohlferd <d...@limegreensocks.com> Date: Thu, 10 Nov 2016 23:22:48 +0500 Subject: Re: Fwd: [Mingw-w64-public] [PATCH mingw-w64] Add include/iscygtty.c On Wed, Nov 09, 2016 at 08:21:51PM -0800, David Wohlferd wrote: > Shouldn't these (and the rest of the chars in this file) be L'\\'? While it > seems to work either way for gcc, I'm not sure all compilers are as > forgiving. > > dw > > Forwarded Message > + if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') { > - Then '(int)1 == (long)1' would not be considered correct either. - Gcc does not complain even with -pedantic -ansi (attached are test program source, Makefile, and 'make' output) It does not harm to check, through, but adding L-s decreases readability. Attached is v2 patch. - add L-s - make "-pty%d-" check stricter; do not check for "-tty%d-" #include #include #define PRINT_LONG_EXPR(x) printf(""#x" => %ld\n", (long)(x)) int main(int argc, char **argv) { (void) argc; (void) argv; PRINT_LONG_EXPR((int)1 == (long)1); PRINT_LONG_EXPR((char)1 == (wchar_t)1); PRINT_LONG_EXPR('c' == L'c'); { char s[] = "c"; wchar_t ws[] = L"c"; PRINT_LONG_EXPR(s[0] == ws[0]); } return 0; } CFLAGS += -Wall -Wextra -O3 all: @echo $(MAKE) normal @echo $(MAKE) pedantic @echo $(MAKE) ansi @echo PHONY: normal normal: $(LINK.c) -o a.exe main.c PHONY: pedantic pedantic: CFLAGS += -pedantic pedantic: CFLAGS += -pedantic-errors pedantic: normal PHONY: ansi ansi: CFLAGS += -ansi ansi: pedantic make normal make[1]: Entering directory '/mnt/j/msys/home/u/int_cast_test' cc -Wall -Wextra -O3-o a.exe main.c make[1]: Leaving directory '/mnt/j/msys/home/u/int_cast_test' make pedantic make[1]: Entering directory '/mnt/j/msys/home/u/int_cast_test' cc -Wall -Wextra -O3 -pedantic -pedantic-errors-o a.exe main.c make[1]: Leaving directory '/mnt/j/msys/home/u/int_cast_test' make ansi make[1]: Entering directory '/mnt/j/msys/home/u/int_cast_test' cc -Wall -Wextra -O3 -ansi -pedantic -pedantic-errors-o a.exe main.c make[1]: Leaving directory '/mnt/j/msys/home/u/int_cast_test' >From ed18de062e6dd90d5656f8e74533672958d89a8b Mon Sep 17 00:00:00 2001 From: Mihail Konev <k@ya.ru> Date: Tue, 8 Nov 2016 14:16:31 +0500 Subject: [PATCH] Add include/iscygtty.c 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 --- mingw-w64-headers/include/iscygtty.c | 68 1 file changed, 68 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 ..3eb344bbb142 --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,68 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +USHORT l1 = l; +wchar_t *s1 = s0; +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +if (s0[0] == L'\\' && s0[1] == L'\\' && s0[2] == L'?' && s0[3] == L'\\') { +l1 -= 4; +s1 += 4; +} +for (i = 0; i < l1; i++) { +wchar_t e = expect[i]; +c = s1[i]; +if (!e) +break; +if (c != e) +return 0; +} +} + +/* Look for "-pty%d-" */ +for (i = 0; i < l; i++) { +c = s0[i]; +if (c == L'-') { +wchar_t *s = s0 + i + 1; +if (s[0] == L'p' && s[1] == L't' && s[2] == L'y' && +(c = s[3]) && (c >= L'0') && (c <= L'9')) +{ +s +=
[Mingw-w64-public] [PATCH mingw-w64] Add include/iscygtty.c
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 --- mingw-w64-headers/include/iscygtty.c | 69 1 file changed, 69 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 ..f7344b8b20c4 --- /dev/null +++ b/mingw-w64-headers/include/iscygtty.c @@ -0,0 +1,69 @@ +#ifndef __ISCYGTTY_C__ +#define __ISCYGTTY_C__ + +#include +#include + +static int iscygtty(int fd) { +intptr_t h_fd = _get_osfhandle(fd); + +char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; +OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; +NTSTATUS status; +ULONG ntfn_size = sizeof(ntfn_bytes); + +USHORT i, l; +wchar_t c, *s0; + +memset(ntfn, 0, ntfn_size); +status = NtQueryObject((HANDLE)h_fd, ObjectNameInformation, +ntfn, ntfn_size, _size); + +if (!NT_SUCCESS(status)) +return 0; + +l = ntfn->Name.Length; +s0 = ntfn->Name.Buffer; + +/* Check for "\Device\NamedPipe" */ +{ +USHORT l1 = l; +wchar_t *s1 = s0; +wchar_t expect[] = L"\\Device\\NamedPipe\\"; + +if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') { +l1 -= 4; +s1 += 4; +} +for (i = 0; i < l1; i++) { +wchar_t e = expect[i]; +c = s1[i]; +if (!e) +break; +if (c != e) +return 0; +} +} + +/* Look for "-pty%d-" */ +for (i = 0; i < l; i++) { +c = s0[i]; +if (c == '-') { +wchar_t *s = s0 + i + 1; +c = *s; +if ((c == 'p' || c == 't') && s[1] == 't' && s[2] == 'y' && +(c = s[3]) && (c >= '0') && (c <= '9')) +{ +s += 4; +while ((c = *s) && (c >= '0') && (c <= '9')) +s++; +if (c == '-' || c == 0) +return 1; +} +} +} + +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