diff options
| author | Ron Yorston <rmy@pobox.com> | 2016-11-29 11:26:45 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2016-11-29 11:26:45 +0000 |
| commit | bb8d79eadbba1942dbdb9f9cee5c47833afe269f (patch) | |
| tree | b8c517e9ca895d60d7227aef7177b6291df5e2cd /libbb | |
| parent | 9fa1e4990e655a85025c9d270a1606983e375e47 (diff) | |
| parent | 7d877fc9312a742b06125927bb1d34bd35398c6c (diff) | |
| download | busybox-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.src | 162 | ||||
| -rw-r--r-- | libbb/appletlib.c | 26 | ||||
| -rw-r--r-- | libbb/lineedit.c | 112 | ||||
| -rw-r--r-- | libbb/read_key.c | 12 |
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 | ||
| 8 | INSERT | 8 | INSERT |
| 9 | 9 | ||
| 10 | choice | ||
| 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 | |||
| 23 | config FEATURE_BUFFERS_USE_MALLOC | ||
| 24 | bool "Allocate with Malloc" | ||
| 25 | |||
| 26 | config FEATURE_BUFFERS_GO_ON_STACK | ||
| 27 | bool "Allocate on the Stack" | ||
| 28 | |||
| 29 | config FEATURE_BUFFERS_GO_IN_BSS | ||
| 30 | bool "Allocate in the .bss section" | ||
| 31 | |||
| 32 | endchoice | ||
| 33 | |||
| 10 | config PASSWORD_MINLEN | 34 | config 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 | ||
| 180 | config 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 | |||
| 187 | config 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 | |||
| 199 | config 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 | |||
| 208 | config 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 | |||
| 219 | config 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 | |||
| 228 | config 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 | |||
| 258 | config 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 | |||
| 266 | config 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 | |||
| 274 | config 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 | |||
| 282 | config 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 | |||
| 293 | config 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 | |||
| 156 | config FEATURE_NON_POSIX_CP | 305 | config 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 | ||
| 329 | config 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 | |||
| 180 | config FEATURE_COPYBUF_KB | 342 | config 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 | ||
| 939 | static NORETURN void run_applet_and_exit(const char *name, char **argv) | 940 | static 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 |
| 966 | int lbb_main(char **argv) | 967 | int 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 = ""; | |||
| 133 | struct lineedit_statics { | 129 | struct 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 | ||
| 475 | static void put_prompt(void) | 476 | static 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 | ||
| 2055 | static void cmdedit_setwidth(unsigned w, int redraw_flg) | 2050 | static 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 | ||
| 2067 | static void win_changed(int nsig) | 2061 | static 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 | ||
| 2079 | static int lineedit_read_key(char *read_key_buffer, int timeout) | 2075 | static 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 | */ |
| 2330 | int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) | 2329 | int 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 , |
