Files
git/compat/terminal.c
Erik Faye-Lund 431fa8f83c compat/terminal: support echoing on windows
Without /dev/tty support, git_terminal_prompt simply ignores the
'echo'-parameter. On Windows we can do better by clevering up our
getpass-implementation a bit so it can conditionally echo.

While we're at it, plug a small memory-leak by returning a pointer
to a static strbuf instead of detaching it. This is the same thing
the /dev/tty-version of git_terminal_prompt does, and the callee
doesn't expect to have to free it's memory.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
2012-10-01 14:35:45 +01:00

103 lines
1.5 KiB
C

#include "git-compat-util.h"
#include "compat/terminal.h"
#include "sigchain.h"
#include "strbuf.h"
#ifdef HAVE_DEV_TTY
static int term_fd = -1;
static struct termios old_term;
static void restore_term(void)
{
if (term_fd < 0)
return;
tcsetattr(term_fd, TCSAFLUSH, &old_term);
term_fd = -1;
}
static void restore_term_on_signal(int sig)
{
restore_term();
sigchain_pop(sig);
raise(sig);
}
char *git_terminal_prompt(const char *prompt, int echo)
{
static struct strbuf buf = STRBUF_INIT;
int r;
FILE *fh;
fh = fopen("/dev/tty", "w+");
if (!fh)
return NULL;
if (!echo) {
struct termios t;
if (tcgetattr(fileno(fh), &t) < 0) {
fclose(fh);
return NULL;
}
old_term = t;
term_fd = fileno(fh);
sigchain_push_common(restore_term_on_signal);
t.c_lflag &= ~ECHO;
if (tcsetattr(fileno(fh), TCSAFLUSH, &t) < 0) {
term_fd = -1;
fclose(fh);
return NULL;
}
}
fputs(prompt, fh);
fflush(fh);
r = strbuf_getline(&buf, fh, '\n');
if (!echo) {
fseek(fh, SEEK_CUR, 0);
putc('\n', fh);
fflush(fh);
}
restore_term();
fclose(fh);
if (r == EOF)
return NULL;
return buf.buf;
}
#elif defined(WIN32)
char *git_terminal_prompt(const char *prompt, int echo)
{
static struct strbuf buf = STRBUF_INIT;
fputs(prompt, stderr);
strbuf_reset(&buf);
for (;;) {
int c = _getch();
if (c == '\n' || c == '\r')
break;
if (echo)
putc(c, stderr);
strbuf_addch(&buf, c);
}
putc('\n', stderr);
return buf.buf;
}
#else
char *git_terminal_prompt(const char *prompt, int echo)
{
return getpass(prompt);
}
#endif