aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-11-29 11:26:45 +0000
committerRon Yorston <rmy@pobox.com>2016-11-29 11:26:45 +0000
commitbb8d79eadbba1942dbdb9f9cee5c47833afe269f (patch)
treeb8c517e9ca895d60d7227aef7177b6291df5e2cd /libbb
parent9fa1e4990e655a85025c9d270a1606983e375e47 (diff)
parent7d877fc9312a742b06125927bb1d34bd35398c6c (diff)
downloadbusybox-w32-bb8d79eadbba1942dbdb9f9cee5c47833afe269f.tar.gz
busybox-w32-bb8d79eadbba1942dbdb9f9cee5c47833afe269f.tar.bz2
busybox-w32-bb8d79eadbba1942dbdb9f9cee5c47833afe269f.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src162
-rw-r--r--libbb/appletlib.c26
-rw-r--r--libbb/lineedit.c112
-rw-r--r--libbb/read_key.c12
4 files changed, 259 insertions, 53 deletions
diff --git a/libbb/Config.src b/libbb/Config.src
index 6ba256290..00804e31e 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -7,6 +7,30 @@ menu "Busybox Library Tuning"
7 7
8INSERT 8INSERT
9 9
10choice
11 prompt "Buffer allocation policy"
12 default FEATURE_BUFFERS_USE_MALLOC
13 help
14 There are 3 ways BusyBox can handle buffer allocations:
15 - Use malloc. This costs code size for the call to xmalloc.
16 - Put them on stack. For some very small machines with limited stack
17 space, this can be deadly. For most folks, this works just fine.
18 - Put them in BSS. This works beautifully for computers with a real
19 MMU (and OS support), but wastes runtime RAM for uCLinux. This
20 behavior was the only one available for BusyBox versions 0.48 and
21 earlier.
22
23config FEATURE_BUFFERS_USE_MALLOC
24 bool "Allocate with Malloc"
25
26config FEATURE_BUFFERS_GO_ON_STACK
27 bool "Allocate on the Stack"
28
29config FEATURE_BUFFERS_GO_IN_BSS
30 bool "Allocate in the .bss section"
31
32endchoice
33
10config PASSWORD_MINLEN 34config PASSWORD_MINLEN
11 int "Minimum password length" 35 int "Minimum password length"
12 default 6 36 default 6
@@ -153,6 +177,131 @@ config FEATURE_EDITING_ASK_TERMINAL
153 correctly, or want to save on code size (about 400 bytes), 177 correctly, or want to save on code size (about 400 bytes),
154 then do not turn this option on. 178 then do not turn this option on.
155 179
180config LOCALE_SUPPORT
181 bool "Enable locale support (system needs locale for this to work)"
182 default n
183 help
184 Enable this if your system has locale support and you would like
185 busybox to support locale settings.
186
187config UNICODE_SUPPORT
188 bool "Support Unicode"
189 default y
190 help
191 This makes various applets aware that one byte is not
192 one character on screen.
193
194 Busybox aims to eventually work correctly with Unicode displays.
195 Any older encodings are not guaranteed to work.
196 Probably by the time when busybox will be fully Unicode-clean,
197 other encodings will be mainly of historic interest.
198
199config UNICODE_USING_LOCALE
200 bool "Use libc routines for Unicode (else uses internal ones)"
201 default n
202 depends on UNICODE_SUPPORT && LOCALE_SUPPORT
203 help
204 With this option on, Unicode support is implemented using libc
205 routines. Otherwise, internal implementation is used.
206 Internal implementation is smaller.
207
208config FEATURE_CHECK_UNICODE_IN_ENV
209 bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables"
210 default n
211 depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE
212 help
213 With this option on, Unicode support is activated
214 only if locale-related variables have the value of the form
215 "xxxx.utf8"
216
217 Otherwise, Unicode support will be always enabled and active.
218
219config SUBST_WCHAR
220 int "Character code to substitute unprintable characters with"
221 depends on UNICODE_SUPPORT
222 default 63
223 help
224 Typical values are 63 for '?' (works with any output device),
225 30 for ASCII substitute control code,
226 65533 (0xfffd) for Unicode replacement character.
227
228config LAST_SUPPORTED_WCHAR
229 int "Range of supported Unicode characters"
230 depends on UNICODE_SUPPORT
231 default 767
232 help
233 Any character with Unicode value bigger than this is assumed
234 to be non-printable on output device. Many applets replace
235 such characters with substitution character.
236
237 The idea is that many valid printable Unicode chars
238 nevertheless are not displayed correctly. Think about
239 combining charachers, double-wide hieroglyphs, obscure
240 characters in dozens of ancient scripts...
241 Many terminals, terminal emulators, xterms etc will fail
242 to handle them correctly. Choose the smallest value
243 which suits your needs.
244
245 Typical values are:
246 126 - ASCII only
247 767 (0x2ff) - there are no combining chars in [0..767] range
248 (the range includes Latin 1, Latin Ext. A and B),
249 code is ~700 bytes smaller for this case.
250 4351 (0x10ff) - there are no double-wide chars in [0..4351] range,
251 code is ~300 bytes smaller for this case.
252 12799 (0x31ff) - nearly all non-ideographic characters are
253 available in [0..12799] range, including
254 East Asian scripts like katakana, hiragana, hangul,
255 bopomofo...
256 0 - off, any valid printable Unicode character will be printed.
257
258config UNICODE_COMBINING_WCHARS
259 bool "Allow zero-width Unicode characters on output"
260 default n
261 depends on UNICODE_SUPPORT
262 help
263 With this option off, any Unicode char with width of 0
264 is substituted on output.
265
266config UNICODE_WIDE_WCHARS
267 bool "Allow wide Unicode characters on output"
268 default n
269 depends on UNICODE_SUPPORT
270 help
271 With this option off, any Unicode char with width > 1
272 is substituted on output.
273
274config UNICODE_BIDI_SUPPORT
275 bool "Bidirectional character-aware line input"
276 default n
277 depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE
278 help
279 With this option on, right-to-left Unicode characters
280 are treated differently on input (e.g. cursor movement).
281
282config UNICODE_NEUTRAL_TABLE
283 bool "In bidi input, support non-ASCII neutral chars too"
284 default n
285 depends on UNICODE_BIDI_SUPPORT
286 help
287 In most cases it's enough to treat only ASCII non-letters
288 (i.e. punctuation, numbers and space) as characters
289 with neutral directionality.
290 With this option on, more extensive (and bigger) table
291 of neutral chars will be used.
292
293config UNICODE_PRESERVE_BROKEN
294 bool "Make it possible to enter sequences of chars which are not Unicode"
295 default n
296 depends on UNICODE_SUPPORT
297 help
298 With this option on, on line-editing input (such as used by shells)
299 invalid UTF-8 bytes are not substituted with the selected
300 substitution character.
301 For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
302 at shell prompt will list file named 0xff (single char name
303 with char value 255), not file named '?'.
304
156config FEATURE_NON_POSIX_CP 305config FEATURE_NON_POSIX_CP
157 bool "Non-POSIX, but safer, copying to special nodes" 306 bool "Non-POSIX, but safer, copying to special nodes"
158 default y 307 default y
@@ -177,6 +326,19 @@ config FEATURE_VERBOSE_CP_MESSAGE
177 cp: cannot stat '/vmlinuz/file': Not a directory 326 cp: cannot stat '/vmlinuz/file': Not a directory
178 This will cost you ~60 bytes. 327 This will cost you ~60 bytes.
179 328
329config FEATURE_USE_SENDFILE
330 bool "Use sendfile system call"
331 default y
332 select PLATFORM_LINUX
333 help
334 When enabled, busybox will use the kernel sendfile() function
335 instead of read/write loops to copy data between file descriptors
336 (for example, cp command does this a lot).
337 If sendfile() doesn't work, copying code falls back to read/write
338 loop. sendfile() was originally implemented for faster I/O
339 from files to sockets, but since Linux 2.6.33 it was extended
340 to work for many more file types.
341
180config FEATURE_COPYBUF_KB 342config FEATURE_COPYBUF_KB
181 int "Copy buffer size, in kilobytes" 343 int "Copy buffer size, in kilobytes"
182 range 1 1024 344 range 1 1024
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 4aa40454f..1fe0eb44f 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -821,7 +821,7 @@ static int busybox_main(char **argv)
821 col += len2; 821 col += len2;
822 a += len2 - 1; 822 a += len2 - 1;
823 } 823 }
824 full_write2_str("\n\n"); 824 full_write2_str("\n");
825 return 0; 825 return 0;
826 } 826 }
827 827
@@ -936,20 +936,21 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
936} 936}
937# endif /* NUM_APPLETS > 0 */ 937# endif /* NUM_APPLETS > 0 */
938 938
939# if ENABLE_BUSYBOX || NUM_APPLETS > 0
939static NORETURN void run_applet_and_exit(const char *name, char **argv) 940static NORETURN void run_applet_and_exit(const char *name, char **argv)
940{ 941{
941# if ENABLE_BUSYBOX 942# if ENABLE_BUSYBOX
942 if (is_prefixed_with(name, "busybox")) 943 if (is_prefixed_with(name, "busybox"))
943 exit(busybox_main(argv)); 944 exit(busybox_main(argv));
944# endif 945# endif
945# if NUM_APPLETS > 0 946# if NUM_APPLETS > 0
946 /* find_applet_by_name() search is more expensive, so goes second */ 947 /* find_applet_by_name() search is more expensive, so goes second */
947 { 948 {
948 int applet = find_applet_by_name(name); 949 int applet = find_applet_by_name(name);
949 if (applet >= 0) 950 if (applet >= 0)
950 run_applet_no_and_exit(applet, argv); 951 run_applet_no_and_exit(applet, argv);
951 } 952 }
952# endif 953# endif
953 954
954 /*bb_error_msg_and_die("applet not found"); - links in printf */ 955 /*bb_error_msg_and_die("applet not found"); - links in printf */
955 full_write2_str(applet_name); 956 full_write2_str(applet_name);
@@ -957,11 +958,11 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv)
957 /* POSIX: "If a command is not found, the exit status shall be 127" */ 958 /* POSIX: "If a command is not found, the exit status shall be 127" */
958 exit(127); 959 exit(127);
959} 960}
961# endif
960 962
961#endif /* !defined(SINGLE_APPLET_MAIN) */ 963#endif /* !defined(SINGLE_APPLET_MAIN) */
962 964
963 965
964
965#if ENABLE_BUILD_LIBBUSYBOX 966#if ENABLE_BUILD_LIBBUSYBOX
966int lbb_main(char **argv) 967int lbb_main(char **argv)
967#else 968#else
@@ -1025,6 +1026,7 @@ int main(int argc UNUSED_PARAM, char **argv)
1025#endif 1026#endif
1026 1027
1027#if defined(SINGLE_APPLET_MAIN) 1028#if defined(SINGLE_APPLET_MAIN)
1029
1028 /* Only one applet is selected in .config */ 1030 /* Only one applet is selected in .config */
1029 if (argv[1] && is_prefixed_with(argv[0], "busybox")) { 1031 if (argv[1] && is_prefixed_with(argv[0], "busybox")) {
1030 /* "busybox <applet> <params>" should still work as expected */ 1032 /* "busybox <applet> <params>" should still work as expected */
@@ -1033,9 +1035,16 @@ int main(int argc UNUSED_PARAM, char **argv)
1033 /* applet_names in this case is just "applet\0\0" */ 1035 /* applet_names in this case is just "applet\0\0" */
1034 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv)); 1036 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
1035 return SINGLE_APPLET_MAIN(argc, argv); 1037 return SINGLE_APPLET_MAIN(argc, argv);
1038
1039#elif !ENABLE_BUSYBOX && NUM_APPLETS == 0
1040
1041 full_write2_str(bb_basename(argv[0]));
1042 full_write2_str(": no applets enabled\n");
1043 exit(127);
1044
1036#else 1045#else
1037 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
1038 1046
1047 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
1039# if !ENABLE_BUSYBOX 1048# if !ENABLE_BUSYBOX
1040 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) 1049 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox"))
1041 argv++; 1050 argv++;
@@ -1067,9 +1076,8 @@ int main(int argc UNUSED_PARAM, char **argv)
1067 } 1076 }
1068 } 1077 }
1069 applet_name = bb_basename(applet_name); 1078 applet_name = bb_basename(applet_name);
1070
1071 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 1079 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
1072
1073 run_applet_and_exit(applet_name, argv); 1080 run_applet_and_exit(applet_name, argv);
1081
1074#endif 1082#endif
1075} 1083}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 06f708b62..5d9080131 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -13,7 +13,6 @@
13 * 13 *
14 * This code is 'as is' with no warranty. 14 * This code is 'as is' with no warranty.
15 */ 15 */
16
17/* 16/*
18 * Usage and known bugs: 17 * Usage and known bugs:
19 * Terminal key codes are not extensive, more needs to be added. 18 * Terminal key codes are not extensive, more needs to be added.
@@ -23,9 +22,6 @@
23 * Ctrl-E also works as End. 22 * Ctrl-E also works as End.
24 * 23 *
25 * The following readline-like commands are not implemented: 24 * The following readline-like commands are not implemented:
26 * ESC-b -- Move back one word
27 * ESC-f -- Move forward one word
28 * ESC-d -- Delete forward one word
29 * CTL-t -- Transpose two characters 25 * CTL-t -- Transpose two characters
30 * 26 *
31 * lineedit does not know that the terminal escape sequences do not 27 * lineedit does not know that the terminal escape sequences do not
@@ -133,8 +129,7 @@ static const char null_str[] ALIGN1 = "";
133struct lineedit_statics { 129struct lineedit_statics {
134 line_input_t *state; 130 line_input_t *state;
135 131
136 volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */ 132 unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
137 sighandler_t previous_SIGWINCH_handler;
138 133
139 unsigned cmdedit_x; /* real x (col) terminal position */ 134 unsigned cmdedit_x; /* real x (col) terminal position */
140 unsigned cmdedit_y; /* pseudoreal y (row) terminal position */ 135 unsigned cmdedit_y; /* pseudoreal y (row) terminal position */
@@ -159,15 +154,22 @@ struct lineedit_statics {
159 unsigned num_matches; 154 unsigned num_matches;
160#endif 155#endif
161 156
157 unsigned SIGWINCH_saved;
158 volatile unsigned SIGWINCH_count;
159 volatile smallint ok_to_redraw;
160
162#if ENABLE_FEATURE_EDITING_VI 161#if ENABLE_FEATURE_EDITING_VI
163# define DELBUFSIZ 128 162# define DELBUFSIZ 128
164 CHAR_T *delptr;
165 smallint newdelflag; /* whether delbuf should be reused yet */ 163 smallint newdelflag; /* whether delbuf should be reused yet */
164 CHAR_T *delptr;
166 CHAR_T delbuf[DELBUFSIZ]; /* a place to store deleted characters */ 165 CHAR_T delbuf[DELBUFSIZ]; /* a place to store deleted characters */
167#endif 166#endif
168#if ENABLE_FEATURE_EDITING_ASK_TERMINAL 167#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
169 smallint sent_ESC_br6n; 168 smallint sent_ESC_br6n;
170#endif 169#endif
170
171 /* Largish struct, keeping it last results in smaller code */
172 struct sigaction SIGWINCH_handler;
171}; 173};
172 174
173/* See lineedit_ptr_hack.c */ 175/* See lineedit_ptr_hack.c */
@@ -176,7 +178,6 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
176#define S (*lineedit_ptr_to_statics) 178#define S (*lineedit_ptr_to_statics)
177#define state (S.state ) 179#define state (S.state )
178#define cmdedit_termw (S.cmdedit_termw ) 180#define cmdedit_termw (S.cmdedit_termw )
179#define previous_SIGWINCH_handler (S.previous_SIGWINCH_handler)
180#define cmdedit_x (S.cmdedit_x ) 181#define cmdedit_x (S.cmdedit_x )
181#define cmdedit_y (S.cmdedit_y ) 182#define cmdedit_y (S.cmdedit_y )
182#define cmdedit_prmt_len (S.cmdedit_prmt_len) 183#define cmdedit_prmt_len (S.cmdedit_prmt_len)
@@ -474,14 +475,10 @@ static void beep(void)
474 475
475static void put_prompt(void) 476static void put_prompt(void)
476{ 477{
477 unsigned w;
478
479 fputs(cmdedit_prompt, stdout); 478 fputs(cmdedit_prompt, stdout);
480 fflush_all();
481 cursor = 0; 479 cursor = 0;
482 w = cmdedit_termw; /* read volatile var once */ 480 cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */
483 cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ 481 cmdedit_x = cmdedit_prmt_len % cmdedit_termw;
484 cmdedit_x = cmdedit_prmt_len % w;
485} 482}
486 483
487/* Move back one character */ 484/* Move back one character */
@@ -555,13 +552,11 @@ static void input_backward(unsigned num)
555 put_cur_glyph_and_inc_cursor(); 552 put_cur_glyph_and_inc_cursor();
556 } else { 553 } else {
557 int lines_up; 554 int lines_up;
558 unsigned width;
559 /* num = chars to go back from the beginning of current line: */ 555 /* num = chars to go back from the beginning of current line: */
560 num -= cmdedit_x; 556 num -= cmdedit_x;
561 width = cmdedit_termw; /* read volatile var once */
562 /* num=1...w: one line up, w+1...2w: two, etc: */ 557 /* num=1...w: one line up, w+1...2w: two, etc: */
563 lines_up = 1 + (num - 1) / width; 558 lines_up = 1 + (num - 1) / cmdedit_termw;
564 cmdedit_x = (width * cmdedit_y - num) % width; 559 cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw;
565 cmdedit_y -= lines_up; 560 cmdedit_y -= lines_up;
566 /* go to 1st column; go up */ 561 /* go to 1st column; go up */
567 printf("\r" ESC"[%uA", lines_up); 562 printf("\r" ESC"[%uA", lines_up);
@@ -2052,28 +2047,29 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2052} 2047}
2053#endif 2048#endif
2054 2049
2055static void cmdedit_setwidth(unsigned w, int redraw_flg) 2050static void cmdedit_setwidth(void)
2056{ 2051{
2057 cmdedit_termw = w; 2052 int new_y;
2058 if (redraw_flg) { 2053
2059 /* new y for current cursor */ 2054 cmdedit_termw = get_terminal_width(STDIN_FILENO);
2060 int new_y = (cursor + cmdedit_prmt_len) / w; 2055 /* new y for current cursor */
2061 /* redraw */ 2056 new_y = (cursor + cmdedit_prmt_len) / cmdedit_termw;
2062 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor); 2057 /* redraw */
2063 fflush_all(); 2058 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor);
2064 }
2065} 2059}
2066 2060
2067static void win_changed(int nsig) 2061static void win_changed(int nsig UNUSED_PARAM)
2068{ 2062{
2069 int sv_errno = errno; 2063 if (S.ok_to_redraw) {
2070 unsigned width; 2064 /* We are in read_key(), safe to redraw immediately */
2071 2065 int sv_errno = errno;
2072 get_terminal_width_height(0, &width, NULL); 2066 cmdedit_setwidth();
2073//FIXME: cmdedit_setwidth() -> redraw() -> printf() -> KABOOM! (we are in signal handler!) 2067 fflush_all();
2074 cmdedit_setwidth(width, /*redraw_flg:*/ nsig); 2068 errno = sv_errno;
2075 2069 } else {
2076 errno = sv_errno; 2070 /* Signal main loop that redraw is necessary */
2071 S.SIGWINCH_count++;
2072 }
2077} 2073}
2078 2074
2079static int lineedit_read_key(char *read_key_buffer, int timeout) 2075static int lineedit_read_key(char *read_key_buffer, int timeout)
@@ -2084,6 +2080,7 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
2084 int unicode_idx = 0; 2080 int unicode_idx = 0;
2085#endif 2081#endif
2086 2082
2083 fflush_all();
2087 while (1) { 2084 while (1) {
2088 /* Wait for input. TIMEOUT = -1 makes read_key wait even 2085 /* Wait for input. TIMEOUT = -1 makes read_key wait even
2089 * on nonblocking stdin, TIMEOUT = 50 makes sure we won't 2086 * on nonblocking stdin, TIMEOUT = 50 makes sure we won't
@@ -2092,7 +2089,9 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
2092 * 2089 *
2093 * Note: read_key sets errno to 0 on success. 2090 * Note: read_key sets errno to 0 on success.
2094 */ 2091 */
2092 S.ok_to_redraw = 1;
2095 ic = read_key(STDIN_FILENO, read_key_buffer, timeout); 2093 ic = read_key(STDIN_FILENO, read_key_buffer, timeout);
2094 S.ok_to_redraw = 0;
2096 if (errno) { 2095 if (errno) {
2097#if ENABLE_UNICODE_SUPPORT 2096#if ENABLE_UNICODE_SUPPORT
2098 if (errno == EAGAIN && unicode_idx != 0) 2097 if (errno == EAGAIN && unicode_idx != 0)
@@ -2223,7 +2222,6 @@ static int32_t reverse_i_search(void)
2223 int h; 2222 int h;
2224 unsigned match_buf_len = strlen(match_buf); 2223 unsigned match_buf_len = strlen(match_buf);
2225 2224
2226 fflush_all();
2227//FIXME: correct timeout? 2225//FIXME: correct timeout?
2228 ic = lineedit_read_key(read_key_buffer, -1); 2226 ic = lineedit_read_key(read_key_buffer, -1);
2229 2227
@@ -2325,6 +2323,7 @@ static int32_t reverse_i_search(void)
2325 * Returns: 2323 * Returns:
2326 * -1 on read errors or EOF, or on bare Ctrl-D, 2324 * -1 on read errors or EOF, or on bare Ctrl-D,
2327 * 0 on ctrl-C (the line entered is still returned in 'command'), 2325 * 0 on ctrl-C (the line entered is still returned in 'command'),
2326 * (in both cases the cursor remains on the input line, '\n' is not printed)
2328 * >0 length of input string, including terminating '\n' 2327 * >0 length of input string, including terminating '\n'
2329 */ 2328 */
2330int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) 2329int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
@@ -2359,7 +2358,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2359 * tty is still in "raw mode"). 2358 * tty is still in "raw mode").
2360 */ 2359 */
2361 parse_and_put_prompt(prompt); 2360 parse_and_put_prompt(prompt);
2362 /* fflush_all(); - done by parse_and_put_prompt */ 2361 fflush_all();
2363 if (fgets(command, maxsize, stdin) == NULL) 2362 if (fgets(command, maxsize, stdin) == NULL)
2364 len = -1; /* EOF or error */ 2363 len = -1; /* EOF or error */
2365 else 2364 else
@@ -2435,9 +2434,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2435 ask_terminal(); 2434 ask_terminal();
2436 2435
2437 /* Install window resize handler (NB: after *all* init is complete) */ 2436 /* Install window resize handler (NB: after *all* init is complete) */
2438//FIXME: save entire sigaction! 2437 S.SIGWINCH_handler.sa_handler = win_changed;
2439 previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); 2438 S.SIGWINCH_handler.sa_flags = SA_RESTART;
2440 win_changed(0); /* get initial window size */ 2439 sigaction(SIGWINCH, &S.SIGWINCH_handler, &S.SIGWINCH_handler);
2440
2441 cmdedit_termw = get_terminal_width(STDIN_FILENO);
2441 2442
2442 read_key_buffer[0] = 0; 2443 read_key_buffer[0] = 0;
2443 while (1) { 2444 while (1) {
@@ -2450,8 +2451,14 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2450 * in one place. 2451 * in one place.
2451 */ 2452 */
2452 int32_t ic, ic_raw; 2453 int32_t ic, ic_raw;
2454 unsigned count;
2455
2456 count = S.SIGWINCH_count;
2457 if (S.SIGWINCH_saved != count) {
2458 S.SIGWINCH_saved = count;
2459 cmdedit_setwidth();
2460 }
2453 2461
2454 fflush_all();
2455 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); 2462 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
2456#if ENABLE_PLATFORM_MINGW32 2463#if ENABLE_PLATFORM_MINGW32
2457 /* scroll to cursor position on any keypress */ 2464 /* scroll to cursor position on any keypress */
@@ -2565,6 +2572,24 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2565 while (cursor > 0 && !BB_isspace(command_ps[cursor-1])) 2572 while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
2566 input_backspace(); 2573 input_backspace();
2567 break; 2574 break;
2575 case KEYCODE_ALT_D: {
2576 /* Delete word forward */
2577 int nc, sc = cursor;
2578 ctrl_right();
2579 nc = cursor - sc;
2580 input_backward(nc);
2581 while (--nc >= 0)
2582 input_delete(1);
2583 break;
2584 }
2585 case KEYCODE_ALT_BACKSPACE: {
2586 /* Delete word backward */
2587 int sc = cursor;
2588 ctrl_left();
2589 while (sc-- > cursor)
2590 input_delete(1);
2591 break;
2592 }
2568#if ENABLE_FEATURE_REVERSE_SEARCH 2593#if ENABLE_FEATURE_REVERSE_SEARCH
2569 case CTRL('R'): 2594 case CTRL('R'):
2570 ic = ic_raw = reverse_i_search(); 2595 ic = ic_raw = reverse_i_search();
@@ -2792,7 +2817,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2792 && ic_raw == initial_settings.c_cc[VINTR] 2817 && ic_raw == initial_settings.c_cc[VINTR]
2793 ) { 2818 ) {
2794 /* Ctrl-C (usually) - stop gathering input */ 2819 /* Ctrl-C (usually) - stop gathering input */
2795 goto_new_line();
2796 command_len = 0; 2820 command_len = 0;
2797 break_out = -1; /* "do not append '\n'" */ 2821 break_out = -1; /* "do not append '\n'" */
2798 break; 2822 break;
@@ -2914,7 +2938,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2914 /* restore initial_settings */ 2938 /* restore initial_settings */
2915 tcsetattr_stdin_TCSANOW(&initial_settings); 2939 tcsetattr_stdin_TCSANOW(&initial_settings);
2916 /* restore SIGWINCH handler */ 2940 /* restore SIGWINCH handler */
2917 signal(SIGWINCH, previous_SIGWINCH_handler); 2941 sigaction_set(SIGWINCH, &S.SIGWINCH_handler);
2918 fflush_all(); 2942 fflush_all();
2919 2943
2920 len = command_len; 2944 len = command_len;
diff --git a/libbb/read_key.c b/libbb/read_key.c
index ace23defb..951786869 100644
--- a/libbb/read_key.c
+++ b/libbb/read_key.c
@@ -18,8 +18,20 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
18 /* Known escape sequences for cursor and function keys. 18 /* Known escape sequences for cursor and function keys.
19 * See "Xterm Control Sequences" 19 * See "Xterm Control Sequences"
20 * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html 20 * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
21 * Array should be sorted from shortest to longest.
21 */ 22 */
22 static const char esccmds[] ALIGN1 = { 23 static const char esccmds[] ALIGN1 = {
24 '\x7f' |0x80,KEYCODE_ALT_BACKSPACE,
25 '\b' |0x80,KEYCODE_ALT_BACKSPACE,
26 'd' |0x80,KEYCODE_ALT_D ,
27 /* lineedit mimics bash: Alt-f and Alt-b are forward/backward
28 * word jumps. We cheat here and make them return ALT_LEFT/RIGHT
29 * keycodes. This way, lineedit need no special code to handle them.
30 * If we'll need to distinguish them, introduce new ALT_F/B keycodes,
31 * and update lineedit to react to them.
32 */
33 'f' |0x80,KEYCODE_ALT_RIGHT,
34 'b' |0x80,KEYCODE_ALT_LEFT,
23 'O','A' |0x80,KEYCODE_UP , 35 'O','A' |0x80,KEYCODE_UP ,
24 'O','B' |0x80,KEYCODE_DOWN , 36 'O','B' |0x80,KEYCODE_DOWN ,
25 'O','C' |0x80,KEYCODE_RIGHT , 37 'O','C' |0x80,KEYCODE_RIGHT ,