From 4dc35fb5b6b574552a432622274941a6e4c67476 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 8 Jul 2011 04:41:38 +0200
Subject: platform.h: tweaks for cygwin

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/Kbuild.src | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index a6e80e692..875d02456 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -97,7 +97,6 @@ lib-y += strrstr.o
 lib-y += time.o
 lib-y += trim.o
 lib-y += u_signal_names.o
-lib-y += udp_io.o
 lib-y += uuencode.o
 lib-y += vdprintf.o
 lib-y += verror_msg.o
@@ -127,6 +126,15 @@ lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
 lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o
 lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o
 
+lib-$(CONFIG_NC) += udp_io.o
+lib-$(CONFIG_DNSD) += udp_io.o
+lib-$(CONFIG_NTPD) += udp_io.o
+lib-$(CONFIG_TFTP) += udp_io.o
+lib-$(CONFIG_TFTPD) += udp_io.o
+lib-$(CONFIG_TCPSVD) += udp_io.o
+lib-$(CONFIG_UDPSVD) += udp_io.o
+lib-$(CONFIG_TRACEROUTE) += udp_io.o
+
 lib-$(CONFIG_LOSETUP) += loop.o
 lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
 
-- 
cgit v1.2.3-55-g6feb


From 8f6ce094dc780010e51e38bf96b9d107cefdd4b6 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 8 Jul 2011 08:34:28 +0200
Subject: a few tweaks for bionic

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/inet_common.c   | 3 ++-
 libbb/obscure.c       | 2 ++
 miscutils/adjtimex.c  | 6 +++++-
 miscutils/setserial.c | 2 +-
 4 files changed, 10 insertions(+), 3 deletions(-)

(limited to 'libbb')

diff --git a/libbb/inet_common.c b/libbb/inet_common.c
index 207720e96..7208db9ea 100644
--- a/libbb/inet_common.c
+++ b/libbb/inet_common.c
@@ -175,7 +175,8 @@ int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
 		return -1;
 	}
 	memcpy(sin6, ai->ai_addr, sizeof(*sin6));
-	freeaddrinfo(ai);
+	if (ai)
+		freeaddrinfo(ai);
 	return 0;
 }
 
diff --git a/libbb/obscure.c b/libbb/obscure.c
index dd8cd319a..9ecc1f672 100644
--- a/libbb/obscure.c
+++ b/libbb/obscure.c
@@ -109,10 +109,12 @@ static const char *obscure_msg(const char *old_p, const char *new_p, const struc
 	if (string_checker(new_p, pw->pw_name)) {
 		return "similar to username";
 	}
+#ifndef __BIONIC__
 	/* no gecos as-is, as sub-string, reversed, capitalized, doubled */
 	if (pw->pw_gecos[0] && string_checker(new_p, pw->pw_gecos)) {
 		return "similar to gecos";
 	}
+#endif
 	/* hostname as-is, as sub-string, reversed, capitalized, doubled */
 	hostname = safe_gethostname();
 	i = string_checker(new_p, hostname);
diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c
index 98b6ccfbf..c8816e9e7 100644
--- a/miscutils/adjtimex.c
+++ b/miscutils/adjtimex.c
@@ -23,7 +23,11 @@
 //usage:     "\n	-p TCONST"
 
 #include "libbb.h"
-#include <sys/timex.h>
+#ifdef __BIONIC__
+# include <linux/timex.h>
+#else
+# include <sys/timex.h>
+#endif
 
 static const uint16_t statlist_bit[] = {
 	STA_PLL,
diff --git a/miscutils/setserial.c b/miscutils/setserial.c
index 26902a273..2a034e32c 100644
--- a/miscutils/setserial.c
+++ b/miscutils/setserial.c
@@ -11,7 +11,7 @@
 //config:config SETSERIAL
 //config:	bool "setserial"
 //config:	default y
-//config:	depends on PLATFORM_LINUX
+//config:	select PLATFORM_LINUX
 //config:	help
 //config:	  Retrieve or set Linux serial port.
 
-- 
cgit v1.2.3-55-g6feb


From a669eca3a230e35e4a6894a30168a047000f3b75 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 11 Jul 2011 07:36:59 +0200
Subject: libbb/lineedit: implement optional Ctrl-R history search

function                                             old     new   delta
read_line_input                                     3433    3957    +524
load_string                                           77      90     +13
input_tab                                           1086    1069     -17
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 537/-17)           Total: 520 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/Config.src |   8 +++
 libbb/lineedit.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 161 insertions(+), 12 deletions(-)

(limited to 'libbb')

diff --git a/libbb/Config.src b/libbb/Config.src
index 0ea8f43ab..aa442365a 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -94,6 +94,14 @@ config FEATURE_EDITING_SAVEHISTORY
 	help
 	  Enable history saving in shells.
 
+config FEATURE_REVERSE_SEARCH
+	bool "Reverse history search"
+	default y
+	depends on FEATURE_EDITING_SAVEHISTORY
+	help
+	  Enable readline-like Ctrl-R combination for reverse history search.
+	  Increases code by about 0.5k.
+
 config FEATURE_TAB_COMPLETION
 	bool "Tab completion"
 	default y
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 4e3bc0ef7..10265192e 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -207,18 +207,21 @@ static void deinit_S(void)
 
 
 #if ENABLE_UNICODE_SUPPORT
-static size_t load_string(const char *src, int maxsize)
+static size_t load_string(const char *src)
 {
 	if (unicode_status == UNICODE_ON) {
-		ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
+		ssize_t len = mbstowcs(command_ps, src, S.maxsize - 1);
 		if (len < 0)
 			len = 0;
 		command_ps[len] = BB_NUL;
 		return len;
 	} else {
 		unsigned i = 0;
-		while ((command_ps[i] = src[i]) != 0)
+		while (src[i] && i < S.maxsize - 1) {
+			command_ps[i] = src[i];
 			i++;
+		}
+		command_ps[i] = BB_NUL;
 		return i;
 	}
 }
@@ -319,9 +322,9 @@ static wchar_t adjust_width_and_validate_wc(wchar_t wc)
 	return wc;
 }
 #else /* !UNICODE */
