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);