diff options
author | Erik Faye-Lund <kusmabite@gmail.com> | 2012-12-04 09:10:41 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-12-04 08:03:08 -0800 |
commit | afb43561b81b435216b5b8c59fdaa48255e662fb (patch) | |
tree | 912bf5955c89458b75fe80db236a96ab1d385ff2 | |
parent | compat/terminal: separate input and output handles (diff) | |
download | tgif-afb43561b81b435216b5b8c59fdaa48255e662fb.tar.xz |
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>
-rw-r--r-- | compat/terminal.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/compat/terminal.c b/compat/terminal.c index 9aecad68a0..9b5e3d1bb8 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -3,8 +3,22 @@ #include "sigchain.h" #include "strbuf.h" +#if defined(HAVE_DEV_TTY) || defined(WIN32) + +static void restore_term(void); + +static void restore_term_on_signal(int sig) +{ + restore_term(); + sigchain_pop(sig); + raise(sig); +} + #ifdef HAVE_DEV_TTY +#define INPUT_PATH "/dev/tty" +#define OUTPUT_PATH "/dev/tty" + static int term_fd = -1; static struct termios old_term; @@ -18,13 +32,6 @@ static void restore_term(void) term_fd = -1; } -static void restore_term_on_signal(int sig) -{ - restore_term(); - sigchain_pop(sig); - raise(sig); -} - static int disable_echo(void) { struct termios t; @@ -46,17 +53,61 @@ error: return -1; } +#elif defined(WIN32) + +#define INPUT_PATH "CONIN$" +#define OUTPUT_PATH "CONOUT$" +#define FORCE_TEXT "t" + +static HANDLE hconin = INVALID_HANDLE_VALUE; +static DWORD cmode; + +static void restore_term(void) +{ + if (hconin == INVALID_HANDLE_VALUE) + return; + + SetConsoleMode(hconin, cmode); + CloseHandle(hconin); + hconin = INVALID_HANDLE_VALUE; +} + +static int disable_echo(void) +{ + hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hconin == INVALID_HANDLE_VALUE) + return -1; + + GetConsoleMode(hconin, &cmode); + sigchain_push_common(restore_term_on_signal); + if (!SetConsoleMode(hconin, cmode & (~ENABLE_ECHO_INPUT))) { + CloseHandle(hconin); + hconin = INVALID_HANDLE_VALUE; + return -1; + } + + return 0; +} + +#endif + +#ifndef FORCE_TEXT +#define FORCE_TEXT +#endif + char *git_terminal_prompt(const char *prompt, int echo) { static struct strbuf buf = STRBUF_INIT; int r; FILE *input_fh, *output_fh; - input_fh = fopen("/dev/tty", "r"); + input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT); if (!input_fh) return NULL; - output_fh = fopen("/dev/tty", "w"); + output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT); if (!output_fh) { fclose(input_fh); return NULL; |