-static size_t load_string(const char *src, int maxsize)
+static size_t load_string(const char *src)
 {
-	safe_strncpy(command_ps, src, maxsize);
+	safe_strncpy(command_ps, src, S.maxsize);
 	return strlen(command_ps);
 }
 # if ENABLE_FEATURE_TAB_COMPLETION
@@ -1224,10 +1227,10 @@ static NOINLINE void input_tab(smallint *lastWasTab)
 			strcpy(match_buf, &command[cursor_mb]);
 			/* where do we want to have cursor after all? */
 			strcpy(&command[cursor_mb], chosen_match + match_pfx_len);
-			len = load_string(command, S.maxsize);
+			len = load_string(command);
 			/* add match and tail */
 			sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf);
-			command_len = load_string(command, S.maxsize);
+			command_len = load_string(command);
 			/* write out the matched command */
 			/* paranoia: load_string can return 0 on conv error,
 			 * prevent passing pos = (0 - 12) to redraw */
@@ -1948,6 +1951,140 @@ static int isrtl_str(void)
 #undef CTRL
 #define CTRL(a) ((a) & ~0x40)
 
+enum {
+	VI_CMDMODE_BIT = 0x40000000,
+	/* 0x80000000 bit flags KEYCODE_xxx */
+};
+
+#if ENABLE_FEATURE_REVERSE_SEARCH
+/* Mimic readline Ctrl-R reverse history search.
+ * When invoked, it shows the following prompt:
+ * (reverse-i-search)'': user_input [cursor pos unchanged by Ctrl-R]
+ * and typing results in search being performed:
+ * (reverse-i-search)'tmp': cd /tmp [cursor under t in /tmp]
+ * Search is performed by looking at progressively older lines in history.
+ * Ctrl-R again searches for the next match in history.
+ * Backspace deletes last matched char.
+ * Control keys exit search and return to normal editing (at current history line).
+ */
+static int32_t reverse_i_search(void)
+{
+	char match_buf[128]; /* for user input */
+	char read_key_buffer[KEYCODE_BUFFER_SIZE];
+	const char *matched_history_line;
+	const char *saved_prompt;
+	int32_t ic;
+
+	matched_history_line = NULL;
+	read_key_buffer[0] = 0;
+	match_buf[0] = '\0';
+
+	/* Save and replace the prompt */
+	saved_prompt = cmdedit_prompt;
+	goto set_prompt;
+
+	while (1) {
+		int h;
+		unsigned match_buf_len = strlen(match_buf);
+
+		fflush_all();
+//FIXME: correct timeout?
+		ic = lineedit_read_key(read_key_buffer, -1);
+
+		switch (ic) {
+		case CTRL('R'): /* searching for the next match */
+			break;
+
+		case '\b':
+		case '\x7f':
+			/* Backspace */
+			if (unicode_status == UNICODE_ON) {
+				while (match_buf_len != 0) {
+					uint8_t c = match_buf[--match_buf_len];
+					if ((c & 0xc0) != 0x80) /* start of UTF-8 char? */
+						break; /* yes */
+				}
+			} else {
+				if (match_buf_len != 0)
+					match_buf_len--;
+			}
+			match_buf[match_buf_len] = '\0';
+			break;
+
+		default:
+			if (ic < ' '
+			 || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
+			 || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
+			) {
+				goto ret;
+			}
+
+			/* Append this char */
+#if ENABLE_UNICODE_SUPPORT
+			if (unicode_status == UNICODE_ON) {
+				mbstate_t mbstate = { 0 };
+				char buf[MB_CUR_MAX + 1];
+				int len = wcrtomb(buf, ic, &mbstate);
+				if (len > 0) {
+					buf[len] = '\0';
+					if (match_buf_len + len < sizeof(match_buf))
+						strcpy(match_buf + match_buf_len, buf);
+				}
+			} else
+#endif
+			if (match_buf_len < sizeof(match_buf) - 1) {
+				match_buf[match_buf_len] = ic;
+				match_buf[match_buf_len + 1] = '\0';
+			}
+			break;
+		} /* switch (ic) */
+
+		/* Search in history for match_buf */
+		h = state->cur_history;
+		if (ic == CTRL('R'))
+			h--;
+		while (h >= 0) {
+			if (state->history[h]) {
+				char *match = strstr(state->history[h], match_buf);
+				if (match) {
+					state->cur_history = h;
+					matched_history_line = state->history[h];
+					command_len = load_string(matched_history_line);
+					cursor = match - matched_history_line;
+//FIXME: cursor position for Unicode case
+
+					free((char*)cmdedit_prompt);
+ set_prompt:
+					cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
+					cmdedit_prmt_len = strlen(cmdedit_prompt);
+					goto do_redraw;
+				}
+			}
+			h--;
+		}
+
+		/* Not found */
+		match_buf[match_buf_len] = '\0';
+		beep();
+		continue;
+
+ do_redraw:
+		redraw(cmdedit_y, command_len - cursor);
+	} /* while (1) */
+
+ ret:
+	if (matched_history_line)
+		command_len = load_string(matched_history_line);
+
+	free((char*)cmdedit_prompt);
+	cmdedit_prompt = saved_prompt;
+	cmdedit_prmt_len = strlen(cmdedit_prompt);
+	redraw(cmdedit_y, command_len - cursor);
+
+	return ic;
+}
+#endif
+
 /* maxsize must be >= 2.
  * Returns:
  * -1 on read errors or EOF, or on bare Ctrl-D,
@@ -2062,15 +2199,14 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 		 * clutters the big switch a bit, but keeps all the code
 		 * in one place.
 		 */
