summaryrefslogtreecommitdiff
path: root/compat/winansi.c
AgeCommit message (Collapse)AuthorFilesLines
2018-10-31mingw: fix isatty() after dup2()Libravatar Johannes Schindelin1-0/+12
Since a9b8a09c3c30 (mingw: replace isatty() hack, 2016-12-22), we handle isatty() by special-casing the stdin/stdout/stderr file descriptors, caching the return value. However, we missed the case where dup2() overrides the respective file descriptor. That poses a problem e.g. where the `show` builtin asks for a pager very early, the `setup_pager()` function sets the pager depending on the return value of `isatty()` and then redirects stdout. Subsequently, `cmd_log_init_finish()` calls `setup_pager()` *again*. What should happen now is that `isatty()` reports that stdout is *not* a TTY and consequently stdout should be left alone. Let's override dup2() to handle this appropriately. This fixes https://github.com/git-for-windows/git/issues/1077 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-08winansi: avoid buffer overrunLibravatar Johannes Schindelin1-0/+5
When we could not convert the UTF-8 sequence into Unicode for writing to the Console, we should not try to write an insanely-long sequence of invalid wide characters (mistaking the negative return value for an unsigned length). Reported by Coverity. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-08winansi: avoid use of uninitialized valueLibravatar Johannes Schindelin1-0/+7
To initialize the foreground color attributes of "plain text", our ANSI emulation tries to infer them from the currently attached console while running the is_console() function. This function first tries to detect any console attached to stdout, then it is called with stderr. If neither stdout nor stderr has any console attached, it does not actually matter what we use for "plain text" attributes, as we never need to output any text to any console in that case. However, after working on stdout and stderr, is_console() is called with stdin, and it still tries to initialize the "plain text" attributes if they had not been initialized earlier. In this case, we cannot detect any attributes, and we used an uninitialized value for them. Naturally, Coverity complained about this use case because it could not reason about the code deeply enough to figure out that we do not even use those attributes in that case. Let's just initialize the value to 0 in that case, both to avoid future Coverity reports, and to help catch future regressions in case anybody changes the order of the is_console() calls (which would make the text black on black). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-16Merge branch 'js/mingw-isatty'Libravatar Junio C Hamano1-0/+4
A hotfix for a topic already in 'master'. * js/mingw-isatty: mingw: make stderr unbuffered again
2017-02-14mingw: make stderr unbuffered againLibravatar Johannes Schindelin1-0/+4
When removing the hack for isatty(), we actually removed more than just an isatty() hack: we removed the hack where internal data structures of the MSVC runtime are modified in order to redirect stdout/stderr. Instead of using that hack (that does not work with newer versions of the runtime, anyway), we replaced it by reopening the respective file descriptors. What we forgot was to mark stderr as unbuffered again. Reported by Hannes Sixt. Fixed with Jeff Hostetler's assistance. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Tested-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-01-31Merge branch 'js/mingw-isatty'Libravatar Junio C Hamano1-7/+4
An update to a topic that is already in 'master'. * js/mingw-isatty: mingw: follow-up to "replace isatty() hack"
2017-01-18mingw: follow-up to "replace isatty() hack"Libravatar Johannes Schindelin1-7/+4
The version of the "replace isatty() hack" that got merged a few weeks ago did not actually reflect the latest iteration of the patch series: v3 was sent out with these changes, as requested by the reviewer Johannes Sixt: - reworded the comment about "recycling handles" - moved the reassignment of the `console` variable before the dup2() call so that it is valid at all times - removed the "handle = INVALID_HANDLE_VALUE" assignment, as the local variable `handle` is not used afterwards anyway Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-27Merge branch 'js/mingw-isatty'Libravatar Junio C Hamano1-114/+84
Update the isatty() emulation for Windows by updating the previous hack that depended on internals of (older) MSVC runtime. * js/mingw-isatty: mingw: replace isatty() hack mingw: fix colourization on Cygwin pseudo terminals mingw: adjust is_console() to work with stdin
2016-12-27Merge branch 'mk/mingw-winansi-ttyname-termination-fix'Libravatar Junio C Hamano1-1/+1
A potential but unlikely buffer overflow in Windows port has been fixed. * mk/mingw-winansi-ttyname-termination-fix: mingw: consider that UNICODE_STRING::Length counts bytes
2016-12-22mingw: replace isatty() hackLibravatar Jeff Hostetler1-107/+69
Git for Windows has carried a patch that depended on internals of MSVC runtime, but it does not work correctly with recent MSVC runtime. A replacement was written originally for compiling with VC++. The patch in this message is a backport of that replacement, and it also fixes the previous attempt to make isatty() tell that /dev/null is *not* an interactive terminal. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Tested-by: Beat Bolli <dev+git@drbeat.li> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-22mingw: fix colourization on Cygwin pseudo terminalsLibravatar Alan Davies1-2/+6
Git only colours the output and uses pagination if isatty() returns 1. MSYS2 and Cygwin emulate pseudo terminals via named pipes, meaning that isatty() returns 0. f7f90e0f4f (mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*), 2016-04-27) fixed this for MSYS2 terminals, but not for Cygwin. The named pipes that Cygwin and MSYS2 use are very similar. MSYS2 PTY pipes are called 'msys-*-pty*' and Cygwin uses 'cygwin-*-pty*'. This commit modifies the existing check to allow both MSYS2 and Cygwin PTY pipes to be identified as TTYs. Note that pagination is still broken when running Git for Windows from within Cygwin, as MSYS2's less.exe is spawned (and does not like to interact with Cygwin's PTY). This partially fixes https://github.com/git-for-windows/git/issues/267 Signed-off-by: Alan Davies <alan.n.davies@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-22mingw: adjust is_console() to work with stdinLibravatar Johannes Schindelin1-1/+5
When determining whether a handle corresponds to a *real* Win32 Console (as opposed to, say, a character device such as /dev/null), we use the GetConsoleOutputBufferInfo() function as a tell-tale. However, that does not work for *input* handles associated with a console. Let's just use the GetConsoleMode() function for input handles, and since it does not work on output handles fall back to the previous method for those. This patch prepares for using is_console() instead of my previous misguided attempt in cbb3f3c9b1 (mingw: intercept isatty() to handle /dev/null as Git expects it, 2016-12-11) that broke everything on Windows. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-20mingw: consider that UNICODE_STRING::Length counts bytesLibravatar Max Kirillov1-1/+1
UNICODE_STRING::Length field means size of buffer in bytes[1], despite of buffer itself being array of wchar_t. Because of that terminating zero is placed twice as far. Fix it. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa380518.aspx Signed-off-by: Max Kirillov <max@max630.net> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-11mingw: intercept isatty() to handle /dev/null as Git expects itLibravatar Johannes Schindelin1-0/+33
When Git's source code calls isatty(), it really asks whether the respective file descriptor is connected to an interactive terminal. Windows' _isatty() function, however, determines whether the file descriptor is associated with a character device. And NUL, Windows' equivalent of /dev/null, is a character device. Which means that for years, Git mistakenly detected an associated interactive terminal when being run through the test suite, which almost always redirects stdin, stdout and stderr to /dev/null. This bug only became obvious, and painfully so, when the new bisect--helper entered the `pu` branch and made the automatic build & test time out because t6030 was waiting for an answer. For details, see https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-20mingw: let the build succeed with DEVELOPER=1Libravatar Johannes Schindelin1-1/+1
The recently introduced developer flags identified a couple of old-style function declarations in the Windows-specific code where the parameter list was left empty instead of specifying "void" explicitly. Let's just fix them. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-05-26mingw: make isatty() recognize MSYS2's pseudo terminals (/dev/pty*)Libravatar Karsten Blees1-4/+54
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>
2016-01-15mingw: avoid warnings when casting HANDLEs to intLibravatar Johannes Schindelin1-1/+2
HANDLE is defined internally as a void *, but in many cases it is actually guaranteed to be a 32-bit integer. In these cases, GCC should not warn about a cast of a pointer to an integer of a different type because we know exactly what we are doing. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-14compat/winansi: support compiling with MSys2Libravatar Johannes Schindelin1-0/+2
MSys2 already defines the _CONSOLE_FONT_INFOEX structure. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-09-25convert trivial sprintf / strcpy calls to xsnprintfLibravatar Jeff King1-1/+1
We sometimes sprintf into fixed-size buffers when we know that the buffer is large enough to fit the input (either because it's a constant, or because it's numeric input that is bounded in size). Likewise with strcpy of constant strings. However, these sites make it hard to audit sprintf and strcpy calls for buffer overflows, as a reader has to cross-reference the size of the array with the input. Let's use xsnprintf instead, which communicates to a reader that we don't expect this to overflow (and catches the mistake in case we do). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-16Win32: reliably detect console pipe handlesLibravatar Karsten Blees1-18/+7
As of "Win32: Thread-safe windows console output", child processes may print to the console even if stdout has been redirected to a file. E.g.: git config tar.cat.command "cat" git archive -o test.cat HEAD Detecting whether stdout / stderr point to our console pipe is currently based on the assumption that OS HANDLE values are never reused. This is apparently not true if stdout / stderr is replaced via dup2() (as in builtin/archive.c:17). Instead of comparing handle values, check if the file descriptor isatty() backed by a pipe OS handle. This is only possible by swapping the handles in MSVCRT's internal data structures, as we do in winansi_init(). Reported-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-10Win32: fix broken pipe detectionLibravatar Karsten Blees1-44/+70
As of "Win32: Thread-safe windows console output", git-log no longer terminates when the pager process dies. This is due to disabling buffering for the replaced stdout / stderr streams. Git-log will periodically fflush stdout (see write_or_die.c/mayble_flush_or_die()), but with no buffering, this is a NOP that always succeeds (so we never detect the EPIPE error). Exchange the original console handles with our console thread pipe handles by accessing the internal MSVCRT data structures directly (which are exposed via __pioinfo for some reason). Implement this with minimal assumptions about the actual data structure to make it work with different (hopefully even future) MSVCRT versions. While messing with internal data structures is ugly, this patch solves the problem at the source instead of adding more workarounds. We no longer need the special winansi_isatty override, and the limitations documented in "Win32: Thread-safe windows console output" are gone (i.e. fdopen(1/2) returns unbuffered streams now, and isatty() for duped console file descriptors works as expected). Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-10Win32: Thread-safe windows console outputLibravatar Karsten Blees1-138/+263
Winansi.c has many static variables that are accessed and modified from the [v][f]printf / fputs functions overridden in the file. This may cause multi threaded git commands that print to the console to produce corrupted output or even crash. Additionally, winansi.c doesn't override all functions that can be used to print to the console (e.g. fwrite, write, fputc are missing), so that ANSI escapes don't work properly for some git commands (e.g. git-grep). Instead of doing ANSI emulation in just a few wrapped functions on top of the IO API, let's plug into the IO system and take advantage of the thread safety inherent to the IO system. Redirect stdout and stderr to a pipe if they point to the console. A background thread reads from the pipe, handles ANSI escape sequences and UTF-8 to UTF-16 conversion, then writes to the console. The pipe-based stdout and stderr replacements must be set to unbuffered, as MSVCRT doesn't support line buffering and fully buffered streams are inappropriate for console output. Due to the byte-oriented pipe, ANSI escape sequences and multi-byte UTF-8 sequences can no longer be expected to arrive in one piece. Replace the string-based ansi_emulate() with a simple stateful parser (this also fixes colored diff hunk headers, which were broken as of commit 2efcc977). Override isatty to return true for the pipes redirecting to the console. Exec/spawn obtain the original console handle to pass to the next process via winansi_get_osfhandle(). All other overrides are gone, the default stdio implementations work as expected with the piped stdout/stderr descriptors. Global variables are either initialized on startup (single threaded) or exclusively modified by the background thread. Threads communicate through the pipe, no further synchronization is necessary. The background thread is terminated by disonnecting the pipe after flushing the stdio and pipe buffers. This doesn't work for anonymous pipes (created via CreatePipe), as DisconnectNamedPipe only works on the read end, which discards remaining data. Thus we have to setup the pipe manually, with the write end beeing the server (opened with CreateNamedPipe) and the read end the client (opened with CreateFile). Limitations: doesn't track reopened or duped file descriptors, i.e.: - fdopen(1/2) returns fully buffered streams - dup(1/2), dup2(1/2) returns normal pipe descriptors (i.e. isatty() = false, winansi_get_osfhandle won't return the original console handle) Currently, only the git-format-patch command uses xfdopen(xdup(1)) (see "realstdout" in builtin/log.c), but works well with these limitations. Many thanks to Atsushi Nakagawa <atnak@chejz.com> for suggesting and reviewing the thread-exit-mechanism. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-10Win32: warn if the console font doesn't support UnicodeLibravatar Karsten Blees1-0/+66
Unicode console output won't display correctly with default settings because the default console font ("Terminal") only supports the system's OEM charset. Unfortunately, this is a user specific setting, so it cannot be easily fixed by e.g. some registry tricks in the setup program. This change prints a warning on exit if console output contained non-ascii characters and the console font is supposedly not a TrueType font (which usually have decent Unicode support). Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-10Win32: detect console streams more reliablyLibravatar Karsten Blees1-24/+26
GetStdHandle(STD_OUTPUT_HANDLE) doesn't work for stderr if stdout is redirected. Use _get_osfhandle of the FILE* instead. _isatty() is true for all character devices (including parallel and serial ports). Check return value of GetConsoleScreenBufferInfo instead to reliably detect console handles (also don't initialize internal state from an uninitialized CONSOLE_SCREEN_BUFFER_INFO structure if the function fails). Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-10Win32: support Unicode console outputLibravatar Karsten Blees1-6/+20
WriteConsoleW seems to be the only way to reliably print unicode to the console (without weird code page conversions). Also redirects vfprintf to the winansi.c version. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Stepan Kasal <kasal@ucw.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-09-18Make usage of windows.h lean and meanLibravatar Marius Storm-Olsen1-1/+0
Centralize the include of windows.h in git-compat-util.h, turn on WIN32_LEAN_AND_MEAN to avoid including plenty of other header files which is not needed in Git. Also ensure we load winsock2.h first, so we don't load the older winsock definitions at a later stage, since they contain duplicate definitions. When moving windows.h into git-compat-util.h, we need to protect the definition of struct pollfd in mingw.h, since this file is used by both MinGW and MSVC, and the latter defines this struct in winsock2.h. We need to keep the windows.h include in compat/win32.h, since its shared by both MinGW and Cygwin, and we're not touching Cygwin in this commit. The include in git-compat-util.h is protected with an ifdef WIN32, which is not the case when compiling for Cygwin. Signed-off-by: Marius Storm-Olsen <mstormo@gmail.com> Acked-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-01Work around a regression in Windows 7, causing erase_in_line() to crash ↵Libravatar Johannes Schindelin1-1/+2
sometimes The function FillConsoleOutputCharacterA() was pretty content in XP to take a NULL pointer if we did not want to store the number of written columns. In Windows 7, it crashes, but only when called from within Git Bash, not from within cmd.exe. Go figure. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Steffen Prohaska <prohaska@zib.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-03-10winansi: support ESC [ K (erase in line)Libravatar Johannes Schindelin1-3/+15
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-19Add ANSI control code emulation for the Windows consoleLibravatar Peter Harris1-0/+345
This adds only the minimum necessary to keep git pull/merge's diffstat from wrapping. Notably absent is support for the K (erase) operation, and support for POSIX write. Signed-off-by: Peter Harris <git@peter.is-a-geek.org> Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>