mirror of
https://github.com/git/git.git
synced 2024-11-02 15:28:21 +01:00
67fe735653
On Windows, the terminal cannot be opened in read-write mode, so we need distinct pairs for reading and writing. Since this works fine on other platforms as well, always open them in pairs. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
96 lines
1.5 KiB
C
96 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);
|
|
close(term_fd);
|
|
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;
|
|
|
|
term_fd = open("/dev/tty", O_RDWR);
|
|
if (tcgetattr(term_fd, &t) < 0)
|
|
goto error;
|
|
|
|
old_term = t;
|
|
sigchain_push_common(restore_term_on_signal);
|
|
|
|
t.c_lflag &= ~ECHO;
|
|
if (!tcsetattr(term_fd, TCSAFLUSH, &t))
|
|
return 0;
|
|
|
|
error:
|
|
close(term_fd);
|
|
term_fd = -1;
|
|
return -1;
|
|
}
|
|
|
|
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");
|
|
if (!input_fh)
|
|
return NULL;
|
|
|
|
output_fh = fopen("/dev/tty", "w");
|
|
if (!output_fh) {
|
|
fclose(input_fh);
|
|
return NULL;
|
|
}
|
|
|
|
if (!echo && disable_echo()) {
|
|
fclose(input_fh);
|
|
fclose(output_fh);
|
|
return NULL;
|
|
}
|
|
|
|
fputs(prompt, output_fh);
|
|
fflush(output_fh);
|
|
|
|
r = strbuf_getline(&buf, input_fh, '\n');
|
|
if (!echo) {
|
|
putc('\n', output_fh);
|
|
fflush(output_fh);
|
|
}
|
|
|
|
restore_term();
|
|
fclose(input_fh);
|
|
fclose(output_fh);
|
|
|
|
if (r == EOF)
|
|
return NULL;
|
|
return buf.buf;
|
|
}
|
|
|
|
#else
|
|
|
|
char *git_terminal_prompt(const char *prompt, int echo)
|
|
{
|
|
return getpass(prompt);
|
|
}
|
|
|
|
#endif
|