Skip to content

Commit 7d57fb4

Browse files
committed
mingw: make isatty() recognize MSys 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 MSys ptys (such as mintty). However, MSys 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 <[email protected]>
1 parent 22a888e commit 7d57fb4

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

compat/winansi.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
#include <wingdi.h>
88
#include <winreg.h>
99

10+
#ifdef USE_NTDLL
11+
#include <winternl.h>
12+
#include <ntstatus.h>
13+
#endif
14+
1015
/*
1116
ANSI codes used by git: m, K
1217
@@ -483,6 +488,7 @@ static size_t sizeof_ioinfo = 0;
483488
#define IOINFO_L2E 5
484489
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
485490

491+
#define FPIPE 0x08
486492
#define FDEV 0x40
487493

488494
static inline ioinfo* _pioinfo(int fd)
@@ -530,6 +536,44 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
530536
return old_handle;
531537
}
532538

539+
#ifdef USE_NTDLL
540+
541+
static void msystty_init(int fd)
542+
{
543+
ULONG result;
544+
BYTE buffer[1024];
545+
POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;
546+
PWSTR name;
547+
548+
/* check if fd is a pipe */
549+
HANDLE h = (HANDLE) _get_osfhandle(fd);
550+
if (GetFileType(h) != FILE_TYPE_PIPE)
551+
return;
552+
553+
/* get pipe name */
554+
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation,
555+
buffer, sizeof(buffer) - 2, &result)))
556+
return;
557+
name = nameinfo->Name.Buffer;
558+
name[nameinfo->Name.Length] = 0;
559+
560+
/* check if this could be a msys pty pipe ('msys-XXXX-ptyN-XX') */
561+
if (!wcsstr(name, L"msys-") || !wcsstr(name, L"-pty"))
562+
return;
563+
564+
/* init ioinfo size if we haven't done so */
565+
if (init_sizeof_ioinfo())
566+
return;
567+
568+
/* set FDEV flag, reset FPIPE flag */
569+
_pioinfo(fd)->osflags &= ~FPIPE;
570+
_pioinfo(fd)->osflags |= FDEV;
571+
}
572+
573+
#else
574+
#define msystty_init(fd) (void)0
575+
#endif
576+
533577
void winansi_init(void)
534578
{
535579
int con1, con2;
@@ -538,8 +582,13 @@ void winansi_init(void)
538582
/* check if either stdout or stderr is a console output screen buffer */
539583
con1 = is_console(1);
540584
con2 = is_console(2);
541-
if (!con1 && !con2)
585+
if (!con1 && !con2) {
586+
/* check if stdin / stdout / stderr are msys pty pipes */
587+
msystty_init(0);
588+
msystty_init(1);
589+
msystty_init(2);
542590
return;
591+
}
543592

544593
/* create a named pipe to communicate with the console thread */
545594
sprintf(name, "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
@@ -575,8 +624,11 @@ void winansi_init(void)
575624
HANDLE winansi_get_osfhandle(int fd)
576625
{
577626
HANDLE hnd = (HANDLE) _get_osfhandle(fd);
578-
if ((fd == 1 || fd == 2) && isatty(fd)
579-
&& GetFileType(hnd) == FILE_TYPE_PIPE)
580-
return (fd == 1) ? hconsole1 : hconsole2;
627+
if (isatty(fd) && GetFileType(hnd) == FILE_TYPE_PIPE) {
628+
if (fd == 1 && hconsole1)
629+
return hconsole1;
630+
else if (fd == 2 && hconsole2)
631+
return hconsole2;
632+
}
581633
return hnd;
582634
}

config.mak.uname

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,8 @@ else
548548
BASIC_LDFLAGS += -Wl,--large-address-aware
549549
endif
550550
CC = gcc
551-
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0
551+
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DUSE_NTDLL
552+
EXTLIBS += -lntdll
552553
INSTALL = /bin/install
553554
NO_R_TO_GCC_LINKER = YesPlease
554555
INTERNAL_QSORT = YesPlease

0 commit comments

Comments
 (0)