-		enum {
-			VI_CMDMODE_BIT = 0x40000000,
-			/* 0x80000000 bit flags KEYCODE_xxx */
-		};
 		int32_t ic, ic_raw;
 
 		fflush_all();
 		ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
 
+#if ENABLE_FEATURE_REVERSE_SEARCH
+ again:
+#endif
 #if ENABLE_FEATURE_EDITING_VI
 		newdelflag = 1;
 		if (vi_cmdmode) {
@@ -2174,6 +2310,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 			while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
 				input_backspace();
 			break;
+#if ENABLE_FEATURE_REVERSE_SEARCH
+		case CTRL('R'):
+			ic = ic_raw = reverse_i_search();
+			goto again;
+#endif
 
 #if ENABLE_FEATURE_EDITING_VI
 		case 'i'|VI_CMDMODE_BIT:
@@ -2327,7 +2468,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 			/* Rewrite the line with the selected history item */
 			/* change command */
 			command_len = load_string(state->history[state->cur_history] ?
-					state->history[state->cur_history] : "", maxsize);
+					state->history[state->cur_history] : "");
 			/* redraw and go to eol (bol, in vi) */
 			redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
 			break;
-- 
cgit v1.2.3-55-g6feb


From 4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 25 Jul 2011 15:18:20 +0200
Subject: less: optionally query terminal size via "ESC [ 6 n". Closes bug
 2659.

