diff options
Diffstat (limited to 'compat/terminal.c')
-rw-r--r-- | compat/terminal.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/compat/terminal.c b/compat/terminal.c new file mode 100644 index 0000000000..6d16c8fba0 --- /dev/null +++ b/compat/terminal.c @@ -0,0 +1,81 @@ +#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) { + putc('\n', fh); + fflush(fh); + } + + restore_term(); + fclose(fh); + + if (r == EOF) + return NULL; + return buf.buf; +} + +#else + +char *git_terminal_prompt(const char *prompt, int echo) +{ + return getpass(prompt); +} + +#endif |