a6212ca3c988ca0e3ee71c397a79144e6b482fe8
   1#include "git-compat-util.h"
   2#include "compat/terminal.h"
   3#include "sigchain.h"
   4#include "strbuf.h"
   5
   6#ifdef HAVE_DEV_TTY
   7
   8static int term_fd = -1;
   9static struct termios old_term;
  10
  11static void restore_term(void)
  12{
  13        if (term_fd < 0)
  14                return;
  15
  16        tcsetattr(term_fd, TCSAFLUSH, &old_term);
  17        close(term_fd);
  18        term_fd = -1;
  19}
  20
  21static void restore_term_on_signal(int sig)
  22{
  23        restore_term();
  24        sigchain_pop(sig);
  25        raise(sig);
  26}
  27
  28static int disable_echo(void)
  29{
  30        struct termios t;
  31
  32        term_fd = open("/dev/tty", O_RDWR);
  33        if (tcgetattr(term_fd, &t) < 0)
  34                goto error;
  35
  36        old_term = t;
  37        sigchain_push_common(restore_term_on_signal);
  38
  39        t.c_lflag &= ~ECHO;
  40        if (!tcsetattr(term_fd, TCSAFLUSH, &t))
  41                return 0;
  42
  43error:
  44        close(term_fd);
  45        term_fd = -1;
  46        return -1;
  47}
  48
  49char *git_terminal_prompt(const char *prompt, int echo)
  50{
  51        static struct strbuf buf = STRBUF_INIT;
  52        int r;
  53        FILE *fh;
  54
  55        fh = fopen("/dev/tty", "w+");
  56        if (!fh)
  57                return NULL;
  58
  59        if (!echo && disable_echo()) {
  60                fclose(fh);
  61                return NULL;
  62        }
  63
  64        fputs(prompt, fh);
  65        fflush(fh);
  66
  67        r = strbuf_getline(&buf, fh, '\n');
  68        if (!echo) {
  69                fseek(fh, SEEK_CUR, 0);
  70                putc('\n', fh);
  71                fflush(fh);
  72        }
  73
  74        restore_term();
  75        fclose(fh);
  76
  77        if (r == EOF)
  78                return NULL;
  79        return buf.buf;
  80}
  81
  82#else
  83
  84char *git_terminal_prompt(const char *prompt, int echo)
  85{
  86        return getpass(prompt);
  87}
  88
  89#endif