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
26
-
27
- /* In this file, we actually want to use Windows' own isatty(). */
28
- #undef isatty
12
+ #define FD_CONSOLE 0x1
13
+ #define FD_SWAPPED 0x2
14
+ #define FD_MSYS 0x4
29
15
30
16
/*
31
17
ANSI codes used by git: m, K
@@ -96,6 +82,7 @@ static void warn_if_raster_font(void)
96
82
static int is_console (int fd )
97
83
{
98
84
CONSOLE_SCREEN_BUFFER_INFO sbi ;
85
+ DWORD mode ;
99
86
HANDLE hcon ;
100
87
101
88
static int initialized = 0 ;
@@ -110,12 +97,14 @@ static int is_console(int fd)
110
97
return 0 ;
111
98
112
99
/* check if its a handle to a console output screen buffer */
113
- if (!GetConsoleScreenBufferInfo (hcon , & sbi ))
100
+ if (!fd ) {
101
+ if (!GetConsoleMode (hcon , & mode ))
102
+ return 0 ;
103
+ } else if (!GetConsoleScreenBufferInfo (hcon , & sbi ))
114
104
return 0 ;
115
105
116
- #if defined(_MSC_VER )
117
- set_interactive (fd , MY_INTERACTIVE_CONSOLE );
118
- #endif
106
+ if (fd >= 0 && fd <= 2 )
107
+ fd_is_interactive [fd ] |= FD_CONSOLE ;
119
108
120
109
/* initialize attributes */
121
110
if (!initialized ) {
@@ -478,131 +467,52 @@ static HANDLE duplicate_handle(HANDLE hnd)
478
467
return hresult ;
479
468
}
480
469
481
- #if defined(_MSC_VER )
482
470
static HANDLE swap_osfhnd (int fd , HANDLE new_handle )
483
471
{
484
- DWORD key_std = ((fd == 1 ) ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
485
-
486
472
/*
487
473
* Create a copy of the original handle associated with fd
488
474
* because the original will get closed when we dup2().
489
475
*/
490
- HANDLE h_original = (HANDLE )_get_osfhandle (fd );
491
- HANDLE h_copy_original = duplicate_handle (h_original );
476
+ HANDLE handle = (HANDLE )_get_osfhandle (fd );
477
+ HANDLE duplicate = duplicate_handle (handle );
492
478
493
479
/* Create a temp fd associated with the already open "new_handle". */
494
- int fd_temp = _open_osfhandle ((intptr_t )new_handle , O_BINARY );
480
+ int new_fd = _open_osfhandle ((intptr_t )new_handle , O_BINARY );
495
481
496
482
assert ((fd == 1 ) || (fd == 2 ));
497
483
498
484
/*
499
485
* Use stock dup2() to re-bind fd to the new handle. Note that
500
486
* this will implicitly close(1) and close both fd=1 and the
501
487
* originally associated handle. It will open a new fd=1 and
502
- * call DuplicateHandle() on the handle associated with fd_temp .
488
+ * call DuplicateHandle() on the handle associated with new_fd .
503
489
* It is because of this implicit close() that we created the
504
490
* copy of the original.
505
491
*
506
492
* Note that the OS can recycle HANDLE (numbers) just like it
507
493
* recycles fd (numbers), so we must update the cached value
508
494
* of "console". You can use GetFileType() to see that
509
- * h_original and _get_osfhandle(fd) may have the same number
495
+ * handle and _get_osfhandle(fd) may have the same number
510
496
* value, but they refer to different actual files now.
511
497
*
512
498
* Note that dup2() when given target := {0,1,2} will also
513
499
* call SetStdHandle(), so we don't need to worry about that.
514
500
*/
515
- dup2 (fd_temp , fd );
516
- if (console == h_original )
517
- console = h_copy_original ;
518
- h_original = INVALID_HANDLE_VALUE ;
501
+ dup2 (new_fd , fd );
502
+ if (console == handle )
503
+ console = duplicate ;
504
+ handle = INVALID_HANDLE_VALUE ;
519
505
520
506
/* Close the temp fd. This explicitly closes "new_handle"
521
507
* (because it has been associated with it).
522
508
*/
523
- close (fd_temp );
524
-
525
- fd_is_interactive [fd ] |= MY_INTERACTIVE_SWAPPED ;
526
-
527
- return h_copy_original ;
528
- }
529
-
530
- #else
531
-
532
- /*
533
- * Make MSVCRT's internal file descriptor control structure accessible
534
- * so that we can tweak OS handles and flags directly (we need MSVCRT
535
- * to treat our pipe handle as if it were a console).
536
- *
537
- * We assume that the ioinfo structure (exposed by MSVCRT.dll via
538
- * __pioinfo) starts with the OS handle and the flags. The exact size
539
- * varies between MSVCRT versions, so we try different sizes until
540
- * toggling the FDEV bit of _pioinfo(1)->osflags is reflected in
541
- * isatty(1).
542
- */
543
- typedef struct {
544
- HANDLE osfhnd ;
545
- char osflags ;
546
- } ioinfo ;
547
-
548
- extern __declspec(dllimport ) ioinfo * __pioinfo [];
549
-
550
- static size_t sizeof_ioinfo = 0 ;
551
-
552
- #define IOINFO_L2E 5
553
- #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
554
-
555
- #define FPIPE 0x08
556
- #define FDEV 0x40
557
-
558
- static inline ioinfo * _pioinfo (int fd )
559
- {
560
- return (ioinfo * )((char * )__pioinfo [fd >> IOINFO_L2E ] +
561
- (fd & (IOINFO_ARRAY_ELTS - 1 )) * sizeof_ioinfo );
562
- }
509
+ close (new_fd );
563
510
564
- static int init_sizeof_ioinfo (void )
565
- {
566
- int istty , wastty ;
567
- /* don't init twice */
568
- if (sizeof_ioinfo )
569
- return sizeof_ioinfo >= 256 ;
570
-
571
- sizeof_ioinfo = sizeof (ioinfo );
572
- wastty = isatty (1 );
573
- while (sizeof_ioinfo < 256 ) {
574
- /* toggle FDEV flag, check isatty, then toggle back */
575
- _pioinfo (1 )-> osflags ^= FDEV ;
576
- istty = isatty (1 );
577
- _pioinfo (1 )-> osflags ^= FDEV ;
578
- /* return if we found the correct size */
579
- if (istty != wastty )
580
- return 0 ;
581
- sizeof_ioinfo += sizeof (void * );
582
- }
583
- error ("Tweaking file descriptors doesn't work with this MSVCRT.dll" );
584
- return 1 ;
585
- }
511
+ fd_is_interactive [fd ] |= FD_SWAPPED ;
586
512
587
- static HANDLE swap_osfhnd (int fd , HANDLE new_handle )
588
- {
589
- ioinfo * pioinfo ;
590
- HANDLE old_handle ;
591
-
592
- /* init ioinfo size if we haven't done so */
593
- if (init_sizeof_ioinfo ())
594
- return INVALID_HANDLE_VALUE ;
595
-
596
- /* get ioinfo pointer and change the handles */
597
- pioinfo = _pioinfo (fd );
598
- old_handle = pioinfo -> osfhnd ;
599
- pioinfo -> osfhnd = new_handle ;
600
- return old_handle ;
513
+ return duplicate ;
601
514
}
602
515
603
- #endif
604
-
605
-
606
516
#ifdef DETECT_MSYS_TTY
607
517
608
518
#include <winternl.h>
@@ -648,49 +558,25 @@ static void detect_msys_tty(int fd)
648
558
!wcsstr (name , L"-pty" ))
649
559
return ;
650
560
651
- #if defined(_MSC_VER )
652
- fd_is_interactive [fd ] |= MY_INTERACTIVE_MSYS ;
653
- #else
654
- /* init ioinfo size if we haven't done so */
655
- if (init_sizeof_ioinfo ())
656
- return ;
657
-
658
- /* set FDEV flag, reset FPIPE flag */
659
- _pioinfo (fd )-> osflags &= ~FPIPE ;
660
- _pioinfo (fd )-> osflags |= FDEV ;
661
- #endif
561
+ fd_is_interactive [fd ] |= FD_MSYS ;
662
562
}
663
563
664
564
#endif
665
565
566
+ /*
567
+ * Wrapper for isatty(). Most calls in the main git code
568
+ * call isatty(1 or 2) to see if the instance is interactive
569
+ * and should: be colored, show progress, paginate output.
570
+ * We lie and give results for what the descriptor WAS at
571
+ * startup (and ignore any pipe redirection we internally
572
+ * do).
573
+ */
574
+ #undef isatty
666
575
int winansi_isatty (int fd )
667
576
{
668
- int res = isatty (fd );
669
-
670
- if (res ) {
671
- /*
672
- * Make sure that /dev/null is not fooling Git into believing
673
- * that we are connected to a terminal, as "_isatty() returns a
674
- * nonzero value if the descriptor is associated with a
675
- * character device."; for more information, see
676
- *
677
- * https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx
678
- */
679
- HANDLE handle = (HANDLE )_get_osfhandle (fd );
680
- if (fd == STDIN_FILENO ) {
681
- DWORD dummy ;
682
-
683
- if (!GetConsoleMode (handle , & dummy ))
684
- res = 0 ;
685
- } else if (fd == STDOUT_FILENO || fd == STDERR_FILENO ) {
686
- CONSOLE_SCREEN_BUFFER_INFO dummy ;
687
-
688
- if (!GetConsoleScreenBufferInfo (handle , & dummy ))
689
- res = 0 ;
690
- }
691
- }
692
-
693
- return res ;
577
+ if (fd >= 0 && fd <= 2 )
578
+ return fd_is_interactive [fd ] != 0 ;
579
+ return isatty (fd );
694
580
}
695
581
696
582
void winansi_init (void )
@@ -702,10 +588,8 @@ void winansi_init(void)
702
588
con1 = is_console (1 );
703
589
con2 = is_console (2 );
704
590
705
- #if defined(_MSC_VER )
706
591
/* Also compute console bit for fd 0 even though we don't need the result here. */
707
592
is_console (0 );
708
- #endif
709
593
710
594
if (!con1 && !con2 ) {
711
595
#ifdef DETECT_MSYS_TTY
@@ -750,32 +634,10 @@ void winansi_init(void)
750
634
*/
751
635
HANDLE winansi_get_osfhandle (int fd )
752
636
{
753
- HANDLE hnd = (HANDLE ) _get_osfhandle (fd );
754
- if (isatty (fd ) && GetFileType (hnd ) == FILE_TYPE_PIPE ) {
755
- if (fd == 1 && hconsole1 )
756
- return hconsole1 ;
757
- else if (fd == 2 && hconsole2 )
758
- return hconsole2 ;
759
- }
760
- return hnd ;
761
- }
762
-
763
- #ifdef _MSC_VER
637
+ if (fd == 1 && (fd_is_interactive [1 ] & FD_SWAPPED ))
638
+ return hconsole1 ;
639
+ if (fd == 2 && (fd_is_interactive [2 ] & FD_SWAPPED ))
640
+ return hconsole2 ;
764
641
765
- /* Wrapper for isatty(). Most calls in the main git code
766
- * call isatty(1 or 2) to see if the instance is interactive
767
- * and should: be colored, show progress, paginate output.
768
- * We lie and give results for what the descriptor WAS at
769
- * startup (and ignore any pipe redirection we internally
770
- * do).
771
- */
772
- #undef isatty
773
- int msc_isatty (fd )
774
- {
775
- if (fd >=0 && fd <= 2 )
776
- return fd_is_interactive [fd ] != 0 ;
777
- else
778
- return isatty (fd );
642
+ return (HANDLE )_get_osfhandle (fd );
779
643
}
780
-
781
- #endif
0 commit comments