+7 bytes is not selected, +100 if selected.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 editors/vi.c         |   4 +-
 libbb/read_key.c     |   5 +-
 miscutils/Config.src |  66 --------------------------
 miscutils/less.c     | 132 +++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 123 insertions(+), 84 deletions(-)

(limited to 'libbb')

diff --git a/editors/vi.c b/editors/vi.c
index 55092f921..96a0c8df7 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -132,8 +132,8 @@
 //config:	help
 //config:	  If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
 //config:	  this option makes vi perform a last-ditch effort to find it:
-//config:	  vi positions cursor to 999,999 and asks terminal to report real
-//config:	  cursor position using "ESC [ 6 n" escape sequence, then reads stdin.
+//config:	  position cursor to 999,999 and ask terminal to report real
+//config:	  cursor position using "ESC [ 6 n" escape sequence, then read stdin.
 //config:
 //config:	  This is not clean but helps a lot on serial lines and such.
 //config:
diff --git a/libbb/read_key.c b/libbb/read_key.c
index 840325c99..5dcd19c3f 100644
--- a/libbb/read_key.c
+++ b/libbb/read_key.c
@@ -214,7 +214,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
 		}
 		n++;
 		/* Try to decipher "ESC [ NNN ; NNN R" sequence */
-		if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL || ENABLE_FEATURE_VI_ASK_TERMINAL)
+		if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL
+		    || ENABLE_FEATURE_VI_ASK_TERMINAL
+		    || ENABLE_FEATURE_LESS_ASK_TERMINAL
+		    )
 		 && n >= 5
 		 && buffer[0] == '['
 		 && buffer[n-1] == 'R'
diff --git a/miscutils/Config.src b/miscutils/Config.src
index 61529141d..b9fc196d8 100644
--- a/miscutils/Config.src
+++ b/miscutils/Config.src
@@ -360,72 +360,6 @@ config FEATURE_LAST_FANCY
 	  logged into the system (mimics sysvinit last). +900 bytes.
 endchoice
 
-config LESS
-	bool "less"
-	default y
-	help
-	  'less' is a pager, meaning that it displays text files. It possesses
-	  a wide array of features, and is an improvement over 'more'.
-
-config FEATURE_LESS_MAXLINES
-	int "Max number of input lines less will try to eat"
-	default 9999999
-	depends on LESS
-
-config FEATURE_LESS_BRACKETS
-	bool "Enable bracket searching"
-	default y
-	depends on LESS
-	help
-	  This option adds the capability to search for matching left and right
-	  brackets, facilitating programming.
-
-config FEATURE_LESS_FLAGS
-	bool "Enable extra flags"
-	default y
-	depends on LESS
-	help
-	  The extra flags provided do the following:
-
-	  The -M flag enables a more sophisticated status line.
-	  The -m flag enables a simpler status line with a percentage.
-
-config FEATURE_LESS_MARKS
-	bool "Enable marks"
-	default y
-	depends on LESS
-	help
-	  Marks enable positions in a file to be stored for easy reference.
-
-config FEATURE_LESS_REGEXP
-	bool "Enable regular expressions"
-	default y
-	depends on LESS
-	help
-	  Enable regular expressions, allowing complex file searches.
-
-config FEATURE_LESS_WINCH
-	bool "Enable automatic resizing on window size changes"
-	default y
-	depends on LESS
-	help
-	  Makes less track window size changes.
-
-config FEATURE_LESS_DASHCMD
-	bool "Enable flag changes ('-' command)"
-	default y
-	depends on LESS
-	help
-	  This enables the ability to change command-line flags within
-	  less itself ('-' keyboard command).
-
-config FEATURE_LESS_LINENUMS
-	bool "Enable dynamic switching of line numbers"
-	default y
-	depends on FEATURE_LESS_DASHCMD
-	help
-	  Enables "-N" command.
-
 config HDPARM
 	bool "hdparm"
 	default y
diff --git a/miscutils/less.c b/miscutils/less.c
index 46024f9f7..16eb95d56 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -21,6 +21,85 @@
  *   redirected input has been read from stdin
  */
 
