compat/terminal: factor out echo-disabling
[git/mingw.git] / compat / terminal.c
bloba6212ca3c988ca0e3ee71c397a79144e6b482fe8
1 #include "git-compat-util.h"
2 #include "compat/terminal.h"
3 #include "sigchain.h"
4 #include "strbuf.h"
6 #ifdef HAVE_DEV_TTY
8 static int term_fd = -1;
9 static struct termios old_term;
11 static void restore_term(void)
13 if (term_fd < 0)
14 return;
16 tcsetattr(term_fd, TCSAFLUSH, &old_term);
17 close(term_fd);
18 term_fd = -1;
21 static void restore_term_on_signal(int sig)
23 restore_term();
24 sigchain_pop(sig);
25 raise(sig);
28 static int disable_echo(void)
30 struct termios t;
32 term_fd = open("/dev/tty", O_RDWR);
33 if (tcgetattr(term_fd, &t) < 0)
34 goto error;
36 old_term = t;
37 sigchain_push_common(restore_term_on_signal);
39 t.c_lflag &= ~ECHO;
40 if (!tcsetattr(term_fd, TCSAFLUSH, &t))
41 return 0;
43 error:
44 close(term_fd);
45 term_fd = -1;
46 return -1;
49 char *git_terminal_prompt(const char *prompt, int echo)
51 static struct strbuf buf = STRBUF_INIT;
52 int r;
53 FILE *fh;
55 fh = fopen("/dev/tty", "w+");
56 if (!fh)
57 return NULL;
59 if (!echo && disable_echo()) {
60 fclose(fh);
61 return NULL;
64 fputs(prompt, fh);
65 fflush(fh);
67 r = strbuf_getline(&buf, fh, '\n');
68 if (!echo) {
69 fseek(fh, SEEK_CUR, 0);
70 putc('\n', fh);
71 fflush(fh);
74 restore_term();
75 fclose(fh);
77 if (r == EOF)
78 return NULL;
79 return buf.buf;
82 #else
84 char *git_terminal_prompt(const char *prompt, int echo)
86 return getpass(prompt);
89 #endif