diff options
| author | Ron Yorston <rmy@pobox.com> | 2017-01-04 11:32:33 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2017-01-04 11:41:38 +0000 |
| commit | f9cf712f8a640ac2d250dfa77dd809ab033f618a (patch) | |
| tree | c8f6135b5842e0110ca54d6690ab95b28792bb1e /shell | |
| parent | 71ecc8033e6989996057b32577e71148fd544596 (diff) | |
| parent | c6725b0af68238a456690146adec763c04f66c82 (diff) | |
| download | busybox-w32-f9cf712f8a640ac2d250dfa77dd809ab033f618a.tar.gz busybox-w32-f9cf712f8a640ac2d250dfa77dd809ab033f618a.tar.bz2 busybox-w32-f9cf712f8a640ac2d250dfa77dd809ab033f618a.zip | |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/Config.src | 45 | ||||
| -rw-r--r-- | shell/Kbuild.src | 2 | ||||
| -rw-r--r-- | shell/ash.c | 293 | ||||
| -rw-r--r-- | shell/ash_test/ash-misc/exitcode2.right | 4 | ||||
| -rwxr-xr-x | shell/ash_test/ash-misc/exitcode2.tests | 12 | ||||
| -rw-r--r-- | shell/hush.c | 130 | ||||
| -rw-r--r-- | shell/hush_test/hush-misc/exitcode2.right | 4 | ||||
| -rwxr-xr-x | shell/hush_test/hush-misc/exitcode2.tests | 12 | ||||
| -rw-r--r-- | shell/math.h | 2 |
9 files changed, 275 insertions, 229 deletions
diff --git a/shell/Config.src b/shell/Config.src index e4df35973..7f5f67050 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
| @@ -5,34 +5,30 @@ | |||
| 5 | 5 | ||
| 6 | menu "Shells" | 6 | menu "Shells" |
| 7 | 7 | ||
| 8 | INSERT | ||
| 9 | |||
| 10 | 8 | ||
| 11 | choice | 9 | choice |
| 12 | prompt "Choose which shell is aliased to 'sh' name" | 10 | prompt "Choose which shell is aliased to 'sh' name" |
| 13 | default FEATURE_SH_IS_ASH | 11 | default SH_IS_ASH |
| 14 | help | 12 | help |
| 15 | Choose which shell you want to be executed by 'sh' alias. | 13 | Choose which shell you want to be executed by 'sh' alias. |
| 16 | The ash shell is the most bash compatible and full featured one. | 14 | The ash shell is the most bash compatible and full featured one. |
| 17 | 15 | ||
| 18 | # note: cannot use "select ASH" here, it breaks "make allnoconfig" | 16 | # note: cannot use "select ASH" here, it breaks "make allnoconfig" |
| 19 | config FEATURE_SH_IS_ASH | 17 | config SH_IS_ASH |
| 20 | depends on ASH | ||
| 21 | bool "ash" | ||
| 22 | depends on !NOMMU | 18 | depends on !NOMMU |
| 19 | bool "ash" | ||
| 23 | 20 | ||
| 24 | config FEATURE_SH_IS_HUSH | 21 | config SH_IS_HUSH |
| 25 | depends on HUSH | ||
| 26 | bool "hush" | 22 | bool "hush" |
| 27 | 23 | ||
| 28 | config FEATURE_SH_IS_NONE | 24 | config SH_IS_NONE |
| 29 | bool "none" | 25 | bool "none" |
| 30 | 26 | ||
| 31 | endchoice | 27 | endchoice |
| 32 | 28 | ||
| 33 | choice | 29 | choice |
| 34 | prompt "Choose which shell is aliased to 'bash' name" | 30 | prompt "Choose which shell is aliased to 'bash' name" |
| 35 | default FEATURE_BASH_IS_NONE | 31 | default BASH_IS_NONE |
| 36 | help | 32 | help |
| 37 | Choose which shell you want to be executed by 'bash' alias. | 33 | Choose which shell you want to be executed by 'bash' alias. |
| 38 | The ash shell is the most bash compatible and full featured one. | 34 | The ash shell is the most bash compatible and full featured one. |
| @@ -47,32 +43,33 @@ choice | |||
| 47 | can't be used for running them because it won't recongnize | 43 | can't be used for running them because it won't recongnize |
| 48 | "bash" as a supported applet name. | 44 | "bash" as a supported applet name. |
| 49 | 45 | ||
| 50 | config FEATURE_BASH_IS_ASH | 46 | config BASH_IS_ASH |
| 51 | depends on ASH | ||
| 52 | bool "ash" | ||
| 53 | depends on !NOMMU | 47 | depends on !NOMMU |
| 48 | bool "ash" | ||
| 54 | 49 | ||
| 55 | config FEATURE_BASH_IS_HUSH | 50 | config BASH_IS_HUSH |
| 56 | depends on HUSH | ||
| 57 | bool "hush" | 51 | bool "hush" |
| 58 | 52 | ||
| 59 | config FEATURE_BASH_IS_NONE | 53 | config BASH_IS_NONE |
| 60 | bool "none" | 54 | bool "none" |
| 61 | 55 | ||
| 62 | endchoice | 56 | endchoice |
| 63 | 57 | ||
| 64 | 58 | ||
| 65 | config SH_MATH_SUPPORT | 59 | INSERT |
| 60 | |||
| 61 | |||
| 62 | config FEATURE_SH_MATH | ||
| 66 | bool "POSIX math support" | 63 | bool "POSIX math support" |
| 67 | default y | 64 | default y |
| 68 | depends on ASH || HUSH | 65 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH |
| 69 | help | 66 | help |
| 70 | Enable math support in the shell via $((...)) syntax. | 67 | Enable math support in the shell via $((...)) syntax. |
| 71 | 68 | ||
| 72 | config SH_MATH_SUPPORT_64 | 69 | config FEATURE_SH_MATH_64 |
| 73 | bool "Extend POSIX math support to 64 bit" | 70 | bool "Extend POSIX math support to 64 bit" |
| 74 | default y | 71 | default y |
| 75 | depends on SH_MATH_SUPPORT | 72 | depends on FEATURE_SH_MATH |
| 76 | help | 73 | help |
| 77 | Enable 64-bit math support in the shell. This will make the shell | 74 | Enable 64-bit math support in the shell. This will make the shell |
| 78 | slightly larger, but will allow computation with very large numbers. | 75 | slightly larger, but will allow computation with very large numbers. |
| @@ -81,14 +78,14 @@ config SH_MATH_SUPPORT_64 | |||
| 81 | config FEATURE_SH_EXTRA_QUIET | 78 | config FEATURE_SH_EXTRA_QUIET |
| 82 | bool "Hide message on interactive shell startup" | 79 | bool "Hide message on interactive shell startup" |
| 83 | default y | 80 | default y |
| 84 | depends on HUSH || ASH | 81 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH |
| 85 | help | 82 | help |
| 86 | Remove the busybox introduction when starting a shell. | 83 | Remove the busybox introduction when starting a shell. |
| 87 | 84 | ||
| 88 | config FEATURE_SH_STANDALONE | 85 | config FEATURE_SH_STANDALONE |
| 89 | bool "Standalone shell" | 86 | bool "Standalone shell" |
| 90 | default n | 87 | default n |
| 91 | depends on (HUSH || ASH) | 88 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH |
| 92 | help | 89 | help |
| 93 | This option causes busybox shells to use busybox applets | 90 | This option causes busybox shells to use busybox applets |
| 94 | in preference to executables in the PATH whenever possible. For | 91 | in preference to executables in the PATH whenever possible. For |
| @@ -121,7 +118,7 @@ config FEATURE_SH_STANDALONE | |||
| 121 | config FEATURE_SH_NOFORK | 118 | config FEATURE_SH_NOFORK |
| 122 | bool "Run 'nofork' applets directly" | 119 | bool "Run 'nofork' applets directly" |
| 123 | default n | 120 | default n |
| 124 | depends on (HUSH || ASH) | 121 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH |
| 125 | help | 122 | help |
| 126 | This option causes busybox shells to not execute typical | 123 | This option causes busybox shells to not execute typical |
| 127 | fork/exec/wait sequence, but call <applet>_main directly, | 124 | fork/exec/wait sequence, but call <applet>_main directly, |
| @@ -139,7 +136,7 @@ config FEATURE_SH_NOFORK | |||
| 139 | config FEATURE_SH_HISTFILESIZE | 136 | config FEATURE_SH_HISTFILESIZE |
| 140 | bool "Use $HISTFILESIZE" | 137 | bool "Use $HISTFILESIZE" |
| 141 | default y | 138 | default y |
| 142 | depends on HUSH || ASH | 139 | depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH |
| 143 | help | 140 | help |
| 144 | This option makes busybox shells to use $HISTFILESIZE variable | 141 | This option makes busybox shells to use $HISTFILESIZE variable |
| 145 | to set shell history size. Note that its max value is capped | 142 | to set shell history size. Note that its max value is capped |
diff --git a/shell/Kbuild.src b/shell/Kbuild.src index c00aec92a..6bba4989f 100644 --- a/shell/Kbuild.src +++ b/shell/Kbuild.src | |||
| @@ -8,4 +8,4 @@ lib-y:= | |||
| 8 | 8 | ||
| 9 | INSERT | 9 | INSERT |
| 10 | 10 | ||
| 11 | lib-$(CONFIG_SH_MATH_SUPPORT) += math.o | 11 | lib-$(CONFIG_FEATURE_SH_MATH) += math.o |
diff --git a/shell/ash.c b/shell/ash.c index 2e7f68c05..35618937a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -30,80 +30,6 @@ | |||
| 30 | * - fake $PPID | 30 | * - fake $PPID |
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | /* | ||
| 34 | * The following should be set to reflect the type of system you have: | ||
| 35 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. | ||
| 36 | * define SYSV if you are running under System V. | ||
| 37 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) | ||
| 38 | * define DEBUG=2 to compile in and turn on debugging. | ||
| 39 | * | ||
| 40 | * When debugging is on (DEBUG is 1 and "set -o debug" was executed), | ||
| 41 | * debugging info will be written to ./trace and a quit signal | ||
| 42 | * will generate a core dump. | ||
| 43 | */ | ||
| 44 | #define DEBUG 0 | ||
| 45 | /* Tweak debug output verbosity here */ | ||
| 46 | #define DEBUG_TIME 0 | ||
| 47 | #define DEBUG_PID 1 | ||
| 48 | #define DEBUG_SIG 1 | ||
| 49 | #define DEBUG_INTONOFF 0 | ||
| 50 | |||
| 51 | #define PROFILE 0 | ||
| 52 | |||
| 53 | #define JOBS ENABLE_ASH_JOB_CONTROL | ||
| 54 | |||
| 55 | #include <setjmp.h> | ||
| 56 | #include <fnmatch.h> | ||
| 57 | #include <sys/times.h> | ||
| 58 | #include <sys/utsname.h> /* for setting $HOSTNAME */ | ||
| 59 | |||
| 60 | #include "busybox.h" /* for applet_names */ | ||
| 61 | |||
| 62 | #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 | ||
| 63 | /* Bionic at least up to version 24 has no glob() */ | ||
| 64 | # undef ENABLE_ASH_INTERNAL_GLOB | ||
| 65 | # define ENABLE_ASH_INTERNAL_GLOB 1 | ||
| 66 | #endif | ||
| 67 | |||
| 68 | #if !ENABLE_ASH_INTERNAL_GLOB | ||
| 69 | # include <glob.h> | ||
| 70 | #endif | ||
| 71 | |||
| 72 | #include "unicode.h" | ||
| 73 | #include "shell_common.h" | ||
| 74 | #if ENABLE_SH_MATH_SUPPORT | ||
| 75 | # include "math.h" | ||
| 76 | #endif | ||
| 77 | #if ENABLE_ASH_RANDOM_SUPPORT | ||
| 78 | # include "random.h" | ||
| 79 | #else | ||
| 80 | # define CLEAR_RANDOM_T(rnd) ((void)0) | ||
| 81 | #endif | ||
| 82 | |||
| 83 | #include "NUM_APPLETS.h" | ||
| 84 | #if NUM_APPLETS == 1 | ||
| 85 | /* STANDALONE does not make sense, and won't compile */ | ||
| 86 | # undef CONFIG_FEATURE_SH_STANDALONE | ||
| 87 | # undef ENABLE_FEATURE_SH_STANDALONE | ||
| 88 | # undef IF_FEATURE_SH_STANDALONE | ||
| 89 | # undef IF_NOT_FEATURE_SH_STANDALONE | ||
| 90 | # define ENABLE_FEATURE_SH_STANDALONE 0 | ||
| 91 | # define IF_FEATURE_SH_STANDALONE(...) | ||
| 92 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ | ||
| 93 | #endif | ||
| 94 | |||
| 95 | #ifndef PIPE_BUF | ||
| 96 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | ||
| 97 | #endif | ||
| 98 | |||
| 99 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 100 | # define is_absolute_path(path) ((path)[0] == '/') | ||
| 101 | #endif | ||
| 102 | |||
| 103 | #if !BB_MMU | ||
| 104 | # error "Do not even bother, ash will not run on NOMMU machine" | ||
| 105 | #endif | ||
| 106 | |||
| 107 | //config:config ASH | 33 | //config:config ASH |
| 108 | //config: bool "ash" | 34 | //config: bool "ash" |
| 109 | //config: default y | 35 | //config: default y |
| @@ -118,14 +44,14 @@ | |||
| 118 | //config:config ASH_OPTIMIZE_FOR_SIZE | 44 | //config:config ASH_OPTIMIZE_FOR_SIZE |
| 119 | //config: bool "Optimize for size instead of speed" | 45 | //config: bool "Optimize for size instead of speed" |
| 120 | //config: default y | 46 | //config: default y |
| 121 | //config: depends on ASH | 47 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 122 | //config: help | 48 | //config: help |
| 123 | //config: Compile ash for reduced size at the price of speed. | 49 | //config: Compile ash for reduced size at the price of speed. |
| 124 | //config: | 50 | //config: |
| 125 | //config:config ASH_INTERNAL_GLOB | 51 | //config:config ASH_INTERNAL_GLOB |
| 126 | //config: bool "Use internal glob() implementation" | 52 | //config: bool "Use internal glob() implementation" |
| 127 | //config: default n | 53 | //config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now |
| 128 | //config: depends on ASH | 54 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 129 | //config: help | 55 | //config: help |
| 130 | //config: Do not use glob() function from libc, use internal implementation. | 56 | //config: Do not use glob() function from libc, use internal implementation. |
| 131 | //config: Use this if you are getting "glob.h: No such file or directory" | 57 | //config: Use this if you are getting "glob.h: No such file or directory" |
| @@ -134,7 +60,7 @@ | |||
| 134 | //config:config ASH_RANDOM_SUPPORT | 60 | //config:config ASH_RANDOM_SUPPORT |
| 135 | //config: bool "Pseudorandom generator and $RANDOM variable" | 61 | //config: bool "Pseudorandom generator and $RANDOM variable" |
| 136 | //config: default y | 62 | //config: default y |
| 137 | //config: depends on ASH | 63 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 138 | //config: help | 64 | //config: help |
| 139 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". | 65 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". |
| 140 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. | 66 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. |
| @@ -145,7 +71,7 @@ | |||
| 145 | //config:config ASH_EXPAND_PRMT | 71 | //config:config ASH_EXPAND_PRMT |
| 146 | //config: bool "Expand prompt string" | 72 | //config: bool "Expand prompt string" |
| 147 | //config: default y | 73 | //config: default y |
| 148 | //config: depends on ASH | 74 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 149 | //config: help | 75 | //config: help |
| 150 | //config: "PS#" may contain volatile content, such as backquote commands. | 76 | //config: "PS#" may contain volatile content, such as backquote commands. |
| 151 | //config: This option recreates the prompt string from the environment | 77 | //config: This option recreates the prompt string from the environment |
| @@ -154,70 +80,70 @@ | |||
| 154 | //config:config ASH_BASH_COMPAT | 80 | //config:config ASH_BASH_COMPAT |
| 155 | //config: bool "bash-compatible extensions" | 81 | //config: bool "bash-compatible extensions" |
| 156 | //config: default y | 82 | //config: default y |
| 157 | //config: depends on ASH | 83 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 158 | //config: help | 84 | //config: help |
| 159 | //config: Enable bash-compatible extensions. | 85 | //config: Enable bash-compatible extensions. |
| 160 | //config: | 86 | //config: |
| 161 | //config:config ASH_IDLE_TIMEOUT | 87 | //config:config ASH_IDLE_TIMEOUT |
| 162 | //config: bool "Idle timeout variable" | 88 | //config: bool "Idle timeout variable" |
| 163 | //config: default n | 89 | //config: default n |
| 164 | //config: depends on ASH | 90 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 165 | //config: help | 91 | //config: help |
| 166 | //config: Enables bash-like auto-logout after $TMOUT seconds of idle time. | 92 | //config: Enables bash-like auto-logout after $TMOUT seconds of idle time. |
| 167 | //config: | 93 | //config: |
| 168 | //config:config ASH_JOB_CONTROL | 94 | //config:config ASH_JOB_CONTROL |
| 169 | //config: bool "Job control" | 95 | //config: bool "Job control" |
| 170 | //config: default y | 96 | //config: default y |
| 171 | //config: depends on ASH | 97 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 172 | //config: help | 98 | //config: help |
| 173 | //config: Enable job control in the ash shell. | 99 | //config: Enable job control in the ash shell. |
| 174 | //config: | 100 | //config: |
| 175 | //config:config ASH_ALIAS | 101 | //config:config ASH_ALIAS |
| 176 | //config: bool "Alias support" | 102 | //config: bool "Alias support" |
| 177 | //config: default y | 103 | //config: default y |
| 178 | //config: depends on ASH | 104 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 179 | //config: help | 105 | //config: help |
| 180 | //config: Enable alias support in the ash shell. | 106 | //config: Enable alias support in the ash shell. |
| 181 | //config: | 107 | //config: |
| 182 | //config:config ASH_GETOPTS | 108 | //config:config ASH_GETOPTS |
| 183 | //config: bool "Builtin getopt to parse positional parameters" | 109 | //config: bool "Builtin getopt to parse positional parameters" |
| 184 | //config: default y | 110 | //config: default y |
| 185 | //config: depends on ASH | 111 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 186 | //config: help | 112 | //config: help |
| 187 | //config: Enable support for getopts builtin in ash. | 113 | //config: Enable support for getopts builtin in ash. |
| 188 | //config: | 114 | //config: |
| 189 | //config:config ASH_BUILTIN_ECHO | 115 | //config:config ASH_BUILTIN_ECHO |
| 190 | //config: bool "Builtin version of 'echo'" | 116 | //config: bool "Builtin version of 'echo'" |
| 191 | //config: default y | 117 | //config: default y |
| 192 | //config: depends on ASH | 118 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 193 | //config: help | 119 | //config: help |
| 194 | //config: Enable support for echo builtin in ash. | 120 | //config: Enable support for echo builtin in ash. |
| 195 | //config: | 121 | //config: |
| 196 | //config:config ASH_BUILTIN_PRINTF | 122 | //config:config ASH_BUILTIN_PRINTF |
| 197 | //config: bool "Builtin version of 'printf'" | 123 | //config: bool "Builtin version of 'printf'" |
| 198 | //config: default y | 124 | //config: default y |
| 199 | //config: depends on ASH | 125 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 200 | //config: help | 126 | //config: help |
| 201 | //config: Enable support for printf builtin in ash. | 127 | //config: Enable support for printf builtin in ash. |
| 202 | //config: | 128 | //config: |
| 203 | //config:config ASH_BUILTIN_TEST | 129 | //config:config ASH_BUILTIN_TEST |
| 204 | //config: bool "Builtin version of 'test'" | 130 | //config: bool "Builtin version of 'test'" |
| 205 | //config: default y | 131 | //config: default y |
| 206 | //config: depends on ASH | 132 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 207 | //config: help | 133 | //config: help |
| 208 | //config: Enable support for test builtin in ash. | 134 | //config: Enable support for test builtin in ash. |
| 209 | //config: | 135 | //config: |
| 210 | //config:config ASH_HELP | 136 | //config:config ASH_HELP |
| 211 | //config: bool "help builtin" | 137 | //config: bool "help builtin" |
| 212 | //config: default y | 138 | //config: default y |
| 213 | //config: depends on ASH | 139 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 214 | //config: help | 140 | //config: help |
| 215 | //config: Enable help builtin in ash. | 141 | //config: Enable help builtin in ash. |
| 216 | //config: | 142 | //config: |
| 217 | //config:config ASH_CMDCMD | 143 | //config:config ASH_CMDCMD |
| 218 | //config: bool "'command' command to override shell builtins" | 144 | //config: bool "'command' command to override shell builtins" |
| 219 | //config: default y | 145 | //config: default y |
| 220 | //config: depends on ASH | 146 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 221 | //config: help | 147 | //config: help |
| 222 | //config: Enable support for the ash 'command' builtin, which allows | 148 | //config: Enable support for the ash 'command' builtin, which allows |
| 223 | //config: you to run the specified command with the specified arguments, | 149 | //config: you to run the specified command with the specified arguments, |
| @@ -225,19 +151,105 @@ | |||
| 225 | //config: | 151 | //config: |
| 226 | //config:config ASH_MAIL | 152 | //config:config ASH_MAIL |
| 227 | //config: bool "Check for new mail on interactive shells" | 153 | //config: bool "Check for new mail on interactive shells" |
| 228 | //config: default n | 154 | //config: default y |
| 229 | //config: depends on ASH | 155 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 230 | //config: help | 156 | //config: help |
| 231 | //config: Enable "check for new mail" function in the ash shell. | 157 | //config: Enable "check for new mail" function in the ash shell. |
| 232 | //config: | ||
| 233 | 158 | ||
| 234 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) | 159 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) |
| 235 | //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh)) | 160 | //applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) |
| 236 | //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash)) | 161 | //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) |
| 237 | 162 | ||
| 238 | //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o | 163 | //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o |
| 164 | //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o | ||
| 165 | //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o | ||
| 239 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o | 166 | //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o |
| 240 | 167 | ||
| 168 | /* | ||
| 169 | * The following should be set to reflect the type of system you have: | ||
| 170 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. | ||
| 171 | * define SYSV if you are running under System V. | ||
| 172 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) | ||
| 173 | * define DEBUG=2 to compile in and turn on debugging. | ||
| 174 | * | ||
| 175 | * When debugging is on (DEBUG is 1 and "set -o debug" was executed), | ||
| 176 | * debugging info will be written to ./trace and a quit signal | ||
| 177 | * will generate a core dump. | ||
| 178 | */ | ||
| 179 | #define DEBUG 0 | ||
| 180 | /* Tweak debug output verbosity here */ | ||
| 181 | #define DEBUG_TIME 0 | ||
| 182 | #define DEBUG_PID 1 | ||
| 183 | #define DEBUG_SIG 1 | ||
| 184 | #define DEBUG_INTONOFF 0 | ||
| 185 | |||
| 186 | #define PROFILE 0 | ||
| 187 | |||
| 188 | #define JOBS ENABLE_ASH_JOB_CONTROL | ||
| 189 | |||
| 190 | #include <setjmp.h> | ||
| 191 | #include <fnmatch.h> | ||
| 192 | #include <sys/times.h> | ||
| 193 | #include <sys/utsname.h> /* for setting $HOSTNAME */ | ||
| 194 | |||
| 195 | #include "busybox.h" /* for applet_names */ | ||
| 196 | |||
| 197 | #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 | ||
| 198 | /* Bionic at least up to version 24 has no glob() */ | ||
| 199 | # undef ENABLE_ASH_INTERNAL_GLOB | ||
| 200 | # define ENABLE_ASH_INTERNAL_GLOB 1 | ||
| 201 | #endif | ||
| 202 | |||
| 203 | #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__) | ||
| 204 | # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB. | ||
| 205 | # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD" | ||
| 206 | # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b" | ||
| 207 | # error glob() should unbackslash them and match. uClibc does not unbackslash, | ||
| 208 | # error fails to match dirname, subsequently not expanding <pattern> in it. | ||
| 209 | // Testcase: | ||
| 210 | // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug | ||
| 211 | // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n"); | ||
| 212 | #endif | ||
| 213 | |||
| 214 | #if !ENABLE_ASH_INTERNAL_GLOB | ||
| 215 | # include <glob.h> | ||
| 216 | #endif | ||
| 217 | |||
| 218 | #include "unicode.h" | ||
| 219 | #include "shell_common.h" | ||
| 220 | #if ENABLE_FEATURE_SH_MATH | ||
| 221 | # include "math.h" | ||
| 222 | #endif | ||
| 223 | #if ENABLE_ASH_RANDOM_SUPPORT | ||
| 224 | # include "random.h" | ||
| 225 | #else | ||
| 226 | # define CLEAR_RANDOM_T(rnd) ((void)0) | ||
| 227 | #endif | ||
| 228 | |||
| 229 | #include "NUM_APPLETS.h" | ||
| 230 | #if NUM_APPLETS == 1 | ||
| 231 | /* STANDALONE does not make sense, and won't compile */ | ||
| 232 | # undef CONFIG_FEATURE_SH_STANDALONE | ||
| 233 | # undef ENABLE_FEATURE_SH_STANDALONE | ||
| 234 | # undef IF_FEATURE_SH_STANDALONE | ||
| 235 | # undef IF_NOT_FEATURE_SH_STANDALONE | ||
| 236 | # define ENABLE_FEATURE_SH_STANDALONE 0 | ||
| 237 | # define IF_FEATURE_SH_STANDALONE(...) | ||
| 238 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ | ||
| 239 | #endif | ||
| 240 | |||
| 241 | #ifndef PIPE_BUF | ||
| 242 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | ||
| 243 | #endif | ||
| 244 | |||
| 245 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 246 | # define is_absolute_path(path) ((path)[0] == '/') | ||
| 247 | #endif | ||
| 248 | |||
| 249 | #if !BB_MMU | ||
| 250 | # error "Do not even bother, ash will not run on NOMMU machine" | ||
| 251 | #endif | ||
| 252 | |||
| 241 | #if ENABLE_PLATFORM_MINGW32 | 253 | #if ENABLE_PLATFORM_MINGW32 |
| 242 | union node; | 254 | union node; |
| 243 | struct strlist; | 255 | struct strlist; |
| @@ -1343,6 +1355,8 @@ ash_msg_and_raise_error(const char *msg, ...) | |||
| 1343 | { | 1355 | { |
| 1344 | va_list ap; | 1356 | va_list ap; |
| 1345 | 1357 | ||
| 1358 | exitstatus = 2; | ||
| 1359 | |||
| 1346 | va_start(ap, msg); | 1360 | va_start(ap, msg); |
| 1347 | ash_vmsg_and_raise(EXERROR, msg, ap); | 1361 | ash_vmsg_and_raise(EXERROR, msg, ap); |
| 1348 | /* NOTREACHED */ | 1362 | /* NOTREACHED */ |
| @@ -2205,6 +2219,7 @@ lookupvar(const char *name) | |||
| 2205 | return NULL; | 2219 | return NULL; |
| 2206 | } | 2220 | } |
| 2207 | 2221 | ||
| 2222 | #if ENABLE_UNICODE_SUPPORT | ||
| 2208 | static void | 2223 | static void |
| 2209 | reinit_unicode_for_ash(void) | 2224 | reinit_unicode_for_ash(void) |
| 2210 | { | 2225 | { |
| @@ -2221,6 +2236,9 @@ reinit_unicode_for_ash(void) | |||
| 2221 | reinit_unicode(s); | 2236 | reinit_unicode(s); |
| 2222 | } | 2237 | } |
| 2223 | } | 2238 | } |
| 2239 | #else | ||
| 2240 | # define reinit_unicode_for_ash() ((void)0) | ||
| 2241 | #endif | ||
| 2224 | 2242 | ||
| 2225 | /* | 2243 | /* |
| 2226 | * Search the environment of a builtin command. | 2244 | * Search the environment of a builtin command. |
| @@ -2924,7 +2942,7 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
| 2924 | 2942 | ||
| 2925 | #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE | 2943 | #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE |
| 2926 | 2944 | ||
| 2927 | #if ENABLE_SH_MATH_SUPPORT | 2945 | #if ENABLE_FEATURE_SH_MATH |
| 2928 | # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12)) | 2946 | # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12)) |
| 2929 | #else | 2947 | #else |
| 2930 | # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8)) | 2948 | # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8)) |
| @@ -3305,7 +3323,18 @@ static const uint8_t syntax_index_table[] ALIGN1 = { | |||
| 3305 | # endif | 3323 | # endif |
| 3306 | }; | 3324 | }; |
| 3307 | 3325 | ||
| 3326 | #if 1 | ||
| 3308 | # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf) | 3327 | # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf) |
| 3328 | #else /* debug version, caught one signed char bug */ | ||
| 3329 | # define SIT(c, syntax) \ | ||
| 3330 | ({ \ | ||
| 3331 | if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \ | ||
| 3332 | bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \ | ||
| 3333 | if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \ | ||
| 3334 | bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \ | ||
| 3335 | ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \ | ||
| 3336 | }) | ||
| 3337 | #endif | ||
| 3309 | 3338 | ||
| 3310 | #endif /* !USE_SIT_FUNCTION */ | 3339 | #endif /* !USE_SIT_FUNCTION */ |
| 3311 | 3340 | ||
| @@ -4765,7 +4794,7 @@ cmdputs(const char *s) | |||
| 4765 | case CTLBACKQ: | 4794 | case CTLBACKQ: |
| 4766 | str = "$(...)"; | 4795 | str = "$(...)"; |
| 4767 | goto dostr; | 4796 | goto dostr; |
| 4768 | #if ENABLE_SH_MATH_SUPPORT | 4797 | #if ENABLE_FEATURE_SH_MATH |
| 4769 | case CTLARI: | 4798 | case CTLARI: |
| 4770 | str = "$(("; | 4799 | str = "$(("; |
| 4771 | goto dostr; | 4800 | goto dostr; |
| @@ -5878,7 +5907,7 @@ redirectsafe(union node *redir, int flags) | |||
| 5878 | * We have to deal with backquotes, shell variables, and file metacharacters. | 5907 | * We have to deal with backquotes, shell variables, and file metacharacters. |
| 5879 | */ | 5908 | */ |
| 5880 | 5909 | ||
| 5881 | #if ENABLE_SH_MATH_SUPPORT | 5910 | #if ENABLE_FEATURE_SH_MATH |
| 5882 | static arith_t | 5911 | static arith_t |
| 5883 | ash_arith(const char *s) | 5912 | ash_arith(const char *s) |
| 5884 | { | 5913 | { |
| @@ -5966,7 +5995,7 @@ static struct arglist exparg; | |||
| 5966 | /* | 5995 | /* |
| 5967 | * Our own itoa(). | 5996 | * Our own itoa(). |
| 5968 | */ | 5997 | */ |
| 5969 | #if !ENABLE_SH_MATH_SUPPORT | 5998 | #if !ENABLE_FEATURE_SH_MATH |
| 5970 | /* cvtnum() is used even if math support is off (to prepare $? values and such) */ | 5999 | /* cvtnum() is used even if math support is off (to prepare $? values and such) */ |
| 5971 | typedef long arith_t; | 6000 | typedef long arith_t; |
| 5972 | # define ARITH_FMT "%ld" | 6001 | # define ARITH_FMT "%ld" |
| @@ -6220,14 +6249,15 @@ memtodest(const char *p, size_t len, int syntax, int quotes) | |||
| 6220 | do { | 6249 | do { |
| 6221 | unsigned char c = *p++; | 6250 | unsigned char c = *p++; |
| 6222 | if (c) { | 6251 | if (c) { |
| 6223 | int n = SIT(c, syntax); | 6252 | if (quotes & QUOTES_ESC) { |
| 6224 | if ((quotes & QUOTES_ESC) | 6253 | int n = SIT(c, syntax); |
| 6225 | && ((n == CCTL) | 6254 | if (n == CCTL |
| 6226 | || (((quotes & EXP_FULL) || syntax != BASESYNTAX) | 6255 | || (((quotes & EXP_FULL) || syntax != BASESYNTAX) |
| 6227 | && n == CBACK) | 6256 | && n == CBACK |
| 6228 | ) | 6257 | ) |
| 6229 | ) { | 6258 | ) { |
| 6230 | USTPUTC(CTLESC, q); | 6259 | USTPUTC(CTLESC, q); |
| 6260 | } | ||
| 6231 | } | 6261 | } |
| 6232 | } else if (!(quotes & QUOTES_KEEPNUL)) | 6262 | } else if (!(quotes & QUOTES_KEEPNUL)) |
| 6233 | continue; | 6263 | continue; |
| @@ -6490,7 +6520,7 @@ expbackq(union node *cmd, int flag) | |||
| 6490 | stackblock() + startloc)); | 6520 | stackblock() + startloc)); |
| 6491 | } | 6521 | } |
| 6492 | 6522 | ||
| 6493 | #if ENABLE_SH_MATH_SUPPORT | 6523 | #if ENABLE_FEATURE_SH_MATH |
| 6494 | /* | 6524 | /* |
| 6495 | * Expand arithmetic expression. Backup to start of expression, | 6525 | * Expand arithmetic expression. Backup to start of expression, |
| 6496 | * evaluate, place result in (backed up) result, adjust string position. | 6526 | * evaluate, place result in (backed up) result, adjust string position. |
| @@ -6572,7 +6602,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
| 6572 | CTLESC, | 6602 | CTLESC, |
| 6573 | CTLVAR, | 6603 | CTLVAR, |
| 6574 | CTLBACKQ, | 6604 | CTLBACKQ, |
| 6575 | #if ENABLE_SH_MATH_SUPPORT | 6605 | #if ENABLE_FEATURE_SH_MATH |
| 6576 | CTLENDARI, | 6606 | CTLENDARI, |
| 6577 | #endif | 6607 | #endif |
| 6578 | '\0' | 6608 | '\0' |
| @@ -6608,7 +6638,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
| 6608 | c = p[length]; | 6638 | c = p[length]; |
| 6609 | if (c) { | 6639 | if (c) { |
| 6610 | if (!(c & 0x80) | 6640 | if (!(c & 0x80) |
| 6611 | IF_SH_MATH_SUPPORT(|| c == CTLENDARI) | 6641 | IF_FEATURE_SH_MATH(|| c == CTLENDARI) |
| 6612 | ) { | 6642 | ) { |
| 6613 | /* c == '=' || c == ':' || c == CTLENDARI */ | 6643 | /* c == '=' || c == ':' || c == CTLENDARI */ |
| 6614 | length++; | 6644 | length++; |
| @@ -6688,7 +6718,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
| 6688 | expbackq(argbackq->n, flags | inquotes); | 6718 | expbackq(argbackq->n, flags | inquotes); |
| 6689 | argbackq = argbackq->next; | 6719 | argbackq = argbackq->next; |
| 6690 | goto start; | 6720 | goto start; |
| 6691 | #if ENABLE_SH_MATH_SUPPORT | 6721 | #if ENABLE_FEATURE_SH_MATH |
| 6692 | case CTLENDARI: | 6722 | case CTLENDARI: |
| 6693 | p--; | 6723 | p--; |
| 6694 | expari(flags | inquotes); | 6724 | expari(flags | inquotes); |
| @@ -9686,7 +9716,7 @@ static int helpcmd(int, char **) FAST_FUNC; | |||
| 9686 | #if MAX_HISTORY | 9716 | #if MAX_HISTORY |
| 9687 | static int historycmd(int, char **) FAST_FUNC; | 9717 | static int historycmd(int, char **) FAST_FUNC; |
| 9688 | #endif | 9718 | #endif |
| 9689 | #if ENABLE_SH_MATH_SUPPORT | 9719 | #if ENABLE_FEATURE_SH_MATH |
| 9690 | static int letcmd(int, char **) FAST_FUNC; | 9720 | static int letcmd(int, char **) FAST_FUNC; |
| 9691 | #endif | 9721 | #endif |
| 9692 | static int readcmd(int, char **) FAST_FUNC; | 9722 | static int readcmd(int, char **) FAST_FUNC; |
| @@ -9766,7 +9796,7 @@ static const struct builtincmd builtintab[] = { | |||
| 9766 | { BUILTIN_REGULAR "jobs" , jobscmd }, | 9796 | { BUILTIN_REGULAR "jobs" , jobscmd }, |
| 9767 | { BUILTIN_REGULAR "kill" , killcmd }, | 9797 | { BUILTIN_REGULAR "kill" , killcmd }, |
| 9768 | #endif | 9798 | #endif |
| 9769 | #if ENABLE_SH_MATH_SUPPORT | 9799 | #if ENABLE_FEATURE_SH_MATH |
| 9770 | { BUILTIN_NOSPEC "let" , letcmd }, | 9800 | { BUILTIN_NOSPEC "let" , letcmd }, |
| 9771 | #endif | 9801 | #endif |
| 9772 | { BUILTIN_ASSIGN "local" , localcmd }, | 9802 | { BUILTIN_ASSIGN "local" , localcmd }, |
| @@ -10004,11 +10034,13 @@ evalcommand(union node *cmd, int flags) | |||
| 10004 | } | 10034 | } |
| 10005 | 10035 | ||
| 10006 | if (status) { | 10036 | if (status) { |
| 10037 | bail: | ||
| 10038 | exitstatus = status; | ||
| 10039 | |||
| 10007 | /* We have a redirection error. */ | 10040 | /* We have a redirection error. */ |
| 10008 | if (spclbltin > 0) | 10041 | if (spclbltin > 0) |
| 10009 | raise_exception(EXERROR); | 10042 | raise_exception(EXERROR); |
| 10010 | bail: | 10043 | |
| 10011 | exitstatus = status; | ||
| 10012 | goto out; | 10044 | goto out; |
| 10013 | } | 10045 | } |
| 10014 | 10046 | ||
| @@ -10516,7 +10548,7 @@ pgetc(void) | |||
| 10516 | return g_parsefile->lastc[--g_parsefile->unget]; | 10548 | return g_parsefile->lastc[--g_parsefile->unget]; |
| 10517 | 10549 | ||
| 10518 | if (--g_parsefile->left_in_line >= 0) | 10550 | if (--g_parsefile->left_in_line >= 0) |
| 10519 | c = (signed char)*g_parsefile->next_to_pgetc++; | 10551 | c = (unsigned char)*g_parsefile->next_to_pgetc++; |
| 10520 | else | 10552 | else |
| 10521 | c = preadbuffer(); | 10553 | c = preadbuffer(); |
| 10522 | 10554 | ||
| @@ -11840,13 +11872,13 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
| 11840 | smallint quotef; | 11872 | smallint quotef; |
| 11841 | smallint dblquote; | 11873 | smallint dblquote; |
| 11842 | smallint oldstyle; | 11874 | smallint oldstyle; |
| 11843 | smallint prevsyntax; /* syntax before arithmetic */ | 11875 | IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */ |
| 11844 | #if ENABLE_ASH_EXPAND_PRMT | 11876 | #if ENABLE_ASH_EXPAND_PRMT |
| 11845 | smallint pssyntax; /* we are expanding a prompt string */ | 11877 | smallint pssyntax; /* we are expanding a prompt string */ |
| 11846 | #endif | 11878 | #endif |
| 11847 | int varnest; /* levels of variables expansion */ | 11879 | int varnest; /* levels of variables expansion */ |
| 11848 | int arinest; /* levels of arithmetic expansion */ | 11880 | IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ |
| 11849 | int parenlevel; /* levels of parens in arithmetic */ | 11881 | IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ |
| 11850 | int dqvarnest; /* levels of variables expansion within double quotes */ | 11882 | int dqvarnest; /* levels of variables expansion within double quotes */ |
| 11851 | 11883 | ||
| 11852 | IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) | 11884 | IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) |
| @@ -11854,7 +11886,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
| 11854 | startlinno = g_parsefile->linno; | 11886 | startlinno = g_parsefile->linno; |
| 11855 | bqlist = NULL; | 11887 | bqlist = NULL; |
| 11856 | quotef = 0; | 11888 | quotef = 0; |
| 11857 | prevsyntax = 0; | 11889 | IF_FEATURE_SH_MATH(prevsyntax = 0;) |
| 11858 | #if ENABLE_ASH_EXPAND_PRMT | 11890 | #if ENABLE_ASH_EXPAND_PRMT |
| 11859 | pssyntax = (syntax == PSSYNTAX); | 11891 | pssyntax = (syntax == PSSYNTAX); |
| 11860 | if (pssyntax) | 11892 | if (pssyntax) |
| @@ -11862,8 +11894,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
| 11862 | #endif | 11894 | #endif |
| 11863 | dblquote = (syntax == DQSYNTAX); | 11895 | dblquote = (syntax == DQSYNTAX); |
| 11864 | varnest = 0; | 11896 | varnest = 0; |
| 11865 | arinest = 0; | 11897 | IF_FEATURE_SH_MATH(arinest = 0;) |
| 11866 | parenlevel = 0; | 11898 | IF_FEATURE_SH_MATH(parenlevel = 0;) |
| 11867 | dqvarnest = 0; | 11899 | dqvarnest = 0; |
| 11868 | 11900 | ||
| 11869 | STARTSTACKSTR(out); | 11901 | STARTSTACKSTR(out); |
| @@ -11970,7 +12002,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
| 11970 | } | 12002 | } |
| 11971 | USTPUTC(c, out); | 12003 | USTPUTC(c, out); |
| 11972 | break; | 12004 | break; |
| 11973 | #if ENABLE_SH_MATH_SUPPORT | 12005 | #if ENABLE_FEATURE_SH_MATH |
| 11974 | case CLP: /* '(' in arithmetic */ | 12006 | case CLP: /* '(' in arithmetic */ |
| 11975 | parenlevel++; | 12007 | parenlevel++; |
| 11976 | USTPUTC(c, out); | 12008 | USTPUTC(c, out); |
| @@ -12021,7 +12053,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
| 12021 | } /* for (;;) */ | 12053 | } /* for (;;) */ |
| 12022 | endword: | 12054 | endword: |
| 12023 | 12055 | ||
| 12024 | #if ENABLE_SH_MATH_SUPPORT | 12056 | #if ENABLE_FEATURE_SH_MATH |
| 12025 | if (syntax == ARISYNTAX) | 12057 | if (syntax == ARISYNTAX) |
| 12026 | raise_error_syntax("missing '))'"); | 12058 | raise_error_syntax("missing '))'"); |
| 12027 | #endif | 12059 | #endif |
| @@ -12200,7 +12232,7 @@ parsesub: { | |||
| 12200 | } else if (c == '(') { | 12232 | } else if (c == '(') { |
| 12201 | /* $(command) or $((arith)) */ | 12233 | /* $(command) or $((arith)) */ |
| 12202 | if (pgetc_eatbnl() == '(') { | 12234 | if (pgetc_eatbnl() == '(') { |
| 12203 | #if ENABLE_SH_MATH_SUPPORT | 12235 | #if ENABLE_FEATURE_SH_MATH |
| 12204 | PARSEARITH(); | 12236 | PARSEARITH(); |
| 12205 | #else | 12237 | #else |
| 12206 | raise_error_syntax("you disabled math support for $((arith)) syntax"); | 12238 | raise_error_syntax("you disabled math support for $((arith)) syntax"); |
| @@ -12455,7 +12487,7 @@ parsebackq: { | |||
| 12455 | goto parsebackq_newreturn; | 12487 | goto parsebackq_newreturn; |
| 12456 | } | 12488 | } |
| 12457 | 12489 | ||
| 12458 | #if ENABLE_SH_MATH_SUPPORT | 12490 | #if ENABLE_FEATURE_SH_MATH |
| 12459 | /* | 12491 | /* |
| 12460 | * Parse an arithmetic expansion (indicate start of one and set state) | 12492 | * Parse an arithmetic expansion (indicate start of one and set state) |
| 12461 | */ | 12493 | */ |
| @@ -13532,7 +13564,7 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
| 13532 | return 0; | 13564 | return 0; |
| 13533 | } | 13565 | } |
| 13534 | 13566 | ||
| 13535 | #if ENABLE_SH_MATH_SUPPORT | 13567 | #if ENABLE_FEATURE_SH_MATH |
| 13536 | /* | 13568 | /* |
| 13537 | * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell. | 13569 | * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell. |
| 13538 | * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. | 13570 | * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. |
| @@ -13871,15 +13903,6 @@ init(void) | |||
| 13871 | //usage:#define ash_full_usage "\n\n" | 13903 | //usage:#define ash_full_usage "\n\n" |
| 13872 | //usage: "Unix shell interpreter" | 13904 | //usage: "Unix shell interpreter" |
| 13873 | 13905 | ||
| 13874 | //usage:#if ENABLE_FEATURE_SH_IS_ASH | ||
| 13875 | //usage:# define sh_trivial_usage ash_trivial_usage | ||
| 13876 | //usage:# define sh_full_usage ash_full_usage | ||
| 13877 | //usage:#endif | ||
| 13878 | //usage:#if ENABLE_FEATURE_BASH_IS_ASH | ||
| 13879 | //usage:# define bash_trivial_usage ash_trivial_usage | ||
| 13880 | //usage:# define bash_full_usage ash_full_usage | ||
| 13881 | //usage:#endif | ||
| 13882 | |||
| 13883 | /* | 13906 | /* |
| 13884 | * Process the shell command line arguments. | 13907 | * Process the shell command line arguments. |
| 13885 | */ | 13908 | */ |
diff --git a/shell/ash_test/ash-misc/exitcode2.right b/shell/ash_test/ash-misc/exitcode2.right new file mode 100644 index 000000000..f7cb983c6 --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode2.right | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | ./test.sh: line 1: syntax error: unexpected ")" | ||
| 2 | Done:2 | ||
| 3 | ./exitcode2.tests: line 11: can't open does_not_exist: no such file | ||
| 4 | Done:1 | ||
diff --git a/shell/ash_test/ash-misc/exitcode2.tests b/shell/ash_test/ash-misc/exitcode2.tests new file mode 100755 index 000000000..79a6ebd50 --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode2.tests | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # syntax error should return status 2 | ||
| 2 | cat >test.sh <<EOF | ||
| 3 | ) | ||
| 4 | EOF | ||
| 5 | chmod +x test.sh | ||
| 6 | $THIS_SH ./test.sh | ||
| 7 | echo Done:$? | ||
| 8 | rm -f test.sh | ||
| 9 | |||
| 10 | # redirection error with special builtin should return status 1 | ||
| 11 | (eval cat <does_not_exist) | ||
| 12 | echo Done:$? | ||
diff --git a/shell/hush.c b/shell/hush.c index bcd4dffee..a56d3b280 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -82,35 +82,6 @@ | |||
| 82 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" | 82 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" |
| 83 | * aaa | 83 | * aaa |
| 84 | */ | 84 | */ |
| 85 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | ||
| 86 | || defined(__APPLE__) \ | ||
| 87 | ) | ||
| 88 | # include <malloc.h> /* for malloc_trim */ | ||
| 89 | #endif | ||
| 90 | #include <glob.h> | ||
| 91 | /* #include <dmalloc.h> */ | ||
| 92 | #if ENABLE_HUSH_CASE | ||
| 93 | # include <fnmatch.h> | ||
| 94 | #endif | ||
| 95 | #include <sys/utsname.h> /* for setting $HOSTNAME */ | ||
| 96 | |||
| 97 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | ||
| 98 | #include "unicode.h" | ||
| 99 | #include "shell_common.h" | ||
| 100 | #include "math.h" | ||
| 101 | #include "match.h" | ||
| 102 | #if ENABLE_HUSH_RANDOM_SUPPORT | ||
| 103 | # include "random.h" | ||
| 104 | #else | ||
| 105 | # define CLEAR_RANDOM_T(rnd) ((void)0) | ||
| 106 | #endif | ||
| 107 | #ifndef F_DUPFD_CLOEXEC | ||
| 108 | # define F_DUPFD_CLOEXEC F_DUPFD | ||
| 109 | #endif | ||
| 110 | #ifndef PIPE_BUF | ||
| 111 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | ||
| 112 | #endif | ||
| 113 | |||
| 114 | //config:config HUSH | 85 | //config:config HUSH |
| 115 | //config: bool "hush" | 86 | //config: bool "hush" |
| 116 | //config: default y | 87 | //config: default y |
| @@ -128,7 +99,7 @@ | |||
| 128 | //config:config HUSH_BASH_COMPAT | 99 | //config:config HUSH_BASH_COMPAT |
| 129 | //config: bool "bash-compatible extensions" | 100 | //config: bool "bash-compatible extensions" |
| 130 | //config: default y | 101 | //config: default y |
| 131 | //config: depends on HUSH | 102 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 132 | //config: help | 103 | //config: help |
| 133 | //config: Enable bash-compatible extensions. | 104 | //config: Enable bash-compatible extensions. |
| 134 | //config: | 105 | //config: |
| @@ -142,14 +113,14 @@ | |||
| 142 | //config:config HUSH_HELP | 113 | //config:config HUSH_HELP |
| 143 | //config: bool "help builtin" | 114 | //config: bool "help builtin" |
| 144 | //config: default y | 115 | //config: default y |
| 145 | //config: depends on HUSH | 116 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 146 | //config: help | 117 | //config: help |
| 147 | //config: Enable help builtin in hush. Code size + ~1 kbyte. | 118 | //config: Enable help builtin in hush. Code size + ~1 kbyte. |
| 148 | //config: | 119 | //config: |
| 149 | //config:config HUSH_INTERACTIVE | 120 | //config:config HUSH_INTERACTIVE |
| 150 | //config: bool "Interactive mode" | 121 | //config: bool "Interactive mode" |
| 151 | //config: default y | 122 | //config: default y |
| 152 | //config: depends on HUSH | 123 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 153 | //config: help | 124 | //config: help |
| 154 | //config: Enable interactive mode (prompt and command editing). | 125 | //config: Enable interactive mode (prompt and command editing). |
| 155 | //config: Without this, hush simply reads and executes commands | 126 | //config: Without this, hush simply reads and executes commands |
| @@ -177,35 +148,35 @@ | |||
| 177 | //config:config HUSH_TICK | 148 | //config:config HUSH_TICK |
| 178 | //config: bool "Process substitution" | 149 | //config: bool "Process substitution" |
| 179 | //config: default y | 150 | //config: default y |
| 180 | //config: depends on HUSH | 151 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 181 | //config: help | 152 | //config: help |
| 182 | //config: Enable process substitution `command` and $(command) in hush. | 153 | //config: Enable process substitution `command` and $(command) in hush. |
| 183 | //config: | 154 | //config: |
| 184 | //config:config HUSH_IF | 155 | //config:config HUSH_IF |
| 185 | //config: bool "Support if/then/elif/else/fi" | 156 | //config: bool "Support if/then/elif/else/fi" |
| 186 | //config: default y | 157 | //config: default y |
| 187 | //config: depends on HUSH | 158 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 188 | //config: help | 159 | //config: help |
| 189 | //config: Enable if/then/elif/else/fi in hush. | 160 | //config: Enable if/then/elif/else/fi in hush. |
| 190 | //config: | 161 | //config: |
| 191 | //config:config HUSH_LOOPS | 162 | //config:config HUSH_LOOPS |
| 192 | //config: bool "Support for, while and until loops" | 163 | //config: bool "Support for, while and until loops" |
| 193 | //config: default y | 164 | //config: default y |
| 194 | //config: depends on HUSH | 165 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 195 | //config: help | 166 | //config: help |
| 196 | //config: Enable for, while and until loops in hush. | 167 | //config: Enable for, while and until loops in hush. |
| 197 | //config: | 168 | //config: |
| 198 | //config:config HUSH_CASE | 169 | //config:config HUSH_CASE |
| 199 | //config: bool "Support case ... esac statement" | 170 | //config: bool "Support case ... esac statement" |
| 200 | //config: default y | 171 | //config: default y |
| 201 | //config: depends on HUSH | 172 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 202 | //config: help | 173 | //config: help |
| 203 | //config: Enable case ... esac statement in hush. +400 bytes. | 174 | //config: Enable case ... esac statement in hush. +400 bytes. |
| 204 | //config: | 175 | //config: |
| 205 | //config:config HUSH_FUNCTIONS | 176 | //config:config HUSH_FUNCTIONS |
| 206 | //config: bool "Support funcname() { commands; } syntax" | 177 | //config: bool "Support funcname() { commands; } syntax" |
| 207 | //config: default y | 178 | //config: default y |
| 208 | //config: depends on HUSH | 179 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 209 | //config: help | 180 | //config: help |
| 210 | //config: Enable support for shell functions in hush. +800 bytes. | 181 | //config: Enable support for shell functions in hush. +800 bytes. |
| 211 | //config: | 182 | //config: |
| @@ -219,7 +190,7 @@ | |||
| 219 | //config:config HUSH_RANDOM_SUPPORT | 190 | //config:config HUSH_RANDOM_SUPPORT |
| 220 | //config: bool "Pseudorandom generator and $RANDOM variable" | 191 | //config: bool "Pseudorandom generator and $RANDOM variable" |
| 221 | //config: default y | 192 | //config: default y |
| 222 | //config: depends on HUSH | 193 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 223 | //config: help | 194 | //config: help |
| 224 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". | 195 | //config: Enable pseudorandom generator and dynamic variable "$RANDOM". |
| 225 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. | 196 | //config: Each read of "$RANDOM" will generate a new pseudorandom value. |
| @@ -227,14 +198,14 @@ | |||
| 227 | //config:config HUSH_EXPORT_N | 198 | //config:config HUSH_EXPORT_N |
| 228 | //config: bool "Support 'export -n' option" | 199 | //config: bool "Support 'export -n' option" |
| 229 | //config: default y | 200 | //config: default y |
| 230 | //config: depends on HUSH | 201 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 231 | //config: help | 202 | //config: help |
| 232 | //config: export -n unexports variables. It is a bash extension. | 203 | //config: export -n unexports variables. It is a bash extension. |
| 233 | //config: | 204 | //config: |
| 234 | //config:config HUSH_MODE_X | 205 | //config:config HUSH_MODE_X |
| 235 | //config: bool "Support 'hush -x' option and 'set -x' command" | 206 | //config: bool "Support 'hush -x' option and 'set -x' command" |
| 236 | //config: default y | 207 | //config: default y |
| 237 | //config: depends on HUSH | 208 | //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH |
| 238 | //config: help | 209 | //config: help |
| 239 | //config: This instructs hush to print commands before execution. | 210 | //config: This instructs hush to print commands before execution. |
| 240 | //config: Adds ~300 bytes. | 211 | //config: Adds ~300 bytes. |
| @@ -245,14 +216,15 @@ | |||
| 245 | //config: select HUSH | 216 | //config: select HUSH |
| 246 | //config: help | 217 | //config: help |
| 247 | //config: msh is deprecated and will be removed, please migrate to hush. | 218 | //config: msh is deprecated and will be removed, please migrate to hush. |
| 248 | //config: | ||
| 249 | 219 | ||
| 250 | //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) | 220 | //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) |
| 251 | //applet:IF_MSH(APPLET(msh, BB_DIR_BIN, BB_SUID_DROP)) | 221 | //applet:IF_MSH(APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) |
| 252 | //applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, sh)) | 222 | //applet:IF_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) |
| 253 | //applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, bash)) | 223 | //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) |
| 254 | 224 | ||
| 255 | //kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o | 225 | //kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o |
| 226 | //kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o | ||
| 227 | //kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o | ||
| 256 | //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o | 228 | //kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o |
| 257 | 229 | ||
| 258 | /* -i (interactive) and -s (read stdin) are also accepted, | 230 | /* -i (interactive) and -s (read stdin) are also accepted, |
| @@ -265,17 +237,34 @@ | |||
| 265 | //usage:#define hush_full_usage "\n\n" | 237 | //usage:#define hush_full_usage "\n\n" |
| 266 | //usage: "Unix shell interpreter" | 238 | //usage: "Unix shell interpreter" |
| 267 | 239 | ||
| 268 | //usage:#define msh_trivial_usage hush_trivial_usage | 240 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
| 269 | //usage:#define msh_full_usage hush_full_usage | 241 | || defined(__APPLE__) \ |
| 242 | ) | ||
| 243 | # include <malloc.h> /* for malloc_trim */ | ||
| 244 | #endif | ||
| 245 | #include <glob.h> | ||
| 246 | /* #include <dmalloc.h> */ | ||
| 247 | #if ENABLE_HUSH_CASE | ||
| 248 | # include <fnmatch.h> | ||
| 249 | #endif | ||
| 250 | #include <sys/utsname.h> /* for setting $HOSTNAME */ | ||
| 270 | 251 | ||
| 271 | //usage:#if ENABLE_FEATURE_SH_IS_HUSH | 252 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
| 272 | //usage:# define sh_trivial_usage hush_trivial_usage | 253 | #include "unicode.h" |
| 273 | //usage:# define sh_full_usage hush_full_usage | 254 | #include "shell_common.h" |
| 274 | //usage:#endif | 255 | #include "math.h" |
| 275 | //usage:#if ENABLE_FEATURE_BASH_IS_HUSH | 256 | #include "match.h" |
| 276 | //usage:# define bash_trivial_usage hush_trivial_usage | 257 | #if ENABLE_HUSH_RANDOM_SUPPORT |
| 277 | //usage:# define bash_full_usage hush_full_usage | 258 | # include "random.h" |
| 278 | //usage:#endif | 259 | #else |
| 260 | # define CLEAR_RANDOM_T(rnd) ((void)0) | ||
| 261 | #endif | ||
| 262 | #ifndef F_DUPFD_CLOEXEC | ||
| 263 | # define F_DUPFD_CLOEXEC F_DUPFD | ||
| 264 | #endif | ||
| 265 | #ifndef PIPE_BUF | ||
| 266 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | ||
| 267 | #endif | ||
| 279 | 268 | ||
| 280 | 269 | ||
| 281 | /* Build knobs */ | 270 | /* Build knobs */ |
| @@ -1148,6 +1137,9 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) | |||
| 1148 | char msg[2]; | 1137 | char msg[2]; |
| 1149 | msg[0] = ch; | 1138 | msg[0] = ch; |
| 1150 | msg[1] = '\0'; | 1139 | msg[1] = '\0'; |
| 1140 | #if HUSH_DEBUG >= 2 | ||
| 1141 | bb_error_msg("hush.c:%u", lineno); | ||
| 1142 | #endif | ||
| 1151 | bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); | 1143 | bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); |
| 1152 | } | 1144 | } |
| 1153 | 1145 | ||
| @@ -1574,9 +1566,8 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler) | |||
| 1574 | } | 1566 | } |
| 1575 | 1567 | ||
| 1576 | static void hush_exit(int exitcode) NORETURN; | 1568 | static void hush_exit(int exitcode) NORETURN; |
| 1577 | static void fflush_and__exit(void) NORETURN; | ||
| 1578 | static void restore_ttypgrp_and__exit(void) NORETURN; | ||
| 1579 | 1569 | ||
| 1570 | static void restore_ttypgrp_and__exit(void) NORETURN; | ||
| 1580 | static void restore_ttypgrp_and__exit(void) | 1571 | static void restore_ttypgrp_and__exit(void) |
| 1581 | { | 1572 | { |
| 1582 | /* xfunc has failed! die die die */ | 1573 | /* xfunc has failed! die die die */ |
| @@ -1585,6 +1576,8 @@ static void restore_ttypgrp_and__exit(void) | |||
| 1585 | hush_exit(xfunc_error_retval); | 1576 | hush_exit(xfunc_error_retval); |
| 1586 | } | 1577 | } |
| 1587 | 1578 | ||
| 1579 | #if ENABLE_HUSH_JOB | ||
| 1580 | |||
| 1588 | /* Needed only on some libc: | 1581 | /* Needed only on some libc: |
| 1589 | * It was observed that on exit(), fgetc'ed buffered data | 1582 | * It was observed that on exit(), fgetc'ed buffered data |
| 1590 | * gets "unwound" via lseek(fd, -NUM, SEEK_CUR). | 1583 | * gets "unwound" via lseek(fd, -NUM, SEEK_CUR). |
| @@ -1598,14 +1591,13 @@ static void restore_ttypgrp_and__exit(void) | |||
| 1598 | * and in `cmd` handling. | 1591 | * and in `cmd` handling. |
| 1599 | * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit(): | 1592 | * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit(): |
| 1600 | */ | 1593 | */ |
| 1594 | static void fflush_and__exit(void) NORETURN; | ||
| 1601 | static void fflush_and__exit(void) | 1595 | static void fflush_and__exit(void) |
| 1602 | { | 1596 | { |
| 1603 | fflush_all(); | 1597 | fflush_all(); |
| 1604 | _exit(xfunc_error_retval); | 1598 | _exit(xfunc_error_retval); |
| 1605 | } | 1599 | } |
| 1606 | 1600 | ||
| 1607 | #if ENABLE_HUSH_JOB | ||
| 1608 | |||
| 1609 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ | 1601 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ |
| 1610 | # define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit) | 1602 | # define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit) |
| 1611 | /* After [v]fork, in parent: restore tty pgrp on xfunc death */ | 1603 | /* After [v]fork, in parent: restore tty pgrp on xfunc death */ |
| @@ -4011,7 +4003,7 @@ static int i_peek_and_eat_bkslash_nl(struct in_str *input) | |||
| 4011 | } | 4003 | } |
| 4012 | } | 4004 | } |
| 4013 | 4005 | ||
| 4014 | #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS | 4006 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS |
| 4015 | /* Subroutines for copying $(...) and `...` things */ | 4007 | /* Subroutines for copying $(...) and `...` things */ |
| 4016 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); | 4008 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); |
| 4017 | /* '...' */ | 4009 | /* '...' */ |
| @@ -4179,7 +4171,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
| 4179 | } | 4171 | } |
| 4180 | return ch; | 4172 | return ch; |
| 4181 | } | 4173 | } |
| 4182 | #endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS */ | 4174 | #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */ |
| 4183 | 4175 | ||
| 4184 | /* Return code: 0 for OK, 1 for syntax error */ | 4176 | /* Return code: 0 for OK, 1 for syntax error */ |
| 4185 | #if BB_MMU | 4177 | #if BB_MMU |
| @@ -4333,13 +4325,13 @@ static int parse_dollar(o_string *as_string, | |||
| 4333 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4325 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
| 4334 | break; | 4326 | break; |
| 4335 | } | 4327 | } |
| 4336 | #if ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_TICK | 4328 | #if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK |
| 4337 | case '(': { | 4329 | case '(': { |
| 4338 | unsigned pos; | 4330 | unsigned pos; |
| 4339 | 4331 | ||
| 4340 | ch = i_getch(input); | 4332 | ch = i_getch(input); |
| 4341 | nommu_addchr(as_string, ch); | 4333 | nommu_addchr(as_string, ch); |
| 4342 | # if ENABLE_SH_MATH_SUPPORT | 4334 | # if ENABLE_FEATURE_SH_MATH |
| 4343 | if (i_peek_and_eat_bkslash_nl(input) == '(') { | 4335 | if (i_peek_and_eat_bkslash_nl(input) == '(') { |
| 4344 | ch = i_getch(input); | 4336 | ch = i_getch(input); |
| 4345 | nommu_addchr(as_string, ch); | 4337 | nommu_addchr(as_string, ch); |
| @@ -5008,7 +5000,8 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5008 | * if we see {, we call parse_group(..., end_trigger='}') | 5000 | * if we see {, we call parse_group(..., end_trigger='}') |
| 5009 | * and it will match } earlier (not here). */ | 5001 | * and it will match } earlier (not here). */ |
| 5010 | syntax_error_unexpected_ch(ch); | 5002 | syntax_error_unexpected_ch(ch); |
| 5011 | goto parse_error; | 5003 | G.last_exitcode = 2; |
| 5004 | goto parse_error1; | ||
| 5012 | default: | 5005 | default: |
| 5013 | if (HUSH_DEBUG) | 5006 | if (HUSH_DEBUG) |
| 5014 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); | 5007 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); |
| @@ -5016,6 +5009,8 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5016 | } /* while (1) */ | 5009 | } /* while (1) */ |
| 5017 | 5010 | ||
| 5018 | parse_error: | 5011 | parse_error: |
| 5012 | G.last_exitcode = 1; | ||
| 5013 | parse_error1: | ||
| 5019 | { | 5014 | { |
| 5020 | struct parse_context *pctx; | 5015 | struct parse_context *pctx; |
| 5021 | IF_HAS_KEYWORDS(struct parse_context *p2;) | 5016 | IF_HAS_KEYWORDS(struct parse_context *p2;) |
| @@ -5049,7 +5044,6 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5049 | } while (HAS_KEYWORDS && pctx); | 5044 | } while (HAS_KEYWORDS && pctx); |
| 5050 | 5045 | ||
| 5051 | o_free(&dest); | 5046 | o_free(&dest); |
| 5052 | G.last_exitcode = 1; | ||
| 5053 | #if !BB_MMU | 5047 | #if !BB_MMU |
| 5054 | if (pstring) | 5048 | if (pstring) |
| 5055 | *pstring = NULL; | 5049 | *pstring = NULL; |
| @@ -5217,7 +5211,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int | |||
| 5217 | return exp_str; | 5211 | return exp_str; |
| 5218 | } | 5212 | } |
| 5219 | 5213 | ||
| 5220 | #if ENABLE_SH_MATH_SUPPORT | 5214 | #if ENABLE_FEATURE_SH_MATH |
| 5221 | static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | 5215 | static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) |
| 5222 | { | 5216 | { |
| 5223 | arith_state_t math_state; | 5217 | arith_state_t math_state; |
| @@ -5469,7 +5463,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
| 5469 | } | 5463 | } |
| 5470 | #endif | 5464 | #endif |
| 5471 | else if (exp_op == ':') { | 5465 | else if (exp_op == ':') { |
| 5472 | #if ENABLE_HUSH_BASH_COMPAT && ENABLE_SH_MATH_SUPPORT | 5466 | #if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH |
| 5473 | /* It's ${var:N[:M]} bashism. | 5467 | /* It's ${var:N[:M]} bashism. |
| 5474 | * Note that in encoded form it has TWO parts: | 5468 | * Note that in encoded form it has TWO parts: |
| 5475 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> | 5469 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> |
| @@ -5604,7 +5598,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
| 5604 | #if ENABLE_HUSH_TICK | 5598 | #if ENABLE_HUSH_TICK |
| 5605 | o_string subst_result = NULL_O_STRING; | 5599 | o_string subst_result = NULL_O_STRING; |
| 5606 | #endif | 5600 | #endif |
| 5607 | #if ENABLE_SH_MATH_SUPPORT | 5601 | #if ENABLE_FEATURE_SH_MATH |
| 5608 | char arith_buf[sizeof(arith_t)*3 + 2]; | 5602 | char arith_buf[sizeof(arith_t)*3 + 2]; |
| 5609 | #endif | 5603 | #endif |
| 5610 | 5604 | ||
| @@ -5698,7 +5692,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
| 5698 | val = subst_result.data; | 5692 | val = subst_result.data; |
| 5699 | goto store_val; | 5693 | goto store_val; |
| 5700 | #endif | 5694 | #endif |
| 5701 | #if ENABLE_SH_MATH_SUPPORT | 5695 | #if ENABLE_FEATURE_SH_MATH |
| 5702 | case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ | 5696 | case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ |
| 5703 | arith_t res; | 5697 | arith_t res; |
| 5704 | 5698 | ||
diff --git a/shell/hush_test/hush-misc/exitcode2.right b/shell/hush_test/hush-misc/exitcode2.right new file mode 100644 index 000000000..0a57b9b1b --- /dev/null +++ b/shell/hush_test/hush-misc/exitcode2.right | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | hush: syntax error: unexpected ) | ||
| 2 | Done:2 | ||
| 3 | hush: can't open 'does_not_exist': No such file or directory | ||
| 4 | Done:1 | ||
diff --git a/shell/hush_test/hush-misc/exitcode2.tests b/shell/hush_test/hush-misc/exitcode2.tests new file mode 100755 index 000000000..79a6ebd50 --- /dev/null +++ b/shell/hush_test/hush-misc/exitcode2.tests | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # syntax error should return status 2 | ||
| 2 | cat >test.sh <<EOF | ||
| 3 | ) | ||
| 4 | EOF | ||
| 5 | chmod +x test.sh | ||
| 6 | $THIS_SH ./test.sh | ||
| 7 | echo Done:$? | ||
| 8 | rm -f test.sh | ||
| 9 | |||
| 10 | # redirection error with special builtin should return status 1 | ||
| 11 | (eval cat <does_not_exist) | ||
| 12 | echo Done:$? | ||
diff --git a/shell/math.h b/shell/math.h index 864bee691..32e1ffe35 100644 --- a/shell/math.h +++ b/shell/math.h | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | 63 | ||
| 64 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 64 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
| 65 | 65 | ||
| 66 | #if ENABLE_SH_MATH_SUPPORT_64 | 66 | #if ENABLE_FEATURE_SH_MATH_64 |
| 67 | typedef long long arith_t; | 67 | typedef long long arith_t; |
| 68 | #define ARITH_FMT "%lld" | 68 | #define ARITH_FMT "%lld" |
| 69 | #define strto_arith_t strtoull | 69 | #define strto_arith_t strtoull |