+//config:config LESS
+//config:	bool "less"
+//config:	default y
+//config:	help
+//config:	  'less' is a pager, meaning that it displays text files. It possesses
+//config:	  a wide array of features, and is an improvement over 'more'.
+//config:
+//config:config FEATURE_LESS_MAXLINES
+//config:	int "Max number of input lines less will try to eat"
+//config:	default 9999999
+//config:	depends on LESS
+//config:
+//config:config FEATURE_LESS_BRACKETS
+//config:	bool "Enable bracket searching"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  This option adds the capability to search for matching left and right
+//config:	  brackets, facilitating programming.
+//config:
+//config:config FEATURE_LESS_FLAGS
+//config:	bool "Enable extra flags"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  The extra flags provided do the following:
+//config:
+//config:	  The -M flag enables a more sophisticated status line.
+//config:	  The -m flag enables a simpler status line with a percentage.
+//config:
+//config:config FEATURE_LESS_MARKS
+//config:	bool "Enable marks"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Marks enable positions in a file to be stored for easy reference.
+//config:
+//config:config FEATURE_LESS_REGEXP
+//config:	bool "Enable regular expressions"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Enable regular expressions, allowing complex file searches.
+//config:
+//config:config FEATURE_LESS_WINCH
+//config:	bool "Enable automatic resizing on window size changes"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Makes less track window size changes.
+//config:
+//config:config FEATURE_LESS_ASK_TERMINAL
+//config:	bool "Use 'tell me cursor position' ESC sequence to measure window"
+//config:	default y
+//config:	depends on FEATURE_LESS_WINCH
+//config:	help
+//config:	  Makes less track window size changes.
+//config:	  If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+//config:	  this option makes less perform a last-ditch effort to find it:
+//config:	  position cursor to 999,999 and ask terminal to report real
+//config:	  cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+//config:
+//config:	  This is not clean but helps a lot on serial lines and such.
+//config:
+//config:config FEATURE_LESS_DASHCMD
+//config:	bool "Enable flag changes ('-' command)"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  This enables the ability to change command-line flags within
+//config:	  less itself ('-' keyboard command).
+//config:
+//config:config FEATURE_LESS_LINENUMS
+//config:	bool "Enable dynamic switching of line numbers"
+//config:	default y
+//config:	depends on FEATURE_LESS_DASHCMD
+//config:	help
+//config:	  Enables "-N" command.
+
 //usage:#define less_trivial_usage
 //usage:       "[-EMNmh~I?] [FILE]..."
 //usage:#define less_full_usage "\n\n"
@@ -107,6 +186,9 @@ struct globals {
 	int num_matches;
 	regex_t pattern;
 	smallint pattern_valid;
+#endif
+#if ENABLE_FEATURE_LESS_ASK_TERMINAL
+	smallint winsize_err;
 #endif
 	smallint terminated;
 	struct termios term_orig, term_less;
@@ -815,12 +897,17 @@ static void reinitialize(void)
 	cur_fline = 0;
 	max_lineno = 0;
 	open_file_and_read_lines();
+#if ENABLE_FEATURE_LESS_ASK_TERMINAL
+	if (G.winsize_err)
+		printf("\033[999;999H" "\033[6n");
+#endif
 	buffer_fill_and_print();
 }
 
