From dac3c16ec912e9155dce1cd6956668879e17cebc Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Thu, 7 May 2015 14:09:00 +0200 Subject: [PATCH 1/7] fixup! mingw: Support `git_terminal_prompt` with more terminals Use 'read -r', so that '\' is interpreted verbatim rather than as escape character. Signed-off-by: Karsten Blees --- compat/terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/terminal.c b/compat/terminal.c index d9e5474deb02e1..9e3c7f37cbd7b4 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -98,7 +98,7 @@ static char *xterm_prompt(const char *prompt, int echo) { const char *read_input[] = { "sh", "-c", - "cat >/dev/tty && read line /dev/tty && read -r line Date: Thu, 7 May 2015 14:12:22 +0200 Subject: [PATCH 2/7] fixup! mingw: Support `git_terminal_prompt` with more terminals Also strip trailing CRLF instead of just LF or just CR. Signed-off-by: Karsten Blees --- compat/terminal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 9e3c7f37cbd7b4..b24d67cef77cc9 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -137,10 +137,8 @@ static char *xterm_prompt(const char *prompt, int echo) goto ret; } - if (len && buffer.buf[len - 1] == '\n') - strbuf_setlen(&buffer, len - 1); - if (len && buffer.buf[len - 1] == '\r') - strbuf_setlen(&buffer, len - 1); + strbuf_strip_suffix(&buffer, "\n"); + strbuf_strip_suffix(&buffer, "\r"); ret: if (!code) From 31741afb0c1f2fa0b609669db32e9d88f7ef2b7e Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Thu, 7 May 2015 14:18:28 +0200 Subject: [PATCH 3/7] fixup! mingw: Support `git_terminal_prompt` with more terminals Use strbuf_reset() instead of strbuf_setlen(..., 0). Signed-off-by: Karsten Blees --- compat/terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/terminal.c b/compat/terminal.c index b24d67cef77cc9..2842fe7429f769 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -129,7 +129,7 @@ static char *xterm_prompt(const char *prompt, int echo) } close(child.in); - strbuf_setlen(&buffer, 0); + strbuf_reset(&buffer); len = strbuf_read(&buffer, child.out, 1024); close(child.out); if (len < 0) { From 03a9c6649bc9cbb8279cc105099fb7ccb7f630e2 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sat, 9 May 2015 00:05:11 +0200 Subject: [PATCH 4/7] fixup! mingw: Support `git_terminal_prompt` with more terminals Move 'close(child.out)' down. Signed-off-by: Karsten Blees --- compat/terminal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 2842fe7429f769..025960d80e9bf2 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -124,14 +124,12 @@ static char *xterm_prompt(const char *prompt, int echo) if (write_in_full(child.in, prompt, prompt_len) != prompt_len) { error("Could not write to xterm"); close(child.in); - close(child.out); goto ret; } close(child.in); strbuf_reset(&buffer); len = strbuf_read(&buffer, child.out, 1024); - close(child.out); if (len < 0) { error("Could not read from xterm"); goto ret; @@ -141,6 +139,7 @@ static char *xterm_prompt(const char *prompt, int echo) strbuf_strip_suffix(&buffer, "\r"); ret: + close(child.out); if (!code) finish_command(&child); From 297b780dc8a50d9091b68bbd1d8a974a6488d43c Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Fri, 8 May 2015 23:40:29 +0200 Subject: [PATCH 5/7] fixup! mingw: Support `git_terminal_prompt` with more terminals Reduce shell invocations by chaining commands together. Use 'echo' instead of 'printf \\n'. Use 'read -s' instead of 'stty [-]echo', because we don't have 'stty' in old msysgit. Use 'bash' instead of 'sh' as 'read -s' is bash-specific (in case we ever switch to dash or some other POSIX-only shell). Signed-off-by: Karsten Blees --- compat/terminal.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 025960d80e9bf2..4081eafa1b60f1 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -97,20 +97,16 @@ static int disable_echo(void) static char *xterm_prompt(const char *prompt, int echo) { const char *read_input[] = { - "sh", "-c", - "cat >/dev/tty && read -r line /dev/tty && read -r line /dev/tty && read -r -s line /dev/tty", NULL }; - const char *echo_off[] = { "sh", "-c", "stty -echo /dev/tty", NULL }; struct child_process child = CHILD_PROCESS_INIT; static struct strbuf buffer = STRBUF_INIT; int prompt_len = strlen(prompt), len = -1, code; - if (!echo && run_command_v_opt(echo_off, 0)) - warning("Could not disable echo on xterm"); - child.argv = read_input; child.in = -1; child.out = -1; @@ -143,12 +139,6 @@ static char *xterm_prompt(const char *prompt, int echo) if (!code) finish_command(&child); - if (!echo) { - if (run_command_v_opt(echo_on, 0)) - warning("Could not enable echo on xterm"); - run_command_v_opt(new_line, 0); - } - return len < 0 ? NULL : buffer.buf; } From bffea8755016195d83e5b675341b0492aa686346 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sat, 9 May 2015 00:14:13 +0200 Subject: [PATCH 6/7] fixup! mingw: Support `git_terminal_prompt` with more terminals 'xterm_prompt' is not xterm-specific, change function name and error messages to reflect this. 'start_command' already prints an error message on failure, we don't need another one. Also print the script's exit code on failure. Signed-off-by: Karsten Blees --- compat/terminal.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 4081eafa1b60f1..a923417d28bbdb 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -94,7 +94,7 @@ static int disable_echo(void) return 0; } -static char *xterm_prompt(const char *prompt, int echo) +static char *shell_prompt(const char *prompt, int echo) { const char *read_input[] = { /* Note: call 'bash' explicitly, as 'read -s' is bash-specific */ @@ -111,14 +111,11 @@ static char *xterm_prompt(const char *prompt, int echo) child.in = -1; child.out = -1; - code = start_command(&child); - if (code) { - error("Could not access xterm"); - goto ret; - } + if (start_command(&child)) + return NULL; if (write_in_full(child.in, prompt, prompt_len) != prompt_len) { - error("Could not write to xterm"); + error("could not write to prompt script"); close(child.in); goto ret; } @@ -127,7 +124,7 @@ static char *xterm_prompt(const char *prompt, int echo) strbuf_reset(&buffer); len = strbuf_read(&buffer, child.out, 1024); if (len < 0) { - error("Could not read from xterm"); + error("could not read from prompt script"); goto ret; } @@ -136,8 +133,11 @@ static char *xterm_prompt(const char *prompt, int echo) ret: close(child.out); - if (!code) - finish_command(&child); + code = finish_command(&child); + if (code) { + error("failed to execute prompt script (exit code %d)", code); + return NULL; + } return len < 0 ? NULL : buffer.buf; } @@ -157,7 +157,7 @@ char *git_terminal_prompt(const char *prompt, int echo) const char *term = getenv("TERM"); if (term && starts_with(term, "xterm")) - return xterm_prompt(prompt, echo); + return shell_prompt(prompt, echo); #endif input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT); From 761f1f546c94a643efe51e28f525c8cf6ca458cf Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sat, 9 May 2015 02:11:48 +0200 Subject: [PATCH 7/7] compat/terminal.c: only use the Windows console if bash 'read -r' fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing the Windows console through the special CONIN$ / CONOUT$ devices doesn't work properly for non-ASCII usernames an passwords. It also doesn't work for terminal emulators that hide the native console window (such as mintty), and 'TERM=xterm*' is not necessarily a reliable indicator for such terminals. The new shell_prompt() function, on the other hand, works fine for both MSys1 and MSys2, in native console windows as well as mintty, and properly supports Unicode. It just needs bash on the path (for 'read -s', which is bash-specific). On Windows, try to use the shell to read from the terminal. If that fails with ENOENT (i.e. bash was not found), use CONIN/OUT as fallback. Note: To test this, create a UTF-8 credential file with non-ASCII chars, e.g. in git-bash: 'echo url=http://täst.com > cred.txt'. Then in git-cmd, 'git credential fill --- compat/terminal.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index a923417d28bbdb..8479f6049ac451 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -110,6 +110,7 @@ static char *shell_prompt(const char *prompt, int echo) child.argv = read_input; child.in = -1; child.out = -1; + child.silent_exec_failure = 1; if (start_command(&child)) return NULL; @@ -153,11 +154,14 @@ char *git_terminal_prompt(const char *prompt, int echo) static struct strbuf buf = STRBUF_INIT; int r; FILE *input_fh, *output_fh; + #ifdef GIT_WINDOWS_NATIVE - const char *term = getenv("TERM"); - if (term && starts_with(term, "xterm")) - return shell_prompt(prompt, echo); + /* try shell_prompt first, fall back to CONIN/OUT if bash is missing */ + char *result = shell_prompt(prompt, echo); + if (result || errno != ENOENT) + return result; + #endif input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);