mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)
MSYS2 emulates pseudo terminals via named pipes, and isatty() returns 0 for such file descriptors. Therefore, some interactive functionality (such as launching a pager, asking if a failed unlink should be repeated etc.) doesn't work when run in a terminal emulator that uses MSYS2's ptys (such as mintty). However, MSYS2 uses special names for its pty pipes ('msys-*-pty*'), which allows us to distinguish them from normal piped input / output. On startup, check if stdin / stdout / stderr are connected to such pipes using the NtQueryObject API from NTDll.dll. If the names match, adjust the flags in MSVCRT's ioinfo structure accordingly. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0f8e831356
commit
f7f90e0f4f
@ -483,6 +483,7 @@ static size_t sizeof_ioinfo = 0;
|
|||||||
#define IOINFO_L2E 5
|
#define IOINFO_L2E 5
|
||||||
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
|
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
|
||||||
|
|
||||||
|
#define FPIPE 0x08
|
||||||
#define FDEV 0x40
|
#define FDEV 0x40
|
||||||
|
|
||||||
static inline ioinfo* _pioinfo(int fd)
|
static inline ioinfo* _pioinfo(int fd)
|
||||||
@ -530,6 +531,45 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
|
|||||||
return old_handle;
|
return old_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DETECT_MSYS_TTY
|
||||||
|
|
||||||
|
#include <winternl.h>
|
||||||
|
#include <ntstatus.h>
|
||||||
|
|
||||||
|
static void detect_msys_tty(int fd)
|
||||||
|
{
|
||||||
|
ULONG result;
|
||||||
|
BYTE buffer[1024];
|
||||||
|
POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;
|
||||||
|
PWSTR name;
|
||||||
|
|
||||||
|
/* check if fd is a pipe */
|
||||||
|
HANDLE h = (HANDLE) _get_osfhandle(fd);
|
||||||
|
if (GetFileType(h) != FILE_TYPE_PIPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* get pipe name */
|
||||||
|
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation,
|
||||||
|
buffer, sizeof(buffer) - 2, &result)))
|
||||||
|
return;
|
||||||
|
name = nameinfo->Name.Buffer;
|
||||||
|
name[nameinfo->Name.Length] = 0;
|
||||||
|
|
||||||
|
/* check if this could be a MSYS2 pty pipe ('msys-XXXX-ptyN-XX') */
|
||||||
|
if (!wcsstr(name, L"msys-") || !wcsstr(name, L"-pty"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* init ioinfo size if we haven't done so */
|
||||||
|
if (init_sizeof_ioinfo())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* set FDEV flag, reset FPIPE flag */
|
||||||
|
_pioinfo(fd)->osflags &= ~FPIPE;
|
||||||
|
_pioinfo(fd)->osflags |= FDEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void winansi_init(void)
|
void winansi_init(void)
|
||||||
{
|
{
|
||||||
int con1, con2;
|
int con1, con2;
|
||||||
@ -538,8 +578,15 @@ void winansi_init(void)
|
|||||||
/* check if either stdout or stderr is a console output screen buffer */
|
/* check if either stdout or stderr is a console output screen buffer */
|
||||||
con1 = is_console(1);
|
con1 = is_console(1);
|
||||||
con2 = is_console(2);
|
con2 = is_console(2);
|
||||||
if (!con1 && !con2)
|
if (!con1 && !con2) {
|
||||||
|
#ifdef DETECT_MSYS_TTY
|
||||||
|
/* check if stdin / stdout / stderr are MSYS2 pty pipes */
|
||||||
|
detect_msys_tty(0);
|
||||||
|
detect_msys_tty(1);
|
||||||
|
detect_msys_tty(2);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* create a named pipe to communicate with the console thread */
|
/* create a named pipe to communicate with the console thread */
|
||||||
xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
|
xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
|
||||||
@ -575,8 +622,11 @@ void winansi_init(void)
|
|||||||
HANDLE winansi_get_osfhandle(int fd)
|
HANDLE winansi_get_osfhandle(int fd)
|
||||||
{
|
{
|
||||||
HANDLE hnd = (HANDLE) _get_osfhandle(fd);
|
HANDLE hnd = (HANDLE) _get_osfhandle(fd);
|
||||||
if ((fd == 1 || fd == 2) && isatty(fd)
|
if (isatty(fd) && GetFileType(hnd) == FILE_TYPE_PIPE) {
|
||||||
&& GetFileType(hnd) == FILE_TYPE_PIPE)
|
if (fd == 1 && hconsole1)
|
||||||
return (fd == 1) ? hconsole1 : hconsole2;
|
return hconsole1;
|
||||||
|
else if (fd == 2 && hconsole2)
|
||||||
|
return hconsole2;
|
||||||
|
}
|
||||||
return hnd;
|
return hnd;
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,8 @@ else
|
|||||||
BASIC_LDFLAGS += -Wl,--large-address-aware
|
BASIC_LDFLAGS += -Wl,--large-address-aware
|
||||||
endif
|
endif
|
||||||
CC = gcc
|
CC = gcc
|
||||||
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0
|
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY
|
||||||
|
EXTLIBS += -lntdll
|
||||||
INSTALL = /bin/install
|
INSTALL = /bin/install
|
||||||
NO_R_TO_GCC_LINKER = YesPlease
|
NO_R_TO_GCC_LINKER = YesPlease
|
||||||
INTERNAL_QSORT = YesPlease
|
INTERNAL_QSORT = YesPlease
|
||||||
|
Loading…
x
Reference in New Issue
Block a user