8
8
#include <winreg.h>
9
9
#include "win32.h"
10
10
11
- #if defined(_MSC_VER )
12
-
13
11
static int fd_is_interactive [3 ] = { 0 , 0 , 0 };
14
- #define MY_INTERACTIVE_CONSOLE 0x1
15
- #define MY_INTERACTIVE_SWAPPED 0x2
16
- #define MY_INTERACTIVE_MSYS 0x4
17
-
18
- /* Accumulate what we know about the inherited console descriptors. */
19
- static void set_interactive (int fd , int bit )
20
- {
21
- if (fd >=0 && fd <= 2 )
22
- fd_is_interactive [fd ] |= bit ;
23
- }
24
-
25
- #endif
12
+ #define FD_CONSOLE 0x1
13
+ #define FD_SWAPPED 0x2
14
+ #define FD_MSYS 0x4
26
15
27
16
/*
28
17
ANSI codes used by git: m, K
@@ -93,6 +82,7 @@ static void warn_if_raster_font(void)
93
82
static int is_console (int fd )
94
83
{
95
84
CONSOLE_SCREEN_BUFFER_INFO sbi ;
85
+ DWORD mode ;
96
86
HANDLE hcon ;
97
87
98
88
static int initialized = 0 ;
@@ -107,12 +97,14 @@ static int is_console(int fd)
107
97
return 0 ;
108
98
109
99
/* check if its a handle to a console output screen buffer */
110
- if (!GetConsoleScreenBufferInfo (hcon , & sbi ))
100
+ if (!fd ) {
101
+ if (!GetConsoleMode (hcon , & mode ))
102
+ return 0 ;
103
+ } else if (!GetConsoleScreenBufferInfo (hcon , & sbi ))
111
104
return 0 ;
112
105
113
- #if defined(_MSC_VER )
114
- set_interactive (fd , MY_INTERACTIVE_CONSOLE );
115
- #endif
106
+ if (fd >= 0 && fd <= 2 )
107
+ fd_is_interactive [fd ] |= FD_CONSOLE ;
116
108
117
109
/* initialize attributes */
118
110
if (!initialized ) {
@@ -475,131 +467,49 @@ static HANDLE duplicate_handle(HANDLE hnd)
475
467
return hresult ;
476
468
}
477
469
478
- #if defined(_MSC_VER )
479
470
static HANDLE swap_osfhnd (int fd , HANDLE new_handle )
480
471
{
481
- DWORD key_std = ((fd == 1 ) ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
482
-
483
472
/*
484
473
* Create a copy of the original handle associated with fd
485
474
* because the original will get closed when we dup2().
486
475
*/
487
- HANDLE h_original = (HANDLE )_get_osfhandle (fd );
488
- HANDLE h_copy_original = duplicate_handle (h_original );
476
+ HANDLE handle = (HANDLE )_get_osfhandle (fd );
477
+ HANDLE duplicate = duplicate_handle (handle );
489
478
490
479
/* Create a temp fd associated with the already open "new_handle". */
491
- int fd_temp = _open_osfhandle ((intptr_t )new_handle , O_BINARY );
480
+ int new_fd = _open_osfhandle ((intptr_t )new_handle , O_BINARY );
492
481
493
482
assert ((fd == 1 ) || (fd == 2 ));
494
483
495
484
/*
496
485
* Use stock dup2() to re-bind fd to the new handle. Note that
497
486
* this will implicitly close(1) and close both fd=1 and the
498
487
* originally associated handle. It will open a new fd=1 and
499
- * call DuplicateHandle() on the handle associated with fd_temp .
488
+ * call DuplicateHandle() on the handle associated with new_fd .
500
489
* It is because of this implicit close() that we created the
501
490
* copy of the original.
502
491
*
503
- * Note that the OS can recycle HANDLE (numbers) just like it
504
- * recycles fd (numbers), so we must update the cached value
505
- * of "console". You can use GetFileType() to see that
506
- * h_original and _get_osfhandle(fd) may have the same number
507
- * value, but they refer to different actual files now.
492
+ * Note that we need to update the cached console handle to the
493
+ * duplicated one because the dup2() call will implicitly close
494
+ * the original one.
508
495
*
509
496
* Note that dup2() when given target := {0,1,2} will also
510
497
* call SetStdHandle(), so we don't need to worry about that.
511
498
*/
512
- dup2 (fd_temp , fd );
513
- if (console == h_original )
514
- console = h_copy_original ;
515
- h_original = INVALID_HANDLE_VALUE ;
499
+ if (console == handle )
500
+ console = duplicate ;
501
+ dup2 (new_fd , fd );
516
502
517
503
/* Close the temp fd. This explicitly closes "new_handle"
518
504
* (because it has been associated with it).
519
505
*/
520
- close (fd_temp );
506
+ close (new_fd );
521
507
522
- fd_is_interactive [fd ] |= MY_INTERACTIVE_SWAPPED ;
508
+ fd_is_interactive [fd ] |= FD_SWAPPED ;
523
509
524
- return h_copy_original ;
510
+ return duplicate ;
525
511
}
526
512
527
- #else
528
-
529
- /*
530
- * Make MSVCRT's internal file descriptor control structure accessible
531
- * so that we can tweak OS handles and flags directly (we need MSVCRT
532
- * to treat our pipe handle as if it were a console).
533
- *
534
- * We assume that the ioinfo structure (exposed by MSVCRT.dll via
535
- * __pioinfo) starts with the OS handle and the flags. The exact size
536
- * varies between MSVCRT versions, so we try different sizes until
537
- * toggling the FDEV bit of _pioinfo(1)->osflags is reflected in
538
- * isatty(1).
539
- */
540
- typedef struct {
541
- HANDLE osfhnd ;
542
- char osflags ;
543
- } ioinfo ;
544
-
545
- extern __declspec(dllimport ) ioinfo * __pioinfo [];
546
-
547
- static size_t sizeof_ioinfo = 0 ;
548
-
549
- #define IOINFO_L2E 5
550
- #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
551
-
552
- #define FPIPE 0x08
553
- #define FDEV 0x40
554
-
555
- static inline ioinfo * _pioinfo (int fd )
556
- {
557
- return (ioinfo * )((char * )__pioinfo [fd >> IOINFO_L2E ] +
558
- (fd & (IOINFO_ARRAY_ELTS - 1 )) * sizeof_ioinfo );
559
- }
560
-
561
- static int init_sizeof_ioinfo (void )
562
- {
563
- int istty , wastty ;
564
- /* don't init twice */
565
- if (sizeof_ioinfo )
566
- return sizeof_ioinfo >= 256 ;
567
-
568
- sizeof_ioinfo = sizeof (ioinfo );
569
- wastty = isatty (1 );
570
- while (sizeof_ioinfo < 256 ) {
571
- /* toggle FDEV flag, check isatty, then toggle back */
572
- _pioinfo (1 )-> osflags ^= FDEV ;
573
- istty = isatty (1 );
574
- _pioinfo (1 )-> osflags ^= FDEV ;
575
- /* return if we found the correct size */
576
- if (istty != wastty )
577
- return 0 ;
578
- sizeof_ioinfo += sizeof (void * );
579
- }
580
- error ("Tweaking file descriptors doesn't work with this MSVCRT.dll" );
581
- return 1 ;
582
- }
583
-
584
- static HANDLE swap_osfhnd (int fd , HANDLE new_handle )
585
- {
586
- ioinfo * pioinfo ;
587
- HANDLE old_handle ;
588
-
589
- /* init ioinfo size if we haven't done so */
590
- if (init_sizeof_ioinfo ())
591
- return INVALID_HANDLE_VALUE ;
592
-
593
- /* get ioinfo pointer and change the handles */
594
- pioinfo = _pioinfo (fd );
595
- old_handle = pioinfo -> osfhnd ;
596
- pioinfo -> osfhnd = new_handle ;
597
- return old_handle ;
598
- }
599
-
600
- #endif
601
-
602
-
603
513
#ifdef DETECT_MSYS_TTY
604
514
605
515
#include <winternl.h>
@@ -645,21 +555,27 @@ static void detect_msys_tty(int fd)
645
555
!wcsstr (name , L"-pty" ))
646
556
return ;
647
557
648
- #if defined(_MSC_VER )
649
- fd_is_interactive [fd ] |= MY_INTERACTIVE_MSYS ;
650
- #else
651
- /* init ioinfo size if we haven't done so */
652
- if (init_sizeof_ioinfo ())
653
- return ;
654
-
655
- /* set FDEV flag, reset FPIPE flag */
656
- _pioinfo (fd )-> osflags &= ~FPIPE ;
657
- _pioinfo (fd )-> osflags |= FDEV ;
658
- #endif
558
+ fd_is_interactive [fd ] |= FD_MSYS ;
659
559
}
660
560
661
561
#endif
662
562
563
+ /*
564
+ * Wrapper for isatty(). Most calls in the main git code
565
+ * call isatty(1 or 2) to see if the instance is interactive
566
+ * and should: be colored, show progress, paginate output.
567
+ * We lie and give results for what the descriptor WAS at
568
+ * startup (and ignore any pipe redirection we internally
569
+ * do).
570
+ */
571
+ #undef isatty
572
+ int winansi_isatty (int fd )
573
+ {
574
+ if (fd >= 0 && fd <= 2 )
575
+ return fd_is_interactive [fd ] != 0 ;
576
+ return isatty (fd );
577
+ }
578
+
663
579
void winansi_init (void )
664
580
{
665
581
int con1 , con2 ;
@@ -669,10 +585,8 @@ void winansi_init(void)
669
585
con1 = is_console (1 );
670
586
con2 = is_console (2 );
671
587
672
- #if defined(_MSC_VER )
673
588
/* Also compute console bit for fd 0 even though we don't need the result here. */
674
589
is_console (0 );
675
- #endif
676
590
677
591
if (!con1 && !con2 ) {
678
592
#ifdef DETECT_MSYS_TTY
@@ -717,32 +631,10 @@ void winansi_init(void)
717
631
*/
718
632
HANDLE winansi_get_osfhandle (int fd )
719
633
{
720
- HANDLE hnd = (HANDLE ) _get_osfhandle (fd );
721
- if (isatty (fd ) && GetFileType (hnd ) == FILE_TYPE_PIPE ) {
722
- if (fd == 1 && hconsole1 )
723
- return hconsole1 ;
724
- else if (fd == 2 && hconsole2 )
725
- return hconsole2 ;
726
- }
727
- return hnd ;
728
- }
634
+ if (fd == 1 && (fd_is_interactive [1 ] & FD_SWAPPED ))
635
+ return hconsole1 ;
636
+ if (fd == 2 && (fd_is_interactive [2 ] & FD_SWAPPED ))
637
+ return hconsole2 ;
729
638
730
- #ifdef _MSC_VER
731
-
732
- /* Wrapper for isatty(). Most calls in the main git code
733
- * call isatty(1 or 2) to see if the instance is interactive
734
- * and should: be colored, show progress, paginate output.
735
- * We lie and give results for what the descriptor WAS at
736
- * startup (and ignore any pipe redirection we internally
737
- * do).
738
- */
739
- #undef isatty
740
- int msc_isatty (fd )
741
- {
742
- if (fd >=0 && fd <= 2 )
743
- return fd_is_interactive [fd ] != 0 ;
744
- else
745
- return isatty (fd );
639
+ return (HANDLE )_get_osfhandle (fd );
746
640
}
747
-
748
- #endif
0 commit comments