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>
This commit is contained in:
parent
ff1822aed1
commit
647553a4fc
50
shell/brace.txt
Normal file
50
shell/brace.txt
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
Brace Expansion
|
||||||
|
|
||||||
|
Brace expansion is a mechanism by which arbitrary strings may be gener-
|
||||||
|
ated. This mechanism is similar to pathname expansion, but the file-
|
||||||
|
names generated need not exist. Patterns to be brace expanded take the
|
||||||
|
form of an optional preamble, followed by either a series of comma-sep-
|
||||||
|
arated strings or a sequence expression between a pair of braces, fol-
|
||||||
|
lowed by an optional postscript. The preamble is prefixed to each
|
||||||
|
string contained within the braces, and the postscript is then appended
|
||||||
|
to each resulting string, expanding left to right.
|
||||||
|
|
||||||
|
Brace expansions may be nested. The results of each expanded string
|
||||||
|
are not sorted; left to right order is preserved. For example,
|
||||||
|
a{d,c,b}e expands into `ade ace abe'.
|
||||||
|
|
||||||
|
A sequence expression takes the form {x..y}, where x and y are either
|
||||||
|
integers or single characters. When integers are supplied, the expres-
|
||||||
|
sion expands to each number between x and y, inclusive. When charac-
|
||||||
|
ters are supplied, the expression expands to each character lexico-
|
||||||
|
graphically between x and y, inclusive. Note that both x and y must be
|
||||||
|
of the same type.
|
||||||
|
|
||||||
|
Brace expansion is performed before any other expansions, and any char-
|
||||||
|
acters special to other expansions are preserved in the result. It is
|
||||||
|
strictly textual. Bash does not apply any syntactic interpretation to
|
||||||
|
the context of the expansion or the text between the braces.
|
||||||
|
|
||||||
|
A correctly-formed brace expansion must contain unquoted opening and
|
||||||
|
closing braces, and at least one unquoted comma or a valid sequence
|
||||||
|
expression. Any incorrectly formed brace expansion is left unchanged.
|
||||||
|
A { or , may be quoted with a backslash to prevent its being considered
|
||||||
|
part of a brace expression. To avoid conflicts with parameter expan-
|
||||||
|
sion, the string ${ is not considered eligible for brace expansion.
|
||||||
|
|
||||||
|
This construct is typically used as shorthand when the common prefix of
|
||||||
|
the strings to be generated is longer than in the above example:
|
||||||
|
|
||||||
|
mkdir /usr/local/src/bash/{old,new,dist,bugs}
|
||||||
|
or
|
||||||
|
chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
|
||||||
|
|
||||||
|
Brace expansion introduces a slight incompatibility with historical
|
||||||
|
versions of sh. sh does not treat opening or closing braces specially
|
||||||
|
when they appear as part of a word, and preserves them in the output.
|
||||||
|
Bash removes braces from words as a consequence of brace expansion.
|
||||||
|
For example, a word entered to sh as file{1,2} appears identically in
|
||||||
|
the output. The same word is output as file1 file2 after expansion by
|
||||||
|
bash. If strict compatibility with sh is desired, start bash with the
|
||||||
|
+B option or disable brace expansion with the +B option to the set com-
|
||||||
|
mand
|
36
shell/hush.c
36
shell/hush.c
@ -2287,7 +2287,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
|
|||||||
* expanded result may need to be globbed
|
* expanded result may need to be globbed
|
||||||
* and $IFS-splitted */
|
* and $IFS-splitted */
|
||||||
debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
|
debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
|
||||||
process_command_subs(&subst_result, arg);
|
G.last_exitcode = process_command_subs(&subst_result, arg);
|
||||||
debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
|
debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
|
||||||
val = subst_result.data;
|
val = subst_result.data;
|
||||||
goto store_val;
|
goto store_val;
|
||||||
@ -3904,7 +3904,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
/* if someone gives us an empty string: `cmd with empty output` */
|
/* if someone gives us an empty string: `cmd with empty output` */
|
||||||
if (!argv_expanded[0]) {
|
if (!argv_expanded[0]) {
|
||||||
debug_leave();
|
debug_leave();
|
||||||
return 0;
|
return 0; // or G.last_exitcode? see emptytick.tests
|
||||||
}
|
}
|
||||||
|
|
||||||
x = find_builtin(argv_expanded[0]);
|
x = find_builtin(argv_expanded[0]);
|
||||||
@ -5202,10 +5202,10 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_
|
|||||||
|
|
||||||
|
|
||||||
#if ENABLE_HUSH_TICK
|
#if ENABLE_HUSH_TICK
|
||||||
static FILE *generate_stream_from_string(const char *s)
|
static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
|
||||||
{
|
{
|
||||||
FILE *pf;
|
pid_t pid;
|
||||||
int pid, channel[2];
|
int channel[2];
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
char **to_free;
|
char **to_free;
|
||||||
# endif
|
# endif
|
||||||
@ -5291,6 +5291,7 @@ static FILE *generate_stream_from_string(const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
|
*pid_p = pid;
|
||||||
# if ENABLE_HUSH_FAST
|
# if ENABLE_HUSH_FAST
|
||||||
G.count_SIGCHLD++;
|
G.count_SIGCHLD++;
|
||||||
//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);
|
//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)
|
|||||||
free(to_free);
|
free(to_free);
|
||||||
# endif
|
# endif
|
||||||
close(channel[1]);
|
close(channel[1]);
|
||||||
pf = fdopen(channel[0], "r");
|
//TODO: libbb: fdopen_or_die?
|
||||||
return pf;
|
return fdopen(channel[0], "r");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return code is exit status of the process that is run. */
|
/* 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)
|
|||||||
{
|
{
|
||||||
FILE *pf;
|
FILE *pf;
|
||||||
struct in_str pipe_str;
|
struct in_str pipe_str;
|
||||||
int ch, eol_cnt;
|
pid_t pid;
|
||||||
|
int status, ch, eol_cnt;
|
||||||
|
|
||||||
pf = generate_stream_from_string(s);
|
pf = generate_stream_from_string(s, &pid);
|
||||||
if (pf == NULL)
|
if (pf == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
close_on_exec_on(fileno(pf));
|
close_on_exec_on(fileno(pf));
|
||||||
@ -5331,16 +5333,14 @@ static int process_command_subs(o_string *dest, const char *s)
|
|||||||
o_addQchr(dest, ch);
|
o_addQchr(dest, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_printf("done reading from pipe, pclose()ing\n");
|
debug_printf("done reading from `cmd` pipe, closing it\n");
|
||||||
/* Note: we got EOF, and we just close the read end of the pipe.
|
|
||||||
* We do not wait for the `cmd` child to terminate. bash and ash do.
|
|
||||||
* Try these:
|
|
||||||
* echo `echo Hi; exec 1>&-; sleep 2` - bash waits 2 sec
|
|
||||||
* `false`; echo $? - bash outputs "1"
|
|
||||||
*/
|
|
||||||
fclose(pf);
|
fclose(pf);
|
||||||
debug_printf("closed FILE from child. return 0\n");
|
/* We need to extract exitcode. Test case
|
||||||
return 0;
|
* "true; echo `sleep 1; false` $?"
|
||||||
|
* should print 1 */
|
||||||
|
safe_waitpid(pid, &status, 0);
|
||||||
|
debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
|
||||||
|
return WEXITSTATUS(status);
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_HUSH_TICK */
|
#endif /* ENABLE_HUSH_TICK */
|
||||||
|
|
||||||
|
1
shell/hush_test/hush-psubst/tick5.right
Normal file
1
shell/hush_test/hush-psubst/tick5.right
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
1
shell/hush_test/hush-psubst/tick5.tests
Executable file
1
shell/hush_test/hush-psubst/tick5.tests
Executable file
@ -0,0 +1 @@
|
|||||||
|
true; echo `false` $?
|
Loading…
Reference in New Issue
Block a user