diff options
author | Ron Yorston <rmy@pobox.com> | 2021-03-24 11:55:30 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-03-24 12:43:15 +0000 |
commit | 355a7a6c1e9626b7afe8758a6095f3cf275c52e1 (patch) | |
tree | 6dab679c15b049cab97212e0b43077132eec1fbe /shell | |
parent | 71ecc8033e6989996057b32577e71148fd544596 (diff) | |
parent | 889425812b5cda8b3394d73253cbde7355fb1115 (diff) | |
download | busybox-w32-w32_1_26_2.tar.gz busybox-w32-w32_1_26_2.tar.bz2 busybox-w32-w32_1_26_2.zip |
Merge tag '1_26_2' into w32_1_26_2w32_1_26_2
Diffstat (limited to 'shell')
-rw-r--r-- | shell/Config.src | 45 | ||||
-rw-r--r-- | shell/Kbuild.src | 2 | ||||
-rw-r--r-- | shell/ash.c | 304 | ||||
-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/ash_test/ash-redir/redir_leak.right | 6 | ||||
-rwxr-xr-x | shell/ash_test/ash-redir/redir_leak.tests | 10 | ||||
-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/hush_test/hush-redir/redir_leak.right | 6 | ||||
-rwxr-xr-x | shell/hush_test/hush-redir/redir_leak.tests | 10 | ||||
-rw-r--r-- | shell/math.h | 2 |
13 files changed, 314 insertions, 233 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..af1157709 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 CONFIG_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; |
@@ -5749,11 +5778,11 @@ redirect(union node *redir, int flags) | |||
5749 | /* Careful to not accidentally "save" | 5778 | /* Careful to not accidentally "save" |
5750 | * to the same fd as right side fd in N>&M */ | 5779 | * to the same fd as right side fd in N>&M */ |
5751 | int minfd = right_fd < 10 ? 10 : right_fd + 1; | 5780 | int minfd = right_fd < 10 ? 10 : right_fd + 1; |
5781 | #if defined(F_DUPFD_CLOEXEC) | ||
5782 | i = fcntl(fd, F_DUPFD_CLOEXEC, minfd); | ||
5783 | #else | ||
5752 | i = fcntl(fd, F_DUPFD, minfd); | 5784 | i = fcntl(fd, F_DUPFD, minfd); |
5753 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds | 5785 | #endif |
5754 | * are closed in popredir() in the child, preventing them from leaking | ||
5755 | * into child. (popredir() also cleans up the mess in case of failures) | ||
5756 | */ | ||
5757 | if (i == -1) { | 5786 | if (i == -1) { |
5758 | i = errno; | 5787 | i = errno; |
5759 | if (i != EBADF) { | 5788 | if (i != EBADF) { |
@@ -5768,6 +5797,9 @@ redirect(union node *redir, int flags) | |||
5768 | remember_to_close: | 5797 | remember_to_close: |
5769 | i = CLOSED; | 5798 | i = CLOSED; |
5770 | } else { /* fd is open, save its copy */ | 5799 | } else { /* fd is open, save its copy */ |
5800 | #if !defined(F_DUPFD_CLOEXEC) | ||
5801 | fcntl(i, F_SETFD, FD_CLOEXEC); | ||
5802 | #endif | ||
5771 | /* "exec fd>&-" should not close fds | 5803 | /* "exec fd>&-" should not close fds |
5772 | * which point to script file(s). | 5804 | * which point to script file(s). |
5773 | * Force them to be restored afterwards */ | 5805 | * Force them to be restored afterwards */ |
@@ -5878,7 +5910,7 @@ redirectsafe(union node *redir, int flags) | |||
5878 | * We have to deal with backquotes, shell variables, and file metacharacters. | 5910 | * We have to deal with backquotes, shell variables, and file metacharacters. |
5879 | */ | 5911 | */ |
5880 | 5912 | ||
5881 | #if ENABLE_SH_MATH_SUPPORT | 5913 | #if ENABLE_FEATURE_SH_MATH |
5882 | static arith_t | 5914 | static arith_t |
5883 | ash_arith(const char *s) | 5915 | ash_arith(const char *s) |
5884 | { | 5916 | { |
@@ -5966,7 +5998,7 @@ static struct arglist exparg; | |||
5966 | /* | 5998 | /* |
5967 | * Our own itoa(). | 5999 | * Our own itoa(). |
5968 | */ | 6000 | */ |
5969 | #if !ENABLE_SH_MATH_SUPPORT | 6001 | #if !ENABLE_FEATURE_SH_MATH |
5970 | /* cvtnum() is used even if math support is off (to prepare $? values and such) */ | 6002 | /* cvtnum() is used even if math support is off (to prepare $? values and such) */ |
5971 | typedef long arith_t; | 6003 | typedef long arith_t; |
5972 | # define ARITH_FMT "%ld" | 6004 | # define ARITH_FMT "%ld" |
@@ -6220,14 +6252,15 @@ memtodest(const char *p, size_t len, int syntax, int quotes) | |||
6220 | do { | 6252 | do { |
6221 | unsigned char c = *p++; | 6253 | unsigned char c = *p++; |
6222 | if (c) { | 6254 | if (c) { |
6223 | int n = SIT(c, syntax); | 6255 | if (quotes & QUOTES_ESC) { |
6224 | if ((quotes & QUOTES_ESC) | 6256 | int n = SIT(c, syntax); |
6225 | && ((n == CCTL) | 6257 | if (n == CCTL |
6226 | || (((quotes & EXP_FULL) || syntax != BASESYNTAX) | 6258 | || (((quotes & EXP_FULL) || syntax != BASESYNTAX) |
6227 | && n == CBACK) | 6259 | && n == CBACK |
6228 | ) | 6260 | ) |
6229 | ) { | 6261 | ) { |
6230 | USTPUTC(CTLESC, q); | 6262 | USTPUTC(CTLESC, q); |
6263 | } | ||
6231 | } | 6264 | } |
6232 | } else if (!(quotes & QUOTES_KEEPNUL)) | 6265 | } else if (!(quotes & QUOTES_KEEPNUL)) |
6233 | continue; | 6266 | continue; |
@@ -6490,7 +6523,7 @@ expbackq(union node *cmd, int flag) | |||
6490 | stackblock() + startloc)); | 6523 | stackblock() + startloc)); |
6491 | } | 6524 | } |
6492 | 6525 | ||
6493 | #if ENABLE_SH_MATH_SUPPORT | 6526 | #if ENABLE_FEATURE_SH_MATH |
6494 | /* | 6527 | /* |
6495 | * Expand arithmetic expression. Backup to start of expression, | 6528 | * Expand arithmetic expression. Backup to start of expression, |
6496 | * evaluate, place result in (backed up) result, adjust string position. | 6529 | * evaluate, place result in (backed up) result, adjust string position. |
@@ -6572,7 +6605,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6572 | CTLESC, | 6605 | CTLESC, |
6573 | CTLVAR, | 6606 | CTLVAR, |
6574 | CTLBACKQ, | 6607 | CTLBACKQ, |
6575 | #if ENABLE_SH_MATH_SUPPORT | 6608 | #if ENABLE_FEATURE_SH_MATH |
6576 | CTLENDARI, | 6609 | CTLENDARI, |
6577 | #endif | 6610 | #endif |
6578 | '\0' | 6611 | '\0' |
@@ -6608,7 +6641,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6608 | c = p[length]; | 6641 | c = p[length]; |
6609 | if (c) { | 6642 | if (c) { |
6610 | if (!(c & 0x80) | 6643 | if (!(c & 0x80) |
6611 | IF_SH_MATH_SUPPORT(|| c == CTLENDARI) | 6644 | IF_FEATURE_SH_MATH(|| c == CTLENDARI) |
6612 | ) { | 6645 | ) { |
6613 | /* c == '=' || c == ':' || c == CTLENDARI */ | 6646 | /* c == '=' || c == ':' || c == CTLENDARI */ |
6614 | length++; | 6647 | length++; |
@@ -6688,7 +6721,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6688 | expbackq(argbackq->n, flags | inquotes); | 6721 | expbackq(argbackq->n, flags | inquotes); |
6689 | argbackq = argbackq->next; | 6722 | argbackq = argbackq->next; |
6690 | goto start; | 6723 | goto start; |
6691 | #if ENABLE_SH_MATH_SUPPORT | 6724 | #if ENABLE_FEATURE_SH_MATH |
6692 | case CTLENDARI: | 6725 | case CTLENDARI: |
6693 | p--; | 6726 | p--; |
6694 | expari(flags | inquotes); | 6727 | expari(flags | inquotes); |
@@ -9686,7 +9719,7 @@ static int helpcmd(int, char **) FAST_FUNC; | |||
9686 | #if MAX_HISTORY | 9719 | #if MAX_HISTORY |
9687 | static int historycmd(int, char **) FAST_FUNC; | 9720 | static int historycmd(int, char **) FAST_FUNC; |
9688 | #endif | 9721 | #endif |
9689 | #if ENABLE_SH_MATH_SUPPORT | 9722 | #if ENABLE_FEATURE_SH_MATH |
9690 | static int letcmd(int, char **) FAST_FUNC; | 9723 | static int letcmd(int, char **) FAST_FUNC; |
9691 | #endif | 9724 | #endif |
9692 | static int readcmd(int, char **) FAST_FUNC; | 9725 | static int readcmd(int, char **) FAST_FUNC; |
@@ -9766,7 +9799,7 @@ static const struct builtincmd builtintab[] = { | |||
9766 | { BUILTIN_REGULAR "jobs" , jobscmd }, | 9799 | { BUILTIN_REGULAR "jobs" , jobscmd }, |
9767 | { BUILTIN_REGULAR "kill" , killcmd }, | 9800 | { BUILTIN_REGULAR "kill" , killcmd }, |
9768 | #endif | 9801 | #endif |
9769 | #if ENABLE_SH_MATH_SUPPORT | 9802 | #if ENABLE_FEATURE_SH_MATH |
9770 | { BUILTIN_NOSPEC "let" , letcmd }, | 9803 | { BUILTIN_NOSPEC "let" , letcmd }, |
9771 | #endif | 9804 | #endif |
9772 | { BUILTIN_ASSIGN "local" , localcmd }, | 9805 | { BUILTIN_ASSIGN "local" , localcmd }, |
@@ -10004,11 +10037,13 @@ evalcommand(union node *cmd, int flags) | |||
10004 | } | 10037 | } |
10005 | 10038 | ||
10006 | if (status) { | 10039 | if (status) { |
10040 | bail: | ||
10041 | exitstatus = status; | ||
10042 | |||
10007 | /* We have a redirection error. */ | 10043 | /* We have a redirection error. */ |
10008 | if (spclbltin > 0) | 10044 | if (spclbltin > 0) |
10009 | raise_exception(EXERROR); | 10045 | raise_exception(EXERROR); |
10010 | bail: | 10046 | |
10011 | exitstatus = status; | ||
10012 | goto out; | 10047 | goto out; |
10013 | } | 10048 | } |
10014 | 10049 | ||
@@ -10516,7 +10551,7 @@ pgetc(void) | |||
10516 | return g_parsefile->lastc[--g_parsefile->unget]; | 10551 | return g_parsefile->lastc[--g_parsefile->unget]; |
10517 | 10552 | ||
10518 | if (--g_parsefile->left_in_line >= 0) | 10553 | if (--g_parsefile->left_in_line >= 0) |
10519 | c = (signed char)*g_parsefile->next_to_pgetc++; | 10554 | c = (unsigned char)*g_parsefile->next_to_pgetc++; |
10520 | else | 10555 | else |
10521 | c = preadbuffer(); | 10556 | c = preadbuffer(); |
10522 | 10557 | ||
@@ -11840,13 +11875,13 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11840 | smallint quotef; | 11875 | smallint quotef; |
11841 | smallint dblquote; | 11876 | smallint dblquote; |
11842 | smallint oldstyle; | 11877 | smallint oldstyle; |
11843 | smallint prevsyntax; /* syntax before arithmetic */ | 11878 | IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */ |
11844 | #if ENABLE_ASH_EXPAND_PRMT | 11879 | #if ENABLE_ASH_EXPAND_PRMT |
11845 | smallint pssyntax; /* we are expanding a prompt string */ | 11880 | smallint pssyntax; /* we are expanding a prompt string */ |
11846 | #endif | 11881 | #endif |
11847 | int varnest; /* levels of variables expansion */ | 11882 | int varnest; /* levels of variables expansion */ |
11848 | int arinest; /* levels of arithmetic expansion */ | 11883 | IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ |
11849 | int parenlevel; /* levels of parens in arithmetic */ | 11884 | IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ |
11850 | int dqvarnest; /* levels of variables expansion within double quotes */ | 11885 | int dqvarnest; /* levels of variables expansion within double quotes */ |
11851 | 11886 | ||
11852 | IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) | 11887 | IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) |
@@ -11854,7 +11889,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11854 | startlinno = g_parsefile->linno; | 11889 | startlinno = g_parsefile->linno; |
11855 | bqlist = NULL; | 11890 | bqlist = NULL; |
11856 | quotef = 0; | 11891 | quotef = 0; |
11857 | prevsyntax = 0; | 11892 | IF_FEATURE_SH_MATH(prevsyntax = 0;) |
11858 | #if ENABLE_ASH_EXPAND_PRMT | 11893 | #if ENABLE_ASH_EXPAND_PRMT |
11859 | pssyntax = (syntax == PSSYNTAX); | 11894 | pssyntax = (syntax == PSSYNTAX); |
11860 | if (pssyntax) | 11895 | if (pssyntax) |
@@ -11862,8 +11897,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11862 | #endif | 11897 | #endif |
11863 | dblquote = (syntax == DQSYNTAX); | 11898 | dblquote = (syntax == DQSYNTAX); |
11864 | varnest = 0; | 11899 | varnest = 0; |
11865 | arinest = 0; | 11900 | IF_FEATURE_SH_MATH(arinest = 0;) |
11866 | parenlevel = 0; | 11901 | IF_FEATURE_SH_MATH(parenlevel = 0;) |
11867 | dqvarnest = 0; | 11902 | dqvarnest = 0; |
11868 | 11903 | ||
11869 | STARTSTACKSTR(out); | 11904 | STARTSTACKSTR(out); |
@@ -11970,7 +12005,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11970 | } | 12005 | } |
11971 | USTPUTC(c, out); | 12006 | USTPUTC(c, out); |
11972 | break; | 12007 | break; |
11973 | #if ENABLE_SH_MATH_SUPPORT | 12008 | #if ENABLE_FEATURE_SH_MATH |
11974 | case CLP: /* '(' in arithmetic */ | 12009 | case CLP: /* '(' in arithmetic */ |
11975 | parenlevel++; | 12010 | parenlevel++; |
11976 | USTPUTC(c, out); | 12011 | USTPUTC(c, out); |
@@ -12021,7 +12056,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
12021 | } /* for (;;) */ | 12056 | } /* for (;;) */ |
12022 | endword: | 12057 | endword: |
12023 | 12058 | ||
12024 | #if ENABLE_SH_MATH_SUPPORT | 12059 | #if ENABLE_FEATURE_SH_MATH |
12025 | if (syntax == ARISYNTAX) | 12060 | if (syntax == ARISYNTAX) |
12026 | raise_error_syntax("missing '))'"); | 12061 | raise_error_syntax("missing '))'"); |
12027 | #endif | 12062 | #endif |
@@ -12200,7 +12235,7 @@ parsesub: { | |||
12200 | } else if (c == '(') { | 12235 | } else if (c == '(') { |
12201 | /* $(command) or $((arith)) */ | 12236 | /* $(command) or $((arith)) */ |
12202 | if (pgetc_eatbnl() == '(') { | 12237 | if (pgetc_eatbnl() == '(') { |
12203 | #if ENABLE_SH_MATH_SUPPORT | 12238 | #if ENABLE_FEATURE_SH_MATH |
12204 | PARSEARITH(); | 12239 | PARSEARITH(); |
12205 | #else | 12240 | #else |
12206 | raise_error_syntax("you disabled math support for $((arith)) syntax"); | 12241 | raise_error_syntax("you disabled math support for $((arith)) syntax"); |
@@ -12455,7 +12490,7 @@ parsebackq: { | |||
12455 | goto parsebackq_newreturn; | 12490 | goto parsebackq_newreturn; |
12456 | } | 12491 | } |
12457 | 12492 | ||
12458 | #if ENABLE_SH_MATH_SUPPORT | 12493 | #if ENABLE_FEATURE_SH_MATH |
12459 | /* | 12494 | /* |
12460 | * Parse an arithmetic expansion (indicate start of one and set state) | 12495 | * Parse an arithmetic expansion (indicate start of one and set state) |
12461 | */ | 12496 | */ |
@@ -13532,7 +13567,7 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13532 | return 0; | 13567 | return 0; |
13533 | } | 13568 | } |
13534 | 13569 | ||
13535 | #if ENABLE_SH_MATH_SUPPORT | 13570 | #if ENABLE_FEATURE_SH_MATH |
13536 | /* | 13571 | /* |
13537 | * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell. | 13572 | * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell. |
13538 | * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. | 13573 | * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. |
@@ -13871,15 +13906,6 @@ init(void) | |||
13871 | //usage:#define ash_full_usage "\n\n" | 13906 | //usage:#define ash_full_usage "\n\n" |
13872 | //usage: "Unix shell interpreter" | 13907 | //usage: "Unix shell interpreter" |
13873 | 13908 | ||
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 | /* | 13909 | /* |
13884 | * Process the shell command line arguments. | 13910 | * Process the shell command line arguments. |
13885 | */ | 13911 | */ |
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/ash_test/ash-redir/redir_leak.right b/shell/ash_test/ash-redir/redir_leak.right new file mode 100644 index 000000000..b1c48292b --- /dev/null +++ b/shell/ash_test/ash-redir/redir_leak.right | |||
@@ -0,0 +1,6 @@ | |||
1 | 4 | ||
2 | 4 | ||
3 | 4 | ||
4 | 4 | ||
5 | 4 | ||
6 | 4 | ||
diff --git a/shell/ash_test/ash-redir/redir_leak.tests b/shell/ash_test/ash-redir/redir_leak.tests new file mode 100755 index 000000000..c8a9c6343 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_leak.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # Each of these should show only four lines: | ||
2 | # fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. | ||
3 | # This test detects bugs where redirects leave stray open fds. | ||
4 | |||
5 | ls -1 /proc/self/fd | wc -l | ||
6 | ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l | ||
7 | ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l | ||
8 | echo "`ls -1 /proc/self/fd `" | wc -l | ||
9 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l | ||
10 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l | ||
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/hush_test/hush-redir/redir_leak.right b/shell/hush_test/hush-redir/redir_leak.right new file mode 100644 index 000000000..b1c48292b --- /dev/null +++ b/shell/hush_test/hush-redir/redir_leak.right | |||
@@ -0,0 +1,6 @@ | |||
1 | 4 | ||
2 | 4 | ||
3 | 4 | ||
4 | 4 | ||
5 | 4 | ||
6 | 4 | ||
diff --git a/shell/hush_test/hush-redir/redir_leak.tests b/shell/hush_test/hush-redir/redir_leak.tests new file mode 100755 index 000000000..c8a9c6343 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_leak.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # Each of these should show only four lines: | ||
2 | # fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. | ||
3 | # This test detects bugs where redirects leave stray open fds. | ||
4 | |||
5 | ls -1 /proc/self/fd | wc -l | ||
6 | ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l | ||
7 | ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l | ||
8 | echo "`ls -1 /proc/self/fd `" | wc -l | ||
9 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l | ||
10 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l | ||
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 |