Skip to content

Commit 3adef8d

Browse files
kbleesdscho
authored andcommitted
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 55c5c80 commit 3adef8d

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

compat/winansi.c

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ static size_t sizeof_ioinfo = 0;
482482
#define IOINFO_L2E 5
483483
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
484484

485+
#define FPIPE 0x08
485486
#define FDEV 0x40
486487

487488
static inline ioinfo* _pioinfo(int fd)
@@ -529,6 +530,45 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
529530
return old_handle;
530531
}
531532

533+
#ifdef DETECT_MSYS_TTY
534+
535+
#include <winternl.h>
536+
#include <ntstatus.h>
537+
538+
static void detect_msys_tty(int fd)
539+
{
540+
ULONG result;
541+
BYTE buffer[1024];
542+
POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;
543+
PWSTR name;
544+
545+
/* check if fd is a pipe */
546+
HANDLE h = (HANDLE) _get_osfhandle(fd);
547+
if (GetFileType(h) != FILE_TYPE_PIPE)
548+
return;
549+
550+
/* get pipe name */
551+
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation,
552+
buffer, sizeof(buffer) - 2, &result)))
553+
return;
554+
name = nameinfo->Name.Buffer;
555+
name[nameinfo->Name.Length] = 0;
556+
557+
/* check if this could be a msys pty pipe ('msys-XXXX-ptyN-XX') */
558+
if (!wcsstr(name, L"msys-") || !wcsstr(name, L"-pty"))
559+
return;
560+
561+
/* init ioinfo size if we haven't done so */
562+
if (init_sizeof_ioinfo())
563+
return;
564+
565+
/* set FDEV flag, reset FPIPE flag */
566+
_pioinfo(fd)->osflags &= ~FPIPE;
567+
_pioinfo(fd)->osflags |= FDEV;
568+
}
569+
570+
#endif
571+
532572
void winansi_init(void)
533573
{
534574
int con1, con2;
@@ -537,8 +577,15 @@ void winansi_init(void)
537577
/* check if either stdout or stderr is a console output screen buffer */
538578
con1 = is_console(1);
539579
con2 = is_console(2);
540-
if (!con1 && !con2)
580+
if (!con1 && !con2) {
581+
#ifdef DETECT_MSYS_TTY
582+
/* check if stdin / stdout / stderr are msys pty pipes */
583+
detect_msys_tty(0);
584+
detect_msys_tty(1);
585+
detect_msys_tty(2);
586+
#endif
541587
return;
588+
}
542589

543590
/* create a named pipe to communicate with the console thread */
544591
sprintf(name, "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
@@ -574,8 +621,11 @@ void winansi_init(void)
574621
HANDLE winansi_get_osfhandle(int fd)
575622
{
576623
HANDLE hnd = (HANDLE) _get_osfhandle(fd);
577-
if ((fd == 1 || fd == 2) && isatty(fd)
578-
&& GetFileType(hnd) == FILE_TYPE_PIPE)
579-
return (fd == 1) ? hconsole1 : hconsole2;
624+
if (isatty(fd) && GetFileType(hnd) == FILE_TYPE_PIPE) {
625+
if (fd == 1 && hconsole1)
626+
return hconsole1;
627+
else if (fd == 2 && hconsole2)
628+
return hconsole2;
629+
}
580630
return hnd;
581631
}

config.mak.uname

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,8 @@ else
557557
BASIC_LDFLAGS += -Wl,--large-address-aware
558558
endif
559559
CC = gcc
560-
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0
560+
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY
561+
EXTLIBS += -lntdll
561562
INSTALL = /bin/install
562563
NO_R_TO_GCC_LINKER = YesPlease
563564
INTERNAL_QSORT = YesPlease

0 commit comments

Comments
 (0)