summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Erik Faye-Lund <kusmabite@gmail.com>2012-12-04 09:10:41 +0100
committerLibravatar Junio C Hamano <gitster@pobox.com>2012-12-04 08:03:08 -0800
commitafb43561b81b435216b5b8c59fdaa48255e662fb (patch)
tree912bf5955c89458b75fe80db236a96ab1d385ff2
parentcompat/terminal: separate input and output handles (diff)
downloadtgif-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.c69
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;