about summary refs log tree commit diff
path: root/third_party/git/compat/terminal.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/git/compat/terminal.c')
-rw-r--r--third_party/git/compat/terminal.c388
1 files changed, 0 insertions, 388 deletions
diff --git a/third_party/git/compat/terminal.c b/third_party/git/compat/terminal.c
deleted file mode 100644
index 43b73ddc7589..000000000000
--- a/third_party/git/compat/terminal.c
+++ /dev/null
@@ -1,388 +0,0 @@
-#include "git-compat-util.h"
-#include "compat/terminal.h"
-#include "sigchain.h"
-#include "strbuf.h"
-#include "run-command.h"
-#include "string-list.h"
-#include "hashmap.h"
-
-#if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
-
-static void restore_term(void);
-
-static void restore_term_on_signal(int sig)
-{
-	restore_term();
-	sigchain_pop(sig);
-	raise(sig);
-}
-
-#ifdef HAVE_DEV_TTY
-
-#define INPUT_PATH "/dev/tty"
-#define OUTPUT_PATH "/dev/tty"
-
-static int term_fd = -1;
-static struct termios old_term;
-
-static void restore_term(void)
-{
-	if (term_fd < 0)
-		return;
-
-	tcsetattr(term_fd, TCSAFLUSH, &old_term);
-	close(term_fd);
-	term_fd = -1;
-}
-
-static int disable_bits(tcflag_t bits)
-{
-	struct termios t;
-
-	term_fd = open("/dev/tty", O_RDWR);
-	if (tcgetattr(term_fd, &t) < 0)
-		goto error;
-
-	old_term = t;
-	sigchain_push_common(restore_term_on_signal);
-
-	t.c_lflag &= ~bits;
-	if (!tcsetattr(term_fd, TCSAFLUSH, &t))
-		return 0;
-
-error:
-	close(term_fd);
-	term_fd = -1;
-	return -1;
-}
-
-static int disable_echo(void)
-{
-	return disable_bits(ECHO);
-}
-
-static int enable_non_canonical(void)
-{
-	return disable_bits(ICANON | ECHO);
-}
-
-#elif defined(GIT_WINDOWS_NATIVE)
-
-#define INPUT_PATH "CONIN$"
-#define OUTPUT_PATH "CONOUT$"
-#define FORCE_TEXT "t"
-
-static int use_stty = 1;
-static struct string_list stty_restore = STRING_LIST_INIT_DUP;
-static HANDLE hconin = INVALID_HANDLE_VALUE;
-static DWORD cmode;
-
-static void restore_term(void)
-{
-	if (use_stty) {
-		int i;
-		struct child_process cp = CHILD_PROCESS_INIT;
-
-		if (stty_restore.nr == 0)
-			return;
-
-		strvec_push(&cp.args, "stty");
-		for (i = 0; i < stty_restore.nr; i++)
-			strvec_push(&cp.args, stty_restore.items[i].string);
-		run_command(&cp);
-		string_list_clear(&stty_restore, 0);
-		return;
-	}
-
-	if (hconin == INVALID_HANDLE_VALUE)
-		return;
-
-	SetConsoleMode(hconin, cmode);
-	CloseHandle(hconin);
-	hconin = INVALID_HANDLE_VALUE;
-}
-
-static int disable_bits(DWORD bits)
-{
-	if (use_stty) {
-		struct child_process cp = CHILD_PROCESS_INIT;
-
-		strvec_push(&cp.args, "stty");
-
-		if (bits & ENABLE_LINE_INPUT) {
-			string_list_append(&stty_restore, "icanon");
-			strvec_push(&cp.args, "-icanon");
-		}
-
-		if (bits & ENABLE_ECHO_INPUT) {
-			string_list_append(&stty_restore, "echo");
-			strvec_push(&cp.args, "-echo");
-		}
-
-		if (bits & ENABLE_PROCESSED_INPUT) {
-			string_list_append(&stty_restore, "-ignbrk");
-			string_list_append(&stty_restore, "intr");
-			string_list_append(&stty_restore, "^c");
-			strvec_push(&cp.args, "ignbrk");
-			strvec_push(&cp.args, "intr");
-			strvec_push(&cp.args, "");
-		}
-
-		if (run_command(&cp) == 0)
-			return 0;
-
-		/* `stty` could not be executed; access the Console directly */
-		use_stty = 0;
-	}
-
-	hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
-	    FILE_SHARE_READ, NULL, OPEN_EXISTING,
-	    FILE_ATTRIBUTE_NORMAL, NULL);
-	if (hconin == INVALID_HANDLE_VALUE)
-		return -1;
-
-	GetConsoleMode(hconin, &cmode);
-	sigchain_push_common(restore_term_on_signal);
-	if (!SetConsoleMode(hconin, cmode & ~bits)) {
-		CloseHandle(hconin);
-		hconin = INVALID_HANDLE_VALUE;
-		return -1;
-	}
-
-	return 0;
-}
-
-static int disable_echo(void)
-{
-	return disable_bits(ENABLE_ECHO_INPUT);
-}
-
-static int enable_non_canonical(void)
-{
-	return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
-}
-
-/*
- * Override `getchar()`, as the default implementation does not use
- * `ReadFile()`.
- *
- * This poses a problem when we want to see whether the standard
- * input has more characters, as the default of Git for Windows is to start the
- * Bash in a MinTTY, which uses a named pipe to emulate a pty, in which case
- * our `poll()` emulation calls `PeekNamedPipe()`, which seems to require
- * `ReadFile()` to be called first to work properly (it only reports 0
- * available bytes, otherwise).
- *
- * So let's just override `getchar()` with a version backed by `ReadFile()` and
- * go our merry ways from here.
- */
-static int mingw_getchar(void)
-{
-	DWORD read = 0;
-	unsigned char ch;
-
-	if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &read, NULL))
-		return EOF;
-
-	if (!read) {
-		error("Unexpected 0 read");
-		return EOF;
-	}
-
-	return ch;
-}
-#define getchar mingw_getchar
-
-#endif
-
-#ifndef FORCE_TEXT
-#define FORCE_TEXT
-#endif
-
-char *git_terminal_prompt(const char *prompt, int echo)
-{
-	static struct strbuf buf = STRBUF_INIT;
-	int r;
-	FILE *input_fh, *output_fh;
-
-	input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT);
-	if (!input_fh)
-		return NULL;
-
-	output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT);
-	if (!output_fh) {
-		fclose(input_fh);
-		return NULL;
-	}
-
-	if (!echo && disable_echo()) {
-		fclose(input_fh);
-		fclose(output_fh);
-		return NULL;
-	}
-
-	fputs(prompt, output_fh);
-	fflush(output_fh);
-
-	r = strbuf_getline_lf(&buf, input_fh);
-	if (!echo) {
-		putc('\n', output_fh);
-		fflush(output_fh);
-	}
-
-	restore_term();
-	fclose(input_fh);
-	fclose(output_fh);
-
-	if (r == EOF)
-		return NULL;
-	return buf.buf;
-}
-
-/*
- * The `is_known_escape_sequence()` function returns 1 if the passed string
- * corresponds to an Escape sequence that the terminal capabilities contains.
- *
- * To avoid depending on ncurses or other platform-specific libraries, we rely
- * on the presence of the `infocmp` executable to do the job for us (failing
- * silently if the program is not available or refused to run).
- */
-struct escape_sequence_entry {
-	struct hashmap_entry entry;
-	char sequence[FLEX_ARRAY];
-};
-
-static int sequence_entry_cmp(const void *hashmap_cmp_fn_data,
-			      const struct escape_sequence_entry *e1,
-			      const struct escape_sequence_entry *e2,
-			      const void *keydata)
-{
-	return strcmp(e1->sequence, keydata ? keydata : e2->sequence);
-}
-
-static int is_known_escape_sequence(const char *sequence)
-{
-	static struct hashmap sequences;
-	static int initialized;
-
-	if (!initialized) {
-		struct child_process cp = CHILD_PROCESS_INIT;
-		struct strbuf buf = STRBUF_INIT;
-		char *p, *eol;
-
-		hashmap_init(&sequences, (hashmap_cmp_fn)sequence_entry_cmp,
-			     NULL, 0);
-
-		strvec_pushl(&cp.args, "infocmp", "-L", "-1", NULL);
-		if (pipe_command(&cp, NULL, 0, &buf, 0, NULL, 0))
-			strbuf_setlen(&buf, 0);
-
-		for (eol = p = buf.buf; *p; p = eol + 1) {
-			p = strchr(p, '=');
-			if (!p)
-				break;
-			p++;
-			eol = strchrnul(p, '\n');
-
-			if (starts_with(p, "\\E")) {
-				char *comma = memchr(p, ',', eol - p);
-				struct escape_sequence_entry *e;
-
-				p[0] = '^';
-				p[1] = '[';
-				FLEX_ALLOC_MEM(e, sequence, p, comma - p);
-				hashmap_entry_init(&e->entry,
-						   strhash(e->sequence));
-				hashmap_add(&sequences, &e->entry);
-			}
-			if (!*eol)
-				break;
-		}
-		initialized = 1;
-	}
-
-	return !!hashmap_get_from_hash(&sequences, strhash(sequence), sequence);
-}
-
-int read_key_without_echo(struct strbuf *buf)
-{
-	static int warning_displayed;
-	int ch;
-
-	if (warning_displayed || enable_non_canonical() < 0) {
-		if (!warning_displayed) {
-			warning("reading single keystrokes not supported on "
-				"this platform; reading line instead");
-			warning_displayed = 1;
-		}
-
-		return strbuf_getline(buf, stdin);
-	}
-
-	strbuf_reset(buf);
-	ch = getchar();
-	if (ch == EOF) {
-		restore_term();
-		return EOF;
-	}
-	strbuf_addch(buf, ch);
-
-	if (ch == '\033' /* ESC */) {
-		/*
-		 * We are most likely looking at an Escape sequence. Let's try
-		 * to read more bytes, waiting at most half a second, assuming
-		 * that the sequence is complete if we did not receive any byte
-		 * within that time.
-		 *
-		 * Start by replacing the Escape byte with ^[ */
-		strbuf_splice(buf, buf->len - 1, 1, "^[", 2);
-
-		/*
-		 * Query the terminal capabilities once about all the Escape
-		 * sequences it knows about, so that we can avoid waiting for
-		 * half a second when we know that the sequence is complete.
-		 */
-		while (!is_known_escape_sequence(buf->buf)) {
-			struct pollfd pfd = { .fd = 0, .events = POLLIN };
-
-			if (poll(&pfd, 1, 500) < 1)
-				break;
-
-			ch = getchar();
-			if (ch == EOF)
-				return 0;
-			strbuf_addch(buf, ch);
-		}
-	}
-
-	restore_term();
-	return 0;
-}
-
-#else
-
-char *git_terminal_prompt(const char *prompt, int echo)
-{
-	return getpass(prompt);
-}
-
-int read_key_without_echo(struct strbuf *buf)
-{
-	static int warning_displayed;
-	const char *res;
-
-	if (!warning_displayed) {
-		warning("reading single keystrokes not supported on this "
-			"platform; reading line instead");
-		warning_displayed = 1;
-	}
-
-	res = getpass("");
-	strbuf_reset(buf);
-	if (!res)
-		return EOF;
-	strbuf_addstr(buf, res);
-	return 0;
-}
-
-#endif