Win32: detect console streams more reliably

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>

Karsten Blees committed Jul 31, 2010 at 00:04 UTC 143e615270bd17dcef0d8e5751dacc496eff687d
1 file changed +26 -24
compat/winansi.c
+26 -24
@@ -25,27 +25,39 @@ static HANDLE console;
25 static WORD plain_attr;
26 static WORD attr;
27 static int negative;
28 +static FILE *last_stream = NULL;
29
29 -static void init(void)
30 +static int is_console(FILE *stream)
31 {
32 CONSOLE_SCREEN_BUFFER_INFO sbi;
33 + HANDLE hcon;
34
35 static int initialized = 0;
34 - if (initialized)
35 - return;
36
37 - console = GetStdHandle(STD_OUTPUT_HANDLE);
38 - if (console == INVALID_HANDLE_VALUE)
39 - console = NULL;
37 + /* use cached value if stream hasn't changed */
38 + if (stream == last_stream)
39 + return console != NULL;
40
41 - if (!console)
42 - return;
41 + last_stream = stream;
42 + console = NULL;
43
44 - GetConsoleScreenBufferInfo(console, &sbi);
45 - attr = plain_attr = sbi.wAttributes;
46 - negative = 0;
44 + /* get OS handle of the stream */
45 + hcon = (HANDLE) _get_osfhandle(_fileno(stream));
46 + if (hcon == INVALID_HANDLE_VALUE)
47 + return 0;
48 +
49 + /* check if its a handle to a console output screen buffer */
50 + if (!GetConsoleScreenBufferInfo(hcon, &sbi))
51 + return 0;
52 +
53 + if (!initialized) {
54 + attr = plain_attr = sbi.wAttributes;
55 + negative = 0;
56 + initialized = 1;
57 + }
58
48 - initialized = 1;
59 + console = hcon;
60 + return 1;
61 }
62
63 static int write_console(const char *str, size_t len)
@@ -292,12 +304,7 @@ int winansi_fputs(const char *str, FILE *stream)
304 {
305 int rv;
306
295 - if (!isatty(fileno(stream)))
296 - return fputs(str, stream);
297 -
298 - init();
299 -
300 - if (!console)
307 + if (!is_console(stream))
308 return fputs(str, stream);
309
310 rv = ansi_emulate(str, stream);
@@ -315,12 +322,7 @@ int winansi_vfprintf(FILE *stream, const char *format, va_list list)
322 char *buf = small_buf;
323 va_list cp;
324
318 - if (!isatty(fileno(stream)))
319 - goto abort;
320 -
321 - init();
322 -
323 - if (!console)
325 + if (!is_console(stream))
326 goto abort;
327
328 va_copy(cp, list);