Skip to content
/ git Public
forked from git/git

Commit afb4356

Browse files
kusmagitster
authored andcommitted
mingw: reuse tty-version of git_terminal_prompt
The getpass-implementation we use on Windows isn't at all ideal; it works in raw-mode (as opposed to cooked mode), and as a result does not deal correcly with deletion, arrow-keys etc. Instead, use cooked mode to read a line at the time, allowing the C run-time to process the input properly. Since we set files to be opened in binary-mode by default on Windows, introduce a FORCE_TEXT macro that expands to the "t" modifier that forces the terminal to be opened in text-mode so we do not have to deal with CRLF issues. Signed-off-by: Erik Faye-Lund <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 67fe735 commit afb4356

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

compat/terminal.c

+60-9
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@
33
#include "sigchain.h"
44
#include "strbuf.h"
55

6+
#if defined(HAVE_DEV_TTY) || defined(WIN32)
7+
8+
static void restore_term(void);
9+
10+
static void restore_term_on_signal(int sig)
11+
{
12+
restore_term();
13+
sigchain_pop(sig);
14+
raise(sig);
15+
}
16+
617
#ifdef HAVE_DEV_TTY
718

19+
#define INPUT_PATH "/dev/tty"
20+
#define OUTPUT_PATH "/dev/tty"
21+
822
static int term_fd = -1;
923
static struct termios old_term;
1024

@@ -18,13 +32,6 @@ static void restore_term(void)
1832
term_fd = -1;
1933
}
2034

21-
static void restore_term_on_signal(int sig)
22-
{
23-
restore_term();
24-
sigchain_pop(sig);
25-
raise(sig);
26-
}
27-
2835
static int disable_echo(void)
2936
{
3037
struct termios t;
@@ -46,17 +53,61 @@ static int disable_echo(void)
4653
return -1;
4754
}
4855

56+
#elif defined(WIN32)
57+
58+
#define INPUT_PATH "CONIN$"
59+
#define OUTPUT_PATH "CONOUT$"
60+
#define FORCE_TEXT "t"
61+
62+
static HANDLE hconin = INVALID_HANDLE_VALUE;
63+
static DWORD cmode;
64+
65+
static void restore_term(void)
66+
{
67+
if (hconin == INVALID_HANDLE_VALUE)
68+
return;
69+
70+
SetConsoleMode(hconin, cmode);
71+
CloseHandle(hconin);
72+
hconin = INVALID_HANDLE_VALUE;
73+
}
74+
75+
static int disable_echo(void)
76+
{
77+
hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
78+
FILE_SHARE_READ, NULL, OPEN_EXISTING,
79+
FILE_ATTRIBUTE_NORMAL, NULL);
80+
if (hconin == INVALID_HANDLE_VALUE)
81+
return -1;
82+
83+
GetConsoleMode(hconin, &cmode);
84+
sigchain_push_common(restore_term_on_signal);
85+
if (!SetConsoleMode(hconin, cmode & (~ENABLE_ECHO_INPUT))) {
86+
CloseHandle(hconin);
87+
hconin = INVALID_HANDLE_VALUE;
88+
return -1;
89+
}
90+
91+
return 0;
92+
}
93+
94+
#endif
95+
96+
#ifndef FORCE_TEXT
97+
#define FORCE_TEXT
98+
#endif
99+
49100
char *git_terminal_prompt(const char *prompt, int echo)
50101
{
51102
static struct strbuf buf = STRBUF_INIT;
52103
int r;
53104
FILE *input_fh, *output_fh;
54105

55-
input_fh = fopen("/dev/tty", "r");
106+
input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
56107
if (!input_fh)
57108
return NULL;
58109

59-
output_fh = fopen("/dev/tty", "w");
110+
output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT);
60111
if (!output_fh) {
61112
fclose(input_fh);
62113
return NULL;

0 commit comments

Comments
 (0)