]>
Commit | Line | Data |
---|---|---|
21aeafce JK |
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 | ||
8 | static int term_fd = -1; | |
9 | static struct termios old_term; | |
10 | ||
11 | static 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 | ||
20 | static void restore_term_on_signal(int sig) | |
21 | { | |
22 | restore_term(); | |
23 | sigchain_pop(sig); | |
24 | raise(sig); | |
25 | } | |
26 | ||
27 | char *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 | ||
76 | char *git_terminal_prompt(const char *prompt, int echo) | |
77 | { | |
78 | return getpass(prompt); | |
79 | } | |
80 | ||
81 | #endif |