{"thread":{"id":"42155","subject":"[PATCH] mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)","startedAt":"2016-04-27T15:16:37Z","lastAt":"2016-05-27T13:33:51Z","messageCount":4,"participants":["Johannes Schindelin","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"284653","messageId":"f1408371e14ff10539990ad710681ef17f29fea1.1461770158.git.johannes.schindelin@gmx.de","threadId":"42155","inReplyTo":null,"subject":"[PATCH] mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-04-27T15:16:37Z","receivedAt":"2016-04-27T15:16:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"From: Karsten Blees <blees@dcon.de>\n\nMSYS2 emulates pseudo terminals via named pipes, and isatty() returns 0\nfor such file descriptors. Therefore, some interactive functionality\n(such as launching a pager, asking if a failed unlink should be repeated\netc.) doesn't work when run in a terminal emulator that uses MSYS2's\nptys (such as mintty).\n\nHowever, MSYS2 uses special names for its pty pipes ('msys-*-pty*'),\nwhich allows us to distinguish them from normal piped input / output.\n\nOn startup, check if stdin / stdout / stderr are connected to such pipes\nusing the NtQueryObject API from NTDll.dll. If the names match, adjust\nthe flags in MSVCRT's ioinfo structure accordingly.\n\nSigned-off-by: Karsten Blees <blees@dcon.de>\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\nPublished-As: https://github.com/dscho/git/releases/tag/windows-isatty-v1\n compat/winansi.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++----\n config.mak.uname |  3 ++-\n 2 files changed, 56 insertions(+), 5 deletions(-)\n\ndiff --git a/compat/winansi.c b/compat/winansi.c\nindex 5dfa5ed..3be60ce 100644\n--- a/compat/winansi.c\n+++ b/compat/winansi.c\n@@ -483,6 +483,7 @@ static size_t sizeof_ioinfo = 0;\n #define IOINFO_L2E 5\n #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)\n \n+#define FPIPE 0x08\n #define FDEV  0x40\n \n static inline ioinfo* _pioinfo(int fd)\n@@ -530,6 +531,45 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)\n \treturn old_handle;\n }\n \n+#ifdef DETECT_MSYS_TTY\n+\n+#include <winternl.h>\n+#include <ntstatus.h>\n+\n+static void detect_msys_tty(int fd)\n+{\n+\tULONG result;\n+\tBYTE buffer[1024];\n+\tPOBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;\n+\tPWSTR name;\n+\n+\t/* check if fd is a pipe */\n+\tHANDLE h = (HANDLE) _get_osfhandle(fd);\n+\tif (GetFileType(h) != FILE_TYPE_PIPE)\n+\t\treturn;\n+\n+\t/* get pipe name */\n+\tif (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation,\n+\t\t\tbuffer, sizeof(buffer) - 2, &result)))\n+\t\treturn;\n+\tname = nameinfo->Name.Buffer;\n+\tname[nameinfo->Name.Length] = 0;\n+\n+\t/* check if this could be a MSYS2 pty pipe ('msys-XXXX-ptyN-XX') */\n+\tif (!wcsstr(name, L\"msys-\") || !wcsstr(name, L\"-pty\"))\n+\t\treturn;\n+\n+\t/* init ioinfo size if we haven't done so */\n+\tif (init_sizeof_ioinfo())\n+\t\treturn;\n+\n+\t/* set FDEV flag, reset FPIPE flag */\n+\t_pioinfo(fd)->osflags &= ~FPIPE;\n+\t_pioinfo(fd)->osflags |= FDEV;\n+}\n+\n+#endif\n+\n void winansi_init(void)\n {\n \tint con1, con2;\n@@ -538,8 +578,15 @@ void winansi_init(void)\n \t/* check if either stdout or stderr is a console output screen buffer */\n \tcon1 = is_console(1);\n \tcon2 = is_console(2);\n-\tif (!con1 && !con2)\n+\tif (!con1 && !con2) {\n+#ifdef DETECT_MSYS_TTY\n+\t\t/* check if stdin / stdout / stderr are MSYS2 pty pipes */\n+\t\tdetect_msys_tty(0);\n+\t\tdetect_msys_tty(1);\n+\t\tdetect_msys_tty(2);\n+#endif\n \t\treturn;\n+\t}\n \n \t/* create a named pipe to communicate with the console thread */\n \txsnprintf(name, sizeof(name), \"\\\\\\\\.\\\\pipe\\\\winansi%lu\", GetCurrentProcessId());\n@@ -575,8 +622,11 @@ void winansi_init(void)\n HANDLE winansi_get_osfhandle(int fd)\n {\n \tHANDLE hnd = (HANDLE) _get_osfhandle(fd);\n-\tif ((fd == 1 || fd == 2) && isatty(fd)\n-\t    && GetFileType(hnd) == FILE_TYPE_PIPE)\n-\t\treturn (fd == 1) ? hconsole1 : hconsole2;\n+\tif (isatty(fd) && GetFileType(hnd) == FILE_TYPE_PIPE) {\n+\t\tif (fd == 1 && hconsole1)\n+\t\t\treturn hconsole1;\n+\t\telse if (fd == 2 && hconsole2)\n+\t\t\treturn hconsole2;\n+\t}\n \treturn hnd;\n }\ndiff --git a/config.mak.uname b/config.mak.uname\nindex 40d6b29..a88f139 100644\n--- a/config.mak.uname\n+++ b/config.mak.uname\n@@ -557,7 +557,8 @@ else\n \t\t\tBASIC_LDFLAGS += -Wl,--large-address-aware\n \t\tendif\n \t\tCC = gcc\n-\t\tCOMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0\n+\t\tCOMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY\n+\t\tEXTLIBS += -lntdll\n \t\tINSTALL = /bin/install\n \t\tNO_R_TO_GCC_LINKER = YesPlease\n \t\tINTERNAL_QSORT = YesPlease\n-- \n2.8.1.306.gff998f2\n"},{"id":"287574","messageId":"alpine.DEB.2.20.1605261525400.4449@virtualbox","threadId":"42155","inReplyTo":"f1408371e14ff10539990ad710681ef17f29fea1.1461770158.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH] mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-05-26T13:28:29Z","receivedAt":"2016-05-26T13:28:29Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Wed, 27 Apr 2016, Johannes Schindelin wrote:\n\n> From: Karsten Blees <blees@dcon.de>\n> \n> MSYS2 emulates pseudo terminals via named pipes, and isatty() returns 0\n> for such file descriptors. Therefore, some interactive functionality\n> (such as launching a pager, asking if a failed unlink should be repeated\n> etc.) doesn't work when run in a terminal emulator that uses MSYS2's\n> ptys (such as mintty).\n> \n> However, MSYS2 uses special names for its pty pipes ('msys-*-pty*'),\n> which allows us to distinguish them from normal piped input / output.\n> \n> On startup, check if stdin / stdout / stderr are connected to such pipes\n> using the NtQueryObject API from NTDll.dll. If the names match, adjust\n> the flags in MSVCRT's ioinfo structure accordingly.\n> \n> Signed-off-by: Karsten Blees <blees@dcon.de>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nFor the record, this patch is needed to make the output of `git log` *not*\nwhizz by when running in MinTTY, the default terminal of Git for Windows\nand MSYS2.\n\nI do not see this patch in 'pu'... Anything I can do to get this into\n'master' eventually?\n\nCiao,\nDscho\n"},{"id":"287594","messageId":"xmqqvb20wy5x.fsf@gitster.mtv.corp.google.com","threadId":"42155","inReplyTo":"alpine.DEB.2.20.1605261525400.4449@virtualbox","subject":"Re: [PATCH] mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-26T17:02:02Z","receivedAt":"2016-05-26T17:02:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> I do not see this patch in 'pu'... Anything I can do to get this into\n> 'master' eventually?\n\nThe reason why I left it in my inbox was because I couldn't tell if\nthis was a final submission with concensus among Git developers on\nWindows, or I should be giving a chance to comment to some folks who\nwork on Windows port but are not necessarily closely communicating\nwith you.\n\nIf the message were Cc'ed to J6t, I would probably have queued it on\n'pu' and marked it as \"Will merge after waiting for a few days\" in\nWhat's cooking.\n\nThanks.\n"},{"id":"287671","messageId":"alpine.DEB.2.20.1605271529540.4449@virtualbox","threadId":"42155","inReplyTo":"xmqqvb20wy5x.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-05-27T13:33:51Z","receivedAt":"2016-05-27T13:33:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Thu, 26 May 2016, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > I do not see this patch in 'pu'... Anything I can do to get this into\n> > 'master' eventually?\n> \n> The reason why I left it in my inbox was because I couldn't tell if\n> this was a final submission with concensus among Git developers on\n> Windows, or I should be giving a chance to comment to some folks who\n> work on Windows port but are not necessarily closely communicating\n> with you.\n> \n> If the message were Cc'ed to J6t, I would probably have queued it on\n> 'pu' and marked it as \"Will merge after waiting for a few days\" in\n> What's cooking.\n\nHannes does not use Git for Windows' SDK, but instead uses an old\nMSys-based development environment that predates even msysGit (which was\nthe SDK used to develop Git for Windows 1.x). His environment most\nnotably does *not* use MinTTY, and therefore is unaffected by the bug that\nthis patch fixes.\n\nThat was the entire reasoning why I did not ask Hannes to review this\npatch: it is unlikely that he knows about the issue, let alone about the\ncorrectness of the implementation of this patch.\n\nThe implementation relies on some really low-level knowledge of the\nWindows internals, which Karsten reverse-engineered and I verified.\n\nThanks,\nDscho\n"}]}