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>
This commit is contained in:
Erik Faye-Lund 2012-12-04 09:10:41 +01:00 committed by Junio C Hamano
parent 67fe735653
commit afb43561b8

View file

@ -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 @@ static int disable_echo(void)
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;