зеркало из https://github.com/microsoft/git.git
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:
Родитель
67fe735653
Коммит
afb43561b8
|
@ -3,8 +3,22 @@
|
||||||
#include "sigchain.h"
|
#include "sigchain.h"
|
||||||
#include "strbuf.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
|
#ifdef HAVE_DEV_TTY
|
||||||
|
|
||||||
|
#define INPUT_PATH "/dev/tty"
|
||||||
|
#define OUTPUT_PATH "/dev/tty"
|
||||||
|
|
||||||
static int term_fd = -1;
|
static int term_fd = -1;
|
||||||
static struct termios old_term;
|
static struct termios old_term;
|
||||||
|
|
||||||
|
@ -18,13 +32,6 @@ static void restore_term(void)
|
||||||
term_fd = -1;
|
term_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_term_on_signal(int sig)
|
|
||||||
{
|
|
||||||
restore_term();
|
|
||||||
sigchain_pop(sig);
|
|
||||||
raise(sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int disable_echo(void)
|
static int disable_echo(void)
|
||||||
{
|
{
|
||||||
struct termios t;
|
struct termios t;
|
||||||
|
@ -46,17 +53,61 @@ error:
|
||||||
return -1;
|
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)
|
char *git_terminal_prompt(const char *prompt, int echo)
|
||||||
{
|
{
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
int r;
|
int r;
|
||||||
FILE *input_fh, *output_fh;
|
FILE *input_fh, *output_fh;
|
||||||
|
|
||||||
input_fh = fopen("/dev/tty", "r");
|
input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
|
||||||
if (!input_fh)
|
if (!input_fh)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
output_fh = fopen("/dev/tty", "w");
|
output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT);
|
||||||
if (!output_fh) {
|
if (!output_fh) {
|
||||||
fclose(input_fh);
|
fclose(input_fh);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче