aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-15 19:58:19 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-15 19:58:19 +0100
commit647553a4fcbbc169b4390d9ef8e4657f0ffe1a5f (patch)
tree974dde9bc45566319f8b9750b6397fbafe94ad43
parentff1822aed159e1c1b5a92dc5c1fd1648b026f8f4 (diff)
downloadbusybox-w32-647553a4fcbbc169b4390d9ef8e4657f0ffe1a5f.tar.gz
busybox-w32-647553a4fcbbc169b4390d9ef8e4657f0ffe1a5f.tar.bz2
busybox-w32-647553a4fcbbc169b4390d9ef8e4657f0ffe1a5f.zip
hush: wait for `cmd` to complete, and immediately store its exitcode in $?
function old new delta expand_vars_to_list 2129 2197 +68 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/brace.txt50
-rw-r--r--shell/hush.c36
-rw-r--r--shell/hush_test/hush-psubst/tick5.right1
-rwxr-xr-xshell/hush_test/hush-psubst/tick5.tests1
4 files changed, 70 insertions, 18 deletions
diff --git a/shell/brace.txt b/shell/brace.txt
new file mode 100644
index 000000000..664861b08
--- /dev/null
+++ b/shell/brace.txt
@@ -0,0 +1,50 @@
1Brace Expansion
2
3Brace expansion is a mechanism by which arbitrary strings may be gener-
4ated. This mechanism is similar to pathname expansion, but the file-
5names generated need not exist. Patterns to be brace expanded take the
6form of an optional preamble, followed by either a series of comma-sep-
7arated strings or a sequence expression between a pair of braces, fol-
8lowed by an optional postscript. The preamble is prefixed to each
9string contained within the braces, and the postscript is then appended
10to each resulting string, expanding left to right.
11
12Brace expansions may be nested. The results of each expanded string
13are not sorted; left to right order is preserved. For example,
14a{d,c,b}e expands into `ade ace abe'.
15
16A sequence expression takes the form {x..y}, where x and y are either
17integers or single characters. When integers are supplied, the expres-
18sion expands to each number between x and y, inclusive. When charac-
19ters are supplied, the expression expands to each character lexico-
20graphically between x and y, inclusive. Note that both x and y must be
21of the same type.
22
23Brace expansion is performed before any other expansions, and any char-
24acters special to other expansions are preserved in the result. It is
25strictly textual. Bash does not apply any syntactic interpretation to
26the context of the expansion or the text between the braces.
27
28A correctly-formed brace expansion must contain unquoted opening and
29closing braces, and at least one unquoted comma or a valid sequence
30expression. Any incorrectly formed brace expansion is left unchanged.
31A { or , may be quoted with a backslash to prevent its being considered
32part of a brace expression. To avoid conflicts with parameter expan-
33sion, the string ${ is not considered eligible for brace expansion.
34
35This construct is typically used as shorthand when the common prefix of
36the strings to be generated is longer than in the above example:
37
38 mkdir /usr/local/src/bash/{old,new,dist,bugs}
39or
40 chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
41
42Brace expansion introduces a slight incompatibility with historical
43versions of sh. sh does not treat opening or closing braces specially
44when they appear as part of a word, and preserves them in the output.
45Bash removes braces from words as a consequence of brace expansion.
46For example, a word entered to sh as file{1,2} appears identically in
47the output. The same word is output as file1 file2 after expansion by
48bash. If strict compatibility with sh is desired, start bash with the
49+B option or disable brace expansion with the +B option to the set com-
50mand
diff --git a/shell/hush.c b/shell/hush.c
index 891d87be7..6f394d1d5 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2287,7 +2287,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2287 * expanded result may need to be globbed 2287 * expanded result may need to be globbed
2288 * and $IFS-splitted */ 2288 * and $IFS-splitted */
2289 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); 2289 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
2290 process_command_subs(&subst_result, arg); 2290 G.last_exitcode = process_command_subs(&subst_result, arg);
2291 debug_printf_subst("SUBST RES '%s'\n", subst_result.data); 2291 debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
2292 val = subst_result.data; 2292 val = subst_result.data;
2293 goto store_val; 2293 goto store_val;
@@ -3904,7 +3904,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
3904 /* if someone gives us an empty string: `cmd with empty output` */ 3904 /* if someone gives us an empty string: `cmd with empty output` */
3905 if (!argv_expanded[0]) { 3905 if (!argv_expanded[0]) {
3906 debug_leave(); 3906 debug_leave();
3907 return 0; 3907 return 0; // or G.last_exitcode? see emptytick.tests
3908 } 3908 }
3909 3909
3910 x = find_builtin(argv_expanded[0]); 3910 x = find_builtin(argv_expanded[0]);
@@ -5202,10 +5202,10 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_
5202 5202
5203 5203
5204#if ENABLE_HUSH_TICK 5204#if ENABLE_HUSH_TICK
5205static FILE *generate_stream_from_string(const char *s) 5205static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
5206{ 5206{
5207 FILE *pf; 5207 pid_t pid;
5208 int pid, channel[2]; 5208 int channel[2];
5209# if !BB_MMU 5209# if !BB_MMU
5210 char **to_free; 5210 char **to_free;
5211# endif 5211# endif
@@ -5291,6 +5291,7 @@ static FILE *generate_stream_from_string(const char *s)
5291 } 5291 }
5292 5292
5293 /* parent */ 5293 /* parent */
5294 *pid_p = pid;
5294# if ENABLE_HUSH_FAST 5295# if ENABLE_HUSH_FAST
5295 G.count_SIGCHLD++; 5296 G.count_SIGCHLD++;
5296//bb_error_msg("[%d] fork in generate_stream_from_string: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 5297//bb_error_msg("[%d] fork in generate_stream_from_string: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
@@ -5300,8 +5301,8 @@ static FILE *generate_stream_from_string(const char *s)
5300 free(to_free); 5301 free(to_free);
5301# endif 5302# endif
5302 close(channel[1]); 5303 close(channel[1]);
5303 pf = fdopen(channel[0], "r"); 5304//TODO: libbb: fdopen_or_die?
5304 return pf; 5305 return fdopen(channel[0], "r");
5305} 5306}
5306 5307
5307/* Return code is exit status of the process that is run. */ 5308/* Return code is exit status of the process that is run. */
@@ -5309,9 +5310,10 @@ static int process_command_subs(o_string *dest, const char *s)
5309{ 5310{
5310 FILE *pf; 5311 FILE *pf;
5311 struct in_str pipe_str; 5312 struct in_str pipe_str;
5312 int ch, eol_cnt; 5313 pid_t pid;
5314 int status, ch, eol_cnt;
5313 5315
5314 pf = generate_stream_from_string(s); 5316 pf = generate_stream_from_string(s, &pid);
5315 if (pf == NULL) 5317 if (pf == NULL)
5316 return 1; 5318 return 1;
5317 close_on_exec_on(fileno(pf)); 5319 close_on_exec_on(fileno(pf));
@@ -5331,16 +5333,14 @@ static int process_command_subs(o_string *dest, const char *s)
5331 o_addQchr(dest, ch); 5333 o_addQchr(dest, ch);
5332 } 5334 }
5333 5335
5334 debug_printf("done reading from pipe, pclose()ing\n"); 5336 debug_printf("done reading from `cmd` pipe, closing it\n");
5335 /* Note: we got EOF, and we just close the read end of the pipe.
5336 * We do not wait for the `cmd` child to terminate. bash and ash do.
5337 * Try these:
5338 * echo `echo Hi; exec 1>&-; sleep 2` - bash waits 2 sec
5339 * `false`; echo $? - bash outputs "1"
5340 */
5341 fclose(pf); 5337 fclose(pf);
5342 debug_printf("closed FILE from child. return 0\n"); 5338 /* We need to extract exitcode. Test case
5343 return 0; 5339 * "true; echo `sleep 1; false` $?"
5340 * should print 1 */
5341 safe_waitpid(pid, &status, 0);
5342 debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
5343 return WEXITSTATUS(status);
5344} 5344}
5345#endif /* ENABLE_HUSH_TICK */ 5345#endif /* ENABLE_HUSH_TICK */
5346 5346
diff --git a/shell/hush_test/hush-psubst/tick5.right b/shell/hush_test/hush-psubst/tick5.right
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/shell/hush_test/hush-psubst/tick5.right
@@ -0,0 +1 @@
1
diff --git a/shell/hush_test/hush-psubst/tick5.tests b/shell/hush_test/hush-psubst/tick5.tests
new file mode 100755
index 000000000..bd160c9fc
--- /dev/null
+++ b/shell/hush_test/hush-psubst/tick5.tests
@@ -0,0 +1 @@
true; echo `false` $?