From 01ccdd1d3c5221789f1ac62ced12b7984d910705 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 11 Jan 2017 16:17:59 +0100
Subject: libbb: consolidate the code to set termios unbuffered mode

function                                             old     new   delta
set_termios_to_raw                                     -     116    +116
count_lines                                           72      74      +2
powertop_main                                       1458    1430     -28
top_main                                             943     914     -29
more_main                                            759     714     -45
fsck_minix_main                                     2969    2921     -48
conspy_main                                         1197    1135     -62
rawmode                                               99      36     -63
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/6 up/down: 118/-275)         Total: -157 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c |  2 +-
 libbb/xfuncs.c   | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 31e392147..2a5d4e704 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2325,7 +2325,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 	/* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
 	/* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
 	new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
-	/* reads would block only if < 1 char is available */
+	/* reads will block only if < 1 char is available */
 	new_settings.c_cc[VMIN] = 1;
 	/* no timeout (reads block forever) */
 	new_settings.c_cc[VTIME] = 0;
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 45650edba..98d3531d6 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -311,6 +311,43 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
 	return tcsetattr(STDIN_FILENO, TCSANOW, tp);
 }
 
+int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags)
+{
+//TODO: lineedit, microcom and less might be adapted to use this too:
+// grep for "tcsetattr"
+
+	struct termios newterm;
+
+	tcgetattr(fd, oldterm);
+	newterm = *oldterm;
+
+	/* Turn off buffered input (ICANON)
+	 * Turn off echoing (ECHO)
+	 * and separate echoing of newline (ECHONL, normally off anyway)
+	 */
+	newterm.c_lflag &= ~(ICANON | ECHO | ECHONL);
+	if (flags & TERMIOS_CLEAR_ISIG) {
+		/* dont recognize INT/QUIT/SUSP chars */
+		newterm.c_lflag &= ~ISIG;
+	}
+	/* reads will block only if < 1 char is available */
+	newterm.c_cc[VMIN] = 1;
+	/* no timeout (reads block forever) */
+	newterm.c_cc[VTIME] = 0;
+	if (flags & TERMIOS_RAW_CRNL) {
+		/* dont convert CR to NL on input */
+		newterm.c_iflag &= ~(IXON | ICRNL);
+		/* dont convert NL to CR on output */
+		newterm.c_oflag &= ~(ONLCR);
+	}
+	if (flags & TERMIOS_RAW_INPUT) {
+		/* dont convert anything on input */
+		newterm.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL);
+	}
+
+	return tcsetattr(fd, TCSANOW, &newterm);
+}
+
 pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
 {
 	pid_t r;
-- 
cgit v1.2.3-55-g6feb