compat / terminal.con commit Merge branch 'maint' (d81c7d1)
   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        term_fd = -1;
  18}
  19
  20static void restore_term_on_signal(int sig)
  21{
  22        restore_term();
  23        sigchain_pop(sig);
  24        raise(sig);
  25}
  26
  27char *git_terminal_prompt(const char *prompt, int echo)
  28{
  29        static struct strbuf buf = STRBUF_INIT;
  30        int r;
  31        FILE *fh;
  32
  33        fh = fopen("/dev/tty", "w+");
  34        if (!fh)
  35                return NULL;
  36
  37        if (!echo) {
  38                struct termios t;
  39
  40                if (tcgetattr(fileno(fh), &t) < 0) {
  41                        fclose(fh);
  42                        return NULL;
  43                }
  44
  45                old_term = t;
  46                term_fd = fileno(fh);
  47                sigchain_push_common(restore_term_on_signal);
  48
  49                t.c_lflag &= ~ECHO;
  50                if (tcsetattr(fileno(fh), TCSAFLUSH, &t) < 0) {
  51                        term_fd = -1;
  52                        fclose(fh);
  53                        return NULL;
  54                }
  55        }
  56
  57        fputs(prompt, fh);
  58        fflush(fh);
  59
  60        r = strbuf_getline(&buf, fh, '\n');
  61        if (!echo) {
  62                putc('\n', fh);
  63                fflush(fh);
  64        }
  65
  66        restore_term();
  67        fclose(fh);
  68
  69        if (r == EOF)
  70                return NULL;
  71        return buf.buf;
  72}
  73
  74#else
  75
  76char *git_terminal_prompt(const char *prompt, int echo)
  77{
  78        return getpass(prompt);
  79}
  80
  81#endif