diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 304 |
1 files changed, 165 insertions, 139 deletions
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 | */ |