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;