Skip to content
/ git Public
forked from git/git

Commit e22b245

Browse files
carenasgitster
authored andcommitted
terminal: teach git how to save/restore its terminal settings
Currently, git will share its console with all its children (unless they create their own), and is therefore possible that any of them that might change the settings for it could affect its operations once completed. Refactor the platform specific functionality to save the terminal settings and expand it to also do so for the output handler. This will allow for the state of the terminal to be saved and restored around a child that might misbehave (ex vi) which will be implemented next. Signed-off-by: Carlo Marcelo Arenas Belón <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 225bc32 commit e22b245

File tree

2 files changed

+63
-15
lines changed

2 files changed

+63
-15
lines changed

compat/terminal.c

+60-15
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
#if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
1010

11-
static void restore_term(void);
12-
1311
static void restore_term_on_signal(int sig)
1412
{
1513
restore_term();
@@ -25,7 +23,7 @@ static void restore_term_on_signal(int sig)
2523
static int term_fd = -1;
2624
static struct termios old_term;
2725

28-
static void restore_term(void)
26+
void restore_term(void)
2927
{
3028
if (term_fd < 0)
3129
return;
@@ -35,15 +33,22 @@ static void restore_term(void)
3533
term_fd = -1;
3634
}
3735

36+
int save_term(int full_duplex)
37+
{
38+
if (term_fd < 0)
39+
term_fd = open("/dev/tty", O_RDWR);
40+
41+
return (term_fd < 0) ? -1 : tcgetattr(term_fd, &old_term);
42+
}
43+
3844
static int disable_bits(tcflag_t bits)
3945
{
4046
struct termios t;
4147

42-
term_fd = open("/dev/tty", O_RDWR);
43-
if (tcgetattr(term_fd, &t) < 0)
48+
if (save_term(0) < 0)
4449
goto error;
4550

46-
old_term = t;
51+
t = old_term;
4752
sigchain_push_common(restore_term_on_signal);
4853

4954
t.c_lflag &= ~bits;
@@ -75,9 +80,10 @@ static int enable_non_canonical(void)
7580
static int use_stty = 1;
7681
static struct string_list stty_restore = STRING_LIST_INIT_DUP;
7782
static HANDLE hconin = INVALID_HANDLE_VALUE;
78-
static DWORD cmode;
83+
static HANDLE hconout = INVALID_HANDLE_VALUE;
84+
static DWORD cmode_in, cmode_out;
7985

80-
static void restore_term(void)
86+
void restore_term(void)
8187
{
8288
if (use_stty) {
8389
int i;
@@ -97,9 +103,42 @@ static void restore_term(void)
97103
if (hconin == INVALID_HANDLE_VALUE)
98104
return;
99105

100-
SetConsoleMode(hconin, cmode);
106+
SetConsoleMode(hconin, cmode_in);
107+
CloseHandle(hconin);
108+
if (cmode_out) {
109+
assert(hconout != INVALID_HANDLE_VALUE);
110+
SetConsoleMode(hconout, cmode_out);
111+
CloseHandle(hconout);
112+
}
113+
114+
hconin = hconout = INVALID_HANDLE_VALUE;
115+
}
116+
117+
int save_term(int full_duplex)
118+
{
119+
hconin = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE,
120+
FILE_SHARE_READ, NULL, OPEN_EXISTING,
121+
FILE_ATTRIBUTE_NORMAL, NULL);
122+
if (hconin == INVALID_HANDLE_VALUE)
123+
return -1;
124+
125+
if (full_duplex) {
126+
hconout = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE,
127+
FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
128+
FILE_ATTRIBUTE_NORMAL, NULL);
129+
if (hconout == INVALID_HANDLE_VALUE)
130+
goto error;
131+
132+
GetConsoleMode(hconout, &cmode_out);
133+
}
134+
135+
GetConsoleMode(hconin, &cmode_in);
136+
use_stty = 0;
137+
return 0;
138+
error:
101139
CloseHandle(hconin);
102140
hconin = INVALID_HANDLE_VALUE;
141+
return -1;
103142
}
104143

105144
static int disable_bits(DWORD bits)
@@ -135,15 +174,11 @@ static int disable_bits(DWORD bits)
135174
use_stty = 0;
136175
}
137176

138-
hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
139-
FILE_SHARE_READ, NULL, OPEN_EXISTING,
140-
FILE_ATTRIBUTE_NORMAL, NULL);
141-
if (hconin == INVALID_HANDLE_VALUE)
177+
if (save_term(0) < 0)
142178
return -1;
143179

144-
GetConsoleMode(hconin, &cmode);
145180
sigchain_push_common(restore_term_on_signal);
146-
if (!SetConsoleMode(hconin, cmode & ~bits)) {
181+
if (!SetConsoleMode(hconin, cmode_in & ~bits)) {
147182
CloseHandle(hconin);
148183
hconin = INVALID_HANDLE_VALUE;
149184
return -1;
@@ -361,6 +396,16 @@ int read_key_without_echo(struct strbuf *buf)
361396

362397
#else
363398

399+
int save_term(int full_duplex)
400+
{
401+
/* full_duplex == 1, but no support available */
402+
return -full_duplex;
403+
}
404+
405+
void restore_term(void)
406+
{
407+
}
408+
364409
char *git_terminal_prompt(const char *prompt, int echo)
365410
{
366411
return getpass(prompt);

compat/terminal.h

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef COMPAT_TERMINAL_H
22
#define COMPAT_TERMINAL_H
33

4+
int save_term(int full_duplex);
5+
void restore_term(void);
6+
47
char *git_terminal_prompt(const char *prompt, int echo);
58

69
/* Read a single keystroke, without echoing it to the terminal */

0 commit comments

Comments
 (0)