-static int getch_nowait(void)
+static int64_t getch_nowait(void)
 {
 	int rd;
+	int64_t key64;
 	struct pollfd pfd[2];
 
 	pfd[0].fd = STDIN_FILENO;
@@ -868,8 +955,8 @@ static int getch_nowait(void)
 
 	/* We have kbd_fd in O_NONBLOCK mode, read inside read_key()
 	 * would not block even if there is no input available */
-	rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
-	if (rd == -1) {
+	key64 = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
+	if ((int)key64 == -1) {
 		if (errno == EAGAIN) {
 			/* No keyboard input available. Since poll() did return,
 			 * we should have input on stdin */
@@ -881,25 +968,29 @@ static int getch_nowait(void)
 		less_exit(0);
 	}
 	set_tty_cooked();
-	return rd;
+	return key64;
 }
 
 /* Grab a character from input without requiring the return key.
  * May return KEYCODE_xxx values.
  * Note that this function works best with raw input. */
-static int less_getch(int pos)
+static int64_t less_getch(int pos)
 {
-	int i;
+	int64_t key64;
+	int key;
 
  again:
 	less_gets_pos = pos;
-	i = getch_nowait();
+	key = key64 = getch_nowait();
 	less_gets_pos = -1;
 
-	/* Discard Ctrl-something chars */
-	if (i >= 0 && i < ' ' && i != 0x0d && i != 8)
+	/* Discard Ctrl-something chars.
+	 * (checking only lower 32 bits is a size optimization:
+	 * upper 32 bits are used only by KEYCODE_CURSOR_POS)
+	 */
+	if (key >= 0 && key < ' ' && key != 0x0d && key != 8)
 		goto again;
-	return i;
+	return key;
 }
 
 static char* less_gets(int sz)
@@ -1514,8 +1605,6 @@ static void sigwinch_handler(int sig UNUSED_PARAM)
 int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int less_main(int argc, char **argv)
 {
-	int keypress;
-
 	INIT_G();
 
 	/* TODO: -x: do not interpret backspace, -xx: tab also */
@@ -1558,7 +1647,7 @@ int less_main(int argc, char **argv)
 	term_less.c_cc[VMIN] = 1;
 	term_less.c_cc[VTIME] = 0;
 
-	get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+	IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
 	/* 20: two tabstops + 4 */
 	if (width < 20 || max_displayed_line < 3)
 		return bb_cat(argv);
@@ -1573,11 +1662,14 @@ int less_main(int argc, char **argv)
 	buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
 	reinitialize();
 	while (1) {
+		int64_t keypress;
+
 #if ENABLE_FEATURE_LESS_WINCH
 		while (WINCH_COUNTER) {
  again:
 			winch_counter--;
-			get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+			IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+ IF_FEATURE_LESS_ASK_TERMINAL(got_size:)
 			/* 20: two tabstops + 4 */
 			if (width < 20)
 				width = 20;
@@ -1597,8 +1689,18 @@ int less_main(int argc, char **argv)
 			/* This took some time. Loop back and check,
 			 * were there another SIGWINCH? */
 		}
-#endif
 		keypress = less_getch(-1); /* -1: do not position cursor */
+# if ENABLE_FEATURE_LESS_ASK_TERMINAL
+		if ((int32_t)keypress == KEYCODE_CURSOR_POS) {
+			uint32_t rc = (keypress >> 32);
+			width = (rc & 0x7fff);
+			max_displayed_line = ((rc >> 16) & 0x7fff);
+			goto got_size;
+		}
+# endif
+#else
+		keypress = less_getch(-1); /* -1: do not position cursor */
+#endif
 		keypress_process(keypress);
 	}
 }
-- 
cgit v1.2.3-55-g6feb


From 7485086f1eca78998d6cd31b0ce18a8a8ea3fc35 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Tue, 9 Aug 2011 04:05:13 +0200
Subject: die_if_bad_username: tighten up a bit

function                                             old     new   delta
die_if_bad_username                                   77      97     +20

Based on patches from Tito.
The changes are:
better comments
we disallow '@' now - in practice such usernames will be unusable
use of the portable filename character set plus '$'
don't use isalnum as it allows non-ASCII letters in legacy 8-bit locales (pointed out by Rich Felker)
enforce maximum length of LOGIN_NAME_MAX (including NUL)
don't allow '$', '.', and '-' as first char
don't print the illegal char in error message as if it is a wide char it will be unreadable
print the position of the illegal character

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/die_if_bad_username.c | 42 ++++++++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 10 deletions(-)

(limited to 'libbb')

diff --git a/libbb/die_if_bad_username.c b/libbb/die_if_bad_username.c
index 9946e3a1d..cf1297bd6 100644
--- a/libbb/die_if_bad_username.c
+++ b/libbb/die_if_bad_username.c
@@ -18,23 +18,45 @@
 
 void FAST_FUNC die_if_bad_username(const char *name)
 {
-	/* 1st char being dash or dot isn't valid: */
-	goto skip;
-	/* For example, name like ".." can make adduser
-	 * chown "/home/.." recursively - NOT GOOD
+	const char *start = name;
+
+	/* 1st char being dash or dot isn't valid:
+	 * for example, name like ".." can make adduser
+	 * chown "/home/.." recursively - NOT GOOD.
+	 * Name of just a single "$" is also rejected.
 	 */
+	goto skip;
 
 	do {
-		if (*name == '-' || *name == '.')
+		unsigned char ch;
+
+		/* These chars are valid unless they are at the 1st pos: */
+		if (*name == '-'
+		 || *name == '.'
+		/* $ is allowed if it's the last char: */
+		 || (*name == '$' && !name[1])
+		) {
 			continue;
+		}
  skip:
-		if (isalnum(*name)
-		 || *name == '_'
-		 || *name == '@'
-		 || (*name == '$' && !name[1])
+		ch = *name;
+		if (ch == '_'
+		/* || ch == '@' -- we disallow this too. Think about "user@host" */
+		/* open-coded isalnum: */
+		 || (ch >= '0' && ch <= '9')
+		 || ((ch|0x20) >= 'a' && (ch|0x20) <= 'z')
 		) {
 			continue;
 		}
-		bb_error_msg_and_die("illegal character '%c'", *name);
+		bb_error_msg_and_die("illegal character with code %u at position %u",
+				(unsigned)ch, (unsigned)(name - start));
 	} while (*++name);
+
+	/* The minimum size of the login name is one char or two if
+	 * last char is the '$'. Violations of this are caught above.
+	 * The maximum size of the login name is LOGIN_NAME_MAX
+	 * including the terminating null byte.
+	 */
+	if (name - start >= LOGIN_NAME_MAX)
+		bb_error_msg_and_die("name is too long");
 }
-- 
cgit v1.2.3-55-g6feb


From b47b3ce1bd651c689fae3cac2760f43f453e2b6e Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 10 Aug 2011 00:51:29 +0200
Subject: randomconfig fixes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 archival/tar.c              |  2 +-
 coreutils/ls.c              |  4 ++--
 libbb/getopt32.c            |  6 +++++-
 testsuite/date/date-R-works | 15 ++++++++++++++-
 testsuite/ls.tests          |  3 ++-
 testsuite/mount.tests       |  2 ++
 testsuite/od.tests          |  4 ++--
 testsuite/tar.tests         |  4 ++++
 8 files changed, 32 insertions(+), 8 deletions(-)

(limited to 'libbb')

diff --git a/archival/tar.c b/archival/tar.c
index 3e90d46cb..375e838d2 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -924,7 +924,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
 	/* Prepend '-' to the first argument if required */
 	opt_complementary = "--:" // first arg is options
 		"tt:vv:" // count -t,-v
-		"X::T::" // cumulative lists
+		IF_FEATURE_TAR_FROM("X::T::") // cumulative lists
 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 		"\xff::" // cumulative lists for --exclude
 #endif
diff --git a/coreutils/ls.c b/coreutils/ls.c
index f11eb4358..d5b25ee70 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1111,7 +1111,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 	IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
 	opt_complementary =
 		/* -e implies -l */
-		"el"
+		IF_FEATURE_LS_TIMESTAMPS("el")
 		/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
 		 * in some pairs of opts, only last one takes effect:
 		 */
@@ -1121,7 +1121,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 		":C-xl:x-Cl:l-xC" /* bycols/bylines/long */
 		":C-1:1-C" /* bycols/oneline */
 		":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
-		":c-u:u-c" /* mtime/atime */
+		IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
 		/* -w NUM: */
 		IF_FEATURE_AUTOWIDTH(":w+");
 	opt = getopt32(argv, ls_options
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index c7c4079c2..d0e83d88e 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -467,13 +467,17 @@ getopt32(char **argv, const char *applet_opts, ...)
 		}
 		for (on_off = complementary; on_off->opt_char; on_off++)
 			if (on_off->opt_char == *s)
-				break;
+				goto found_opt;
+		/* Without this, diagnostic of such bugs is not easy */
+		bb_error_msg_and_die("NO OPT %c!", *s);
+ found_opt:
 		if (c == ':' && s[2] == ':') {
 			on_off->param_type = PARAM_LIST;
 			continue;
 		}
 		if (c == '+' && (s[2] == ':' || s[2] == '\0')) {
 			on_off->param_type = PARAM_INT;
+			s++;
 			continue;
 		}
 		if (c == ':' || c == '\0') {
diff --git a/testsuite/date/date-R-works b/testsuite/date/date-R-works
index d05634456..12f9b96ed 100644
--- a/testsuite/date/date-R-works
+++ b/testsuite/date/date-R-works
@@ -5,4 +5,17 @@ while test x"$dt" = x"$dt1"; do
     dt="`date -R`"
 done
 
-test x"$dt" = x"`busybox date -R`"
+bdt=`busybox date -R`
+bdt=`busybox date -R`
+bdt=`busybox date -R`
+bdt=`busybox date -R`
+bdt=`busybox date -R`
+
+# Wtih !FEATURE_DATE_NANO, that is, with time()
+# instead of clock_gettime(), seconds transition
+# may not happen at _exactly_ the same moment,
+# but can be delayed. Several busybox date -R
+# invocations above are meant to deal with this.
+# (two were enough for me, but I added more just in case).
+
+test x"$dt" = x"$bdt"
diff --git a/testsuite/ls.tests b/testsuite/ls.tests
index e2284658d..9309d366b 100755
--- a/testsuite/ls.tests
+++ b/testsuite/ls.tests
@@ -256,7 +256,8 @@ mkdir ls.testdir || exit 1
 
 # testing "test name" "command" "expected result" "file input" "stdin"
 
-testing "ls symlink_to_dir" \
+test x"$CONFIG_FEATURE_LS_SORTFILES" = x"y" \
+&& testing "ls symlink_to_dir" \
 "touch ls.testdir/A ls.testdir/B; ln -s ls.testdir ls.link; ls ls.link; ls -1 ls.link/; ls -1 ls.link; rm -f ls.link" \
 "A\nB\nA\nB\nA\nB\n" \
 "" ""
diff --git a/testsuite/mount.tests b/testsuite/mount.tests
index 58eeb2ec5..9ddd58795 100755
--- a/testsuite/mount.tests
+++ b/testsuite/mount.tests
@@ -46,6 +46,7 @@ rm mount.image1m
 
 
 # Bug: mount.shared1 directory shows no files (has to show files a and b)
+optional FEATURE_LS_RECURSIVE
 testing "mount bind+rshared" "\
 mkdir -p mount.dir mount.shared1 mount.shared2
 touch mount.dir/a mount.dir/b
@@ -80,5 +81,6 @@ a
 b
 " \
 	"" ""
+SKIP=
 
 exit $FAILCOUNT
diff --git a/testsuite/od.tests b/testsuite/od.tests
index fa47b4790..7a9da3e97 100755
--- a/testsuite/od.tests
+++ b/testsuite/od.tests
@@ -16,7 +16,7 @@ testing "od -b" \
 	"" "HELLO"
 SKIP=
 
-optional DESKTOP
+optional DESKTOP LONG_OPTS
 testing "od -b --traditional" \
 	"od -b --traditional" \
 "\
@@ -26,7 +26,7 @@ testing "od -b --traditional" \
 	"" "HELLO"
 SKIP=
 
-optional DESKTOP
+optional DESKTOP LONG_OPTS
 testing "od -b --traditional FILE" \
 	"od -b --traditional input" \
 "\
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index 534135df8..39ece5feb 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -156,6 +156,7 @@ SKIP=
 
 # Had a bug where on extract autodetect first "switched off" -z
 # and then failed to recognize .tgz extension
+optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ
 testing "tar extract tgz" "\
 dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null
 tar -czf F0.tgz F0
@@ -167,8 +168,10 @@ F0
 Ok
 " \
 "" ""
+SKIP=
 
 # On extract, everything up to and including last ".." component is stripped
+optional FEATURE_TAR_CREATE
 testing "tar strips /../ on extract" "\
 rm -rf input_* test.tar 2>/dev/null
 mkdir input_dir
@@ -184,6 +187,7 @@ input_dir/file
 Ok
 " \
 "" ""
+SKIP=
 
 
 cd .. && rm -rf tar.tempdir || exit 1
-- 
cgit v1.2.3-55-g6feb


From d84b175cb6948eb17f847313bf912174e2f934e1 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 13 Aug 2011 08:46:00 +0200
Subject: Bump version to 1.19.0, update copyright year in help message

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 Makefile          | 2 +-
 libbb/appletlib.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'libbb')

diff --git a/Makefile b/Makefile
index 0fb3d4c72..7a1abda1b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 1
 PATCHLEVEL = 19
 SUBLEVEL = 0
-EXTRAVERSION = .git
+EXTRAVERSION =
 NAME = Unnamed
 
 # *DOCUMENTATION*
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 1bc45c491..8157b4f42 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -627,7 +627,7 @@ static int busybox_main(char **argv)
 		full_write2_str(bb_banner); /* reuse const string */
 		full_write2_str(" multi-call binary.\n"); /* reuse */
 		full_write2_str(
-			"Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n"
+			"Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko\n"
 			"and others. Licensed under GPLv2.\n"
 			"See source distribution for full notice.\n"
 			"\n"
-- 
cgit v1.2.3-55-g6feb