aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 15:48:57 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 15:48:57 +0000
commit9db164d6e39050d09f38288c6045cd2a2cbf6d63 (patch)
treeea5dc2d28d15da0de25c197ed7d059c3656af1a0 /libbb
parent1118c95535ea51961437089fc3dece5ab4ea7e1b (diff)
parentd84b175cb6948eb17f847313bf912174e2f934e1 (diff)
downloadbusybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.tar.gz
busybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.tar.bz2
busybox-w32-9db164d6e39050d09f38288c6045cd2a2cbf6d63.zip
Merge commit 'd84b175cb6948eb17f847313bf912174e2f934e1' into merge
Conflicts: include/platform.h
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src8
-rw-r--r--libbb/Kbuild.src9
-rw-r--r--libbb/appletlib.c2
-rw-r--r--libbb/die_if_bad_username.c42
-rw-r--r--libbb/getopt32.c6
-rw-r--r--libbb/inet_common.c3
-rw-r--r--libbb/lineedit.c165
-rw-r--r--libbb/obscure.c2
-rw-r--r--libbb/read_key.c5
9 files changed, 216 insertions, 26 deletions
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
94 help 94 help
95 Enable history saving in shells. 95 Enable history saving in shells.
96 96
97config FEATURE_REVERSE_SEARCH
98 bool "Reverse history search"
99 default y
100 depends on FEATURE_EDITING_SAVEHISTORY
101 help
102 Enable readline-like Ctrl-R combination for reverse history search.
103 Increases code by about 0.5k.
104
97config FEATURE_TAB_COMPLETION 105config FEATURE_TAB_COMPLETION
98 bool "Tab completion" 106 bool "Tab completion"
99 default y 107 default y
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index fcab184e0..b5e9afc78 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -128,6 +128,15 @@ lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
128lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o 128lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o
129lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o 129lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o
130 130
131lib-$(CONFIG_NC) += udp_io.o
132lib-$(CONFIG_DNSD) += udp_io.o
133lib-$(CONFIG_NTPD) += udp_io.o
134lib-$(CONFIG_TFTP) += udp_io.o
135lib-$(CONFIG_TFTPD) += udp_io.o
136lib-$(CONFIG_TCPSVD) += udp_io.o
137lib-$(CONFIG_UDPSVD) += udp_io.o
138lib-$(CONFIG_TRACEROUTE) += udp_io.o
139
131lib-$(CONFIG_LOSETUP) += loop.o 140lib-$(CONFIG_LOSETUP) += loop.o
132lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o 141lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
133 142
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index b824b4775..6d002b0dd 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -627,7 +627,7 @@ static int busybox_main(char **argv)
627 full_write2_str(bb_banner); /* reuse const string */ 627 full_write2_str(bb_banner); /* reuse const string */
628 full_write2_str(" multi-call binary.\n"); /* reuse */ 628 full_write2_str(" multi-call binary.\n"); /* reuse */
629 full_write2_str( 629 full_write2_str(
630 "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" 630 "Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko\n"
631 "and others. Licensed under GPLv2.\n" 631 "and others. Licensed under GPLv2.\n"
632 "See source distribution for full notice.\n" 632 "See source distribution for full notice.\n"
633 "\n" 633 "\n"
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 @@
18 18
19void FAST_FUNC die_if_bad_username(const char *name) 19void FAST_FUNC die_if_bad_username(const char *name)
20{ 20{
21 /* 1st char being dash or dot isn't valid: */ 21 const char *start = name;
22 goto skip; 22
23 /* For example, name like ".." can make adduser 23 /* 1st char being dash or dot isn't valid:
24 * chown "/home/.." recursively - NOT GOOD 24 * for example, name like ".." can make adduser
25 * chown "/home/.." recursively - NOT GOOD.
26 * Name of just a single "$" is also rejected.
25 */ 27 */
28 goto skip;
26 29
27 do { 30 do {
28 if (*name == '-' || *name == '.') 31 unsigned char ch;
32
33 /* These chars are valid unless they are at the 1st pos: */
34 if (*name == '-'
35 || *name == '.'
36 /* $ is allowed if it's the last char: */
37 || (*name == '$' && !name[1])
38 ) {
29 continue; 39 continue;
40 }
30 skip: 41 skip:
31 if (isalnum(*name) 42 ch = *name;
32 || *name == '_' 43 if (ch == '_'
33 || *name == '@' 44 /* || ch == '@' -- we disallow this too. Think about "user@host" */
34 || (*name == '$' && !name[1]) 45 /* open-coded isalnum: */
46 || (ch >= '0' && ch <= '9')
47 || ((ch|0x20) >= 'a' && (ch|0x20) <= 'z')
35 ) { 48 ) {
36 continue; 49 continue;
37 } 50 }
38 bb_error_msg_and_die("illegal character '%c'", *name); 51 bb_error_msg_and_die("illegal character with code %u at position %u",
52 (unsigned)ch, (unsigned)(name - start));
39 } while (*++name); 53 } while (*++name);
54
55 /* The minimum size of the login name is one char or two if
56 * last char is the '$'. Violations of this are caught above.
57 * The maximum size of the login name is LOGIN_NAME_MAX
58 * including the terminating null byte.
59 */
60 if (name - start >= LOGIN_NAME_MAX)
61 bb_error_msg_and_die("name is too long");
40} 62}
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 02cbefec9..ae019b26b 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -467,13 +467,17 @@ getopt32(char **argv, const char *applet_opts, ...)
467 } 467 }
468 for (on_off = complementary; on_off->opt_char; on_off++) 468 for (on_off = complementary; on_off->opt_char; on_off++)
469 if (on_off->opt_char == *s) 469 if (on_off->opt_char == *s)
470 break; 470 goto found_opt;
471 /* Without this, diagnostic of such bugs is not easy */
472 bb_error_msg_and_die("NO OPT %c!", *s);
473 found_opt:
471 if (c == ':' && s[2] == ':') { 474 if (c == ':' && s[2] == ':') {
472 on_off->param_type = PARAM_LIST; 475 on_off->param_type = PARAM_LIST;
473 continue; 476 continue;
474 } 477 }
475 if (c == '+' && (s[2] == ':' || s[2] == '\0')) { 478 if (c == '+' && (s[2] == ':' || s[2] == '\0')) {
476 on_off->param_type = PARAM_INT; 479 on_off->param_type = PARAM_INT;
480 s++;
477 continue; 481 continue;
478 } 482 }
479 if (c == ':' || c == '\0') { 483 if (c == ':' || c == '\0') {
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)
175 return -1; 175 return -1;
176 } 176 }
177 memcpy(sin6, ai->ai_addr, sizeof(*sin6)); 177 memcpy(sin6, ai->ai_addr, sizeof(*sin6));
178 freeaddrinfo(ai); 178 if (ai)
179 freeaddrinfo(ai);
179 return 0; 180 return 0;
180} 181}
181 182
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index e443c7a3e..1b97e8609 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -207,18 +207,21 @@ static void deinit_S(void)
207 207
208 208
209#if ENABLE_UNICODE_SUPPORT 209#if ENABLE_UNICODE_SUPPORT
210static size_t load_string(const char *src, int maxsize) 210static size_t load_string(const char *src)
211{ 211{
212 if (unicode_status == UNICODE_ON) { 212 if (unicode_status == UNICODE_ON) {
213 ssize_t len = mbstowcs(command_ps, src, maxsize - 1); 213 ssize_t len = mbstowcs(command_ps, src, S.maxsize - 1);
214 if (len < 0) 214 if (len < 0)
215 len = 0; 215 len = 0;
216 command_ps[len] = BB_NUL; 216 command_ps[len] = BB_NUL;
217 return len; 217 return len;
218 } else { 218 } else {
219 unsigned i = 0; 219 unsigned i = 0;
220 while ((command_ps[i] = src[i]) != 0) 220 while (src[i] && i < S.maxsize - 1) {
221 command_ps[i] = src[i];
221 i++; 222 i++;
223 }
224 command_ps[i] = BB_NUL;
222 return i; 225 return i;
223 } 226 }
224} 227}
@@ -319,9 +322,9 @@ static wchar_t adjust_width_and_validate_wc(wchar_t wc)
319 return wc; 322 return wc;
320} 323}
321#else /* !UNICODE */ 324#else /* !UNICODE */
322static size_t load_string(const char *src, int maxsize) 325static size_t load_string(const char *src)
323{ 326{
324 safe_strncpy(command_ps, src, maxsize); 327 safe_strncpy(command_ps, src, S.maxsize);
325 return strlen(command_ps); 328 return strlen(command_ps);
326} 329}
327# if ENABLE_FEATURE_TAB_COMPLETION 330# if ENABLE_FEATURE_TAB_COMPLETION
@@ -1232,10 +1235,10 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1232 strcpy(match_buf, &command[cursor_mb]); 1235 strcpy(match_buf, &command[cursor_mb]);
1233 /* where do we want to have cursor after all? */ 1236 /* where do we want to have cursor after all? */
1234 strcpy(&command[cursor_mb], chosen_match + match_pfx_len); 1237 strcpy(&command[cursor_mb], chosen_match + match_pfx_len);
1235 len = load_string(command, S.maxsize); 1238 len = load_string(command);
1236 /* add match and tail */ 1239 /* add match and tail */
1237 sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf); 1240 sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf);
1238 command_len = load_string(command, S.maxsize); 1241 command_len = load_string(command);
1239 /* write out the matched command */ 1242 /* write out the matched command */
1240 /* paranoia: load_string can return 0 on conv error, 1243 /* paranoia: load_string can return 0 on conv error,
1241 * prevent passing pos = (0 - 12) to redraw */ 1244 * prevent passing pos = (0 - 12) to redraw */
@@ -1956,6 +1959,140 @@ static int isrtl_str(void)
1956#undef CTRL 1959#undef CTRL
1957#define CTRL(a) ((a) & ~0x40) 1960#define CTRL(a) ((a) & ~0x40)
1958 1961
1962enum {
1963 VI_CMDMODE_BIT = 0x40000000,
1964 /* 0x80000000 bit flags KEYCODE_xxx */
1965};
1966
1967#if ENABLE_FEATURE_REVERSE_SEARCH
1968/* Mimic readline Ctrl-R reverse history search.
1969 * When invoked, it shows the following prompt:
1970 * (reverse-i-search)'': user_input [cursor pos unchanged by Ctrl-R]
1971 * and typing results in search being performed:
1972 * (reverse-i-search)'tmp': cd /tmp [cursor under t in /tmp]
1973 * Search is performed by looking at progressively older lines in history.
1974 * Ctrl-R again searches for the next match in history.
1975 * Backspace deletes last matched char.
1976 * Control keys exit search and return to normal editing (at current history line).
1977 */
1978static int32_t reverse_i_search(void)
1979{
1980 char match_buf[128]; /* for user input */
1981 char read_key_buffer[KEYCODE_BUFFER_SIZE];
1982 const char *matched_history_line;
1983 const char *saved_prompt;
1984 int32_t ic;
1985
1986 matched_history_line = NULL;
1987 read_key_buffer[0] = 0;
1988 match_buf[0] = '\0';
1989
1990 /* Save and replace the prompt */
1991 saved_prompt = cmdedit_prompt;
1992 goto set_prompt;
1993
1994 while (1) {
1995 int h;
1996 unsigned match_buf_len = strlen(match_buf);
1997
1998 fflush_all();
1999//FIXME: correct timeout?
2000 ic = lineedit_read_key(read_key_buffer, -1);
2001
2002 switch (ic) {
2003 case CTRL('R'): /* searching for the next match */
2004 break;
2005
2006 case '\b':
2007 case '\x7f':
2008 /* Backspace */
2009 if (unicode_status == UNICODE_ON) {
2010 while (match_buf_len != 0) {
2011 uint8_t c = match_buf[--match_buf_len];
2012 if ((c & 0xc0) != 0x80) /* start of UTF-8 char? */
2013 break; /* yes */
2014 }
2015 } else {
2016 if (match_buf_len != 0)
2017 match_buf_len--;
2018 }
2019 match_buf[match_buf_len] = '\0';
2020 break;
2021
2022 default:
2023 if (ic < ' '
2024 || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
2025 || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
2026 ) {
2027 goto ret;
2028 }
2029
2030 /* Append this char */
2031#if ENABLE_UNICODE_SUPPORT
2032 if (unicode_status == UNICODE_ON) {
2033 mbstate_t mbstate = { 0 };
2034 char buf[MB_CUR_MAX + 1];
2035 int len = wcrtomb(buf, ic, &mbstate);
2036 if (len > 0) {
2037 buf[len] = '\0';
2038 if (match_buf_len + len < sizeof(match_buf))
2039 strcpy(match_buf + match_buf_len, buf);
2040 }
2041 } else
2042#endif
2043 if (match_buf_len < sizeof(match_buf) - 1) {
2044 match_buf[match_buf_len] = ic;
2045 match_buf[match_buf_len + 1] = '\0';
2046 }
2047 break;
2048 } /* switch (ic) */
2049
2050 /* Search in history for match_buf */
2051 h = state->cur_history;
2052 if (ic == CTRL('R'))
2053 h--;
2054 while (h >= 0) {
2055 if (state->history[h]) {
2056 char *match = strstr(state->history[h], match_buf);
2057 if (match) {
2058 state->cur_history = h;
2059 matched_history_line = state->history[h];
2060 command_len = load_string(matched_history_line);
2061 cursor = match - matched_history_line;
2062//FIXME: cursor position for Unicode case
2063
2064 free((char*)cmdedit_prompt);
2065 set_prompt:
2066 cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
2067 cmdedit_prmt_len = strlen(cmdedit_prompt);
2068 goto do_redraw;
2069 }
2070 }
2071 h--;
2072 }
2073
2074 /* Not found */
2075 match_buf[match_buf_len] = '\0';
2076 beep();
2077 continue;
2078
2079 do_redraw:
2080 redraw(cmdedit_y, command_len - cursor);
2081 } /* while (1) */
2082
2083 ret:
2084 if (matched_history_line)
2085 command_len = load_string(matched_history_line);
2086
2087 free((char*)cmdedit_prompt);
2088 cmdedit_prompt = saved_prompt;
2089 cmdedit_prmt_len = strlen(cmdedit_prompt);
2090 redraw(cmdedit_y, command_len - cursor);
2091
2092 return ic;
2093}
2094#endif
2095
1959/* maxsize must be >= 2. 2096/* maxsize must be >= 2.
1960 * Returns: 2097 * Returns:
1961 * -1 on read errors or EOF, or on bare Ctrl-D, 2098 * -1 on read errors or EOF, or on bare Ctrl-D,
@@ -2077,15 +2214,14 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2077 * clutters the big switch a bit, but keeps all the code 2214 * clutters the big switch a bit, but keeps all the code
2078 * in one place. 2215 * in one place.
2079 */ 2216 */
2080 enum {
2081 VI_CMDMODE_BIT = 0x40000000,
2082 /* 0x80000000 bit flags KEYCODE_xxx */
2083 };
2084 int32_t ic, ic_raw; 2217 int32_t ic, ic_raw;
2085 2218
2086 fflush_all(); 2219 fflush_all();
2087 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); 2220 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
2088 2221
2222#if ENABLE_FEATURE_REVERSE_SEARCH
2223 again:
2224#endif
2089#if ENABLE_FEATURE_EDITING_VI 2225#if ENABLE_FEATURE_EDITING_VI
2090 newdelflag = 1; 2226 newdelflag = 1;
2091 if (vi_cmdmode) { 2227 if (vi_cmdmode) {
@@ -2189,6 +2325,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2189 while (cursor > 0 && !BB_isspace(command_ps[cursor-1])) 2325 while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
2190 input_backspace(); 2326 input_backspace();
2191 break; 2327 break;
2328#if ENABLE_FEATURE_REVERSE_SEARCH
2329 case CTRL('R'):
2330 ic = ic_raw = reverse_i_search();
2331 goto again;
2332#endif
2192 2333
2193#if ENABLE_FEATURE_EDITING_VI 2334#if ENABLE_FEATURE_EDITING_VI
2194 case 'i'|VI_CMDMODE_BIT: 2335 case 'i'|VI_CMDMODE_BIT:
@@ -2342,7 +2483,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2342 /* Rewrite the line with the selected history item */ 2483 /* Rewrite the line with the selected history item */
2343 /* change command */ 2484 /* change command */
2344 command_len = load_string(state->history[state->cur_history] ? 2485 command_len = load_string(state->history[state->cur_history] ?
2345 state->history[state->cur_history] : "", maxsize); 2486 state->history[state->cur_history] : "");
2346 /* redraw and go to eol (bol, in vi) */ 2487 /* redraw and go to eol (bol, in vi) */
2347 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); 2488 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
2348 break; 2489 break;
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
109 if (string_checker(new_p, pw->pw_name)) { 109 if (string_checker(new_p, pw->pw_name)) {
110 return "similar to username"; 110 return "similar to username";
111 } 111 }
112#ifndef __BIONIC__
112 /* no gecos as-is, as sub-string, reversed, capitalized, doubled */ 113 /* no gecos as-is, as sub-string, reversed, capitalized, doubled */
113 if (pw->pw_gecos[0] && string_checker(new_p, pw->pw_gecos)) { 114 if (pw->pw_gecos[0] && string_checker(new_p, pw->pw_gecos)) {
114 return "similar to gecos"; 115 return "similar to gecos";
115 } 116 }
117#endif
116 /* hostname as-is, as sub-string, reversed, capitalized, doubled */ 118 /* hostname as-is, as sub-string, reversed, capitalized, doubled */
117 hostname = safe_gethostname(); 119 hostname = safe_gethostname();
118 i = string_checker(new_p, hostname); 120 i = string_checker(new_p, hostname);
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)
214 } 214 }
215 n++; 215 n++;
216 /* Try to decipher "ESC [ NNN ; NNN R" sequence */ 216 /* Try to decipher "ESC [ NNN ; NNN R" sequence */
217 if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL || ENABLE_FEATURE_VI_ASK_TERMINAL) 217 if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL
218 || ENABLE_FEATURE_VI_ASK_TERMINAL
219 || ENABLE_FEATURE_LESS_ASK_TERMINAL
220 )
218 && n >= 5 221 && n >= 5
219 && buffer[0] == '[' 222 && buffer[0] == '['
220 && buffer[n-1] == 'R' 223 && buffer[n-1] == 'R'