Skip to content

Commit d56d2f8

Browse files
committed
squash! mingw: Support git_terminal_prompt with more terminals
Adjust the commit message with the following paragraph: The most prominent user of `git_terminal_prompt()` is certainly `git-remote-https.exe`. It is an interesting use case because both `stdin` and `stdout` are redirected when Git calls said executable, yet it still wants to access the terminal. When running inside a `mintty`, the terminal is not accessible to the `git-remote-https.exe` program, though, because it is a MinGW program and the `mintty` terminal is not backed by a Win32 console. To solve that problem, we simply call out to the shell -- which is an *MSys2* program and can therefore access `/dev/tty`.
1 parent a105bde commit d56d2f8

File tree

1 file changed

+44
-29
lines changed

1 file changed

+44
-29
lines changed

compat/terminal.c

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "compat/terminal.h"
55
#include "sigchain.h"
66
#include "strbuf.h"
7+
#include "cache.h"
78

89
#if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
910

@@ -95,49 +96,63 @@ static int disable_echo(void)
9596

9697
static char *xterm_prompt(const char *prompt, int echo)
9798
{
98-
const char *env = getenv("MSYS_TTY_HANDLES");
99+
const char *read_password[] = {
100+
"sh", "-c",
101+
"cat >/dev/tty && read line </dev/tty && echo \"$line\"",
102+
NULL
103+
};
99104
const char *echo_off[] = { "sh", "-c", "stty -echo </dev/tty", NULL };
100105
const char *echo_on[] = { "sh", "-c", "stty echo </dev/tty", NULL };
101-
static char buffer[1024];
102-
DWORD len, dummy;
103-
size_t tty0, tty1, tty2;
104-
HANDLE in_handle, out_handle;
105-
106-
if (!env || 3 != sscanf(env,
107-
" %" SCNuPTR " %" SCNuPTR " %" SCNuPTR " ",
108-
&tty0, &tty1, &tty2)) {
109-
warning("Cannot read from xterm");
110-
return NULL;
111-
}
112-
113-
in_handle = (HANDLE)tty0;
114-
out_handle = (HANDLE)tty1;
106+
const char *new_line[] = { "sh", "-c", "printf '\\n' >/dev/tty", NULL };
107+
struct child_process child = CHILD_PROCESS_INIT;
108+
static struct strbuf buffer = STRBUF_INIT;
109+
int prompt_len = strlen(prompt), len = -1, code;
115110

116111
if (!echo && run_command_v_opt(echo_off, 0))
117112
warning("Could not disable echo on xterm");
118113

119-
if (!WriteFile(out_handle, prompt, strlen(prompt), &dummy, NULL)) {
120-
warning("Could not write to xterm");
121-
return NULL;
114+
child.argv = read_password;
115+
child.in = -1;
116+
child.out = -1;
117+
118+
code = start_command(&child);
119+
if (code) {
120+
error("Could not access xterm");
121+
goto ret;
122122
}
123123

124-
if (!ReadFile(in_handle, buffer, 1024, &len, NULL)) {
125-
warning("Could not read from xterm");
126-
return NULL;
124+
if (write_in_full(child.in, prompt, prompt_len) != prompt_len) {
125+
error("Could not write to xterm");
126+
close(child.in);
127+
close(child.out);
128+
goto ret;
127129
}
130+
close(child.in);
131+
132+
strbuf_setlen(&buffer, 0);
133+
len = strbuf_read(&buffer, child.out, 1024);
134+
close(child.out);
135+
if (len < 0) {
136+
error("Could not read from xterm");
137+
goto ret;
138+
}
139+
140+
if (len && buffer.buf[len - 1] == '\n')
141+
strbuf_setlen(&buffer, len - 1);
142+
if (len && buffer.buf[len - 1] == '\r')
143+
strbuf_setlen(&buffer, len - 1);
128144

129-
if (len && buffer[len - 1] == '\n')
130-
buffer[--len] = '\0';
131-
if (len && buffer[len - 1] == '\r')
132-
buffer[--len] = '\0';
145+
ret:
146+
if (!code)
147+
finish_command(&child);
133148

134149
if (!echo) {
135-
if(run_command_v_opt(echo_on, 0))
136-
warning("Could not re-enable echo on xterm");
137-
WriteFile(out_handle, "\n", 1, &dummy, NULL);
150+
if (run_command_v_opt(echo_on, 0))
151+
warning("Could not enable echo on xterm");
152+
run_command_v_opt(new_line, 0);
138153
}
139154

140-
return len == 0 ? NULL : buffer;
155+
return len < 0 ? NULL : buffer.buf;
141156
}
142157

143158
#endif

0 commit comments

Comments
 (0)