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 <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Erik Faye-Lund committed
Dec 4, 2012 at 09:10 UTC
afb43561b81b435216b5b8c59fdaa48255e662fb
1 file changed
+60
-9
compat/terminal.c
+60
-9
@@ -3,8 +3,22 @@
3
#include "sigchain.h"
4
#include "strbuf.h"
5
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
+
17
#ifdef HAVE_DEV_TTY
18
19
+#define INPUT_PATH "/dev/tty"
20
+#define OUTPUT_PATH "/dev/tty"
21
+
22
static int term_fd = -1;
23
static struct termios old_term;
24
@@ -18,13 +32,6 @@ static void restore_term(void)
32
term_fd = -1;
33
}
34
21
-static void restore_term_on_signal(int sig)
22
-{
23
- restore_term();
24
- sigchain_pop(sig);
25
- raise(sig);
26
-}
27
-
35
static int disable_echo(void)
36
{
37
struct termios t;
@@ -46,17 +53,61 @@ error:
53
return -1;
54
}
55
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
+
100
char *git_terminal_prompt(const char *prompt, int echo)
101
{
102
static struct strbuf buf = STRBUF_INIT;
103
int r;
104
FILE *input_fh, *output_fh;
105
55
- input_fh = fopen("/dev/tty", "r");
106
+ input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
107
if (!input_fh)
108
return NULL;
109
59
- output_fh = fopen("/dev/tty", "w");
110
+ output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT);
111
if (!output_fh) {
112
fclose(input_fh);
113
return NULL;