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