hush: fix trap clearing in subshells on MMU; simplify NOMMU a bit:

function                                             old     new   delta
parse_stream_dquoted                                 335     324     -11
handle_dollar                                        849     800     -49
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-60)             Total: -60 bytes
This commit is contained in:
Denis Vlasenko 2009-04-05 20:33:27 +00:00
parent f937528571
commit c4a7af55e9

View File

@ -1603,10 +1603,10 @@ static int process_command_subs(o_string *dest, const char *s);
#endif
static char *expand_string_to_string(const char *str);
#if BB_MMU
#define parse_stream_dquoted(ctx, dest, input, dquote_end) \
#define parse_stream_dquoted(as_string, dest, input, dquote_end) \
parse_stream_dquoted(dest, input, dquote_end)
#endif
static int parse_stream_dquoted(struct parse_context *ctx,
static int parse_stream_dquoted(o_string *as_string,
o_string *dest,
struct in_str *input,
int dquote_end);
@ -2275,7 +2275,38 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
_exit(EXIT_FAILURE);
}
#if !BB_MMU
#if BB_MMU
static void reset_traps_to_defaults(void)
{
unsigned sig;
int dirty;
if (!G.traps)
return;
dirty = 0;
for (sig = 0; sig < NSIG; sig++) {
if (!G.traps[sig])
continue;
free(G.traps[sig]);
G.traps[sig] = NULL;
/* There is no signal for 0 (EXIT) */
if (sig == 0)
continue;
/* there was a trap handler, we are removing it
* (if sig has non-DFL handling,
* we don't need to do anything) */
if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
continue;
sigdelset(&G.blocked_set, sig);
dirty = 1;
}
if (dirty)
sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
}
#define clean_up_after_re_execute() ((void)0)
#else /* !BB_MMU */
static void re_execute_shell(const char *s) NORETURN;
static void re_execute_shell(const char *s)
{
@ -2310,13 +2341,32 @@ static void re_execute_shell(const char *s)
*pp++ = cur->varstr;
}
}
//TODO: pass functions
/* We can pass activated traps here. Say, -Tnn:trap_string
*
* However, POSIX says that subshells reset signals with traps
* to SIG_DFL.
* I tested bash-3.2 and it not only does that with true subshells
* of the form ( list ), but with any forked children shells.
* I set trap "echo W" WINCH; and then tried:
*
* { echo 1; sleep 20; echo 2; } &
* while true; do echo 1; sleep 20; echo 2; break; done &
* true | { echo 1; sleep 20; echo 2; } | cat
*
* In all these cases sending SIGWINCH to the child shell
* did not run the trap. If I add trap "echo V" WINCH;
* _inside_ group (just before echo 1), it works.
*
* I conclude it means we don't need to pass active traps here.
* exec syscall below resets them to SIG_DFL for us.
*/
*pp++ = (char *) "-c";
*pp++ = (char *) s;
pp2 = G.global_argv;
while (*pp2)
*pp++ = *pp2++;
/* *pp = NULL; - is already there */
//TODO: pass traps and functions
debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
@ -2343,8 +2393,6 @@ static void clean_up_after_re_execute(void)
G.argv_from_re_execing = NULL;
}
}
#else
#define clean_up_after_re_execute() ((void)0)
#endif
static int run_list(struct pipe *pi);
@ -2373,6 +2421,7 @@ static void pseudo_exec(nommu_save_t *nommu_save,
#if BB_MMU
int rcode;
debug_printf_exec("pseudo_exec: run_list\n");
reset_traps_to_defaults();
rcode = run_list(command->group);
/* OK to leak memory by not calling free_pipe_list,
* since this process is about to exit */
@ -3846,6 +3895,7 @@ static FILE *generate_stream_from_string(const char *s)
/* Prevent it from trying to handle ctrl-z etc */
USE_HUSH_JOB(G.run_list_level = 1;)
#if BB_MMU
reset_traps_to_defaults();
parse_and_run_string(s);
_exit(G.last_return_code);
#else
@ -4097,10 +4147,10 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
/* Return code: 0 for OK, 1 for syntax error */
#if BB_MMU
#define handle_dollar(ctx, dest, input) \
#define handle_dollar(as_string, dest, input) \
handle_dollar(dest, input)
#endif
static int handle_dollar(struct parse_context *ctx,
static int handle_dollar(o_string *as_string,
o_string *dest,
struct in_str *input)
{
@ -4112,7 +4162,7 @@ static int handle_dollar(struct parse_context *ctx,
if (isalpha(ch)) {
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
make_var:
o_addchr(dest, SPECIAL_VAR_SYMBOL);
@ -4125,7 +4175,7 @@ static int handle_dollar(struct parse_context *ctx,
break;
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
}
o_addchr(dest, SPECIAL_VAR_SYMBOL);
@ -4133,7 +4183,7 @@ static int handle_dollar(struct parse_context *ctx,
make_one_char_var:
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
o_addchr(dest, SPECIAL_VAR_SYMBOL);
debug_printf_parse(": '%c'\n", ch);
@ -4153,7 +4203,7 @@ static int handle_dollar(struct parse_context *ctx,
o_addchr(dest, SPECIAL_VAR_SYMBOL);
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
/* XXX maybe someone will try to escape the '}' */
expansion = 0;
@ -4162,7 +4212,7 @@ static int handle_dollar(struct parse_context *ctx,
while (1) {
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
if (ch == '}')
break;
@ -4235,13 +4285,13 @@ static int handle_dollar(struct parse_context *ctx,
# endif
ch = i_getch(input);
# if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
# endif
# if ENABLE_SH_MATH_SUPPORT
if (i_peek(input) == '(') {
ch = i_getch(input);
# if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
# endif
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, /*quote_mask |*/ '+');
@ -4250,10 +4300,10 @@ static int handle_dollar(struct parse_context *ctx,
# endif
add_till_closing_paren(dest, input, true);
# if !BB_MMU
if (ctx) {
o_addstr(&ctx->as_string, dest->data + pos);
o_addchr(&ctx->as_string, ')');
o_addchr(&ctx->as_string, ')');
if (as_string) {
o_addstr(as_string, dest->data + pos);
o_addchr(as_string, ')');
o_addchr(as_string, ')');
}
# endif
o_addchr(dest, SPECIAL_VAR_SYMBOL);
@ -4269,9 +4319,9 @@ static int handle_dollar(struct parse_context *ctx,
# endif
add_till_closing_paren(dest, input, false);
# if !BB_MMU
if (ctx) {
o_addstr(&ctx->as_string, dest->data + pos);
o_addchr(&ctx->as_string, '`');
if (as_string) {
o_addstr(as_string, dest->data + pos);
o_addchr(as_string, '`');
}
# endif
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
@ -4283,7 +4333,7 @@ static int handle_dollar(struct parse_context *ctx,
case '_':
ch = i_getch(input);
#if !BB_MMU
if (ctx) o_addchr(&ctx->as_string, ch);
if (as_string) o_addchr(as_string, ch);
#endif
ch = i_peek(input);
if (isalnum(ch)) { /* it's $_name or $_123 */
@ -4302,10 +4352,10 @@ static int handle_dollar(struct parse_context *ctx,
}
#if BB_MMU
#define parse_stream_dquoted(ctx, dest, input, dquote_end) \
#define parse_stream_dquoted(as_string, dest, input, dquote_end) \
parse_stream_dquoted(dest, input, dquote_end)
#endif
static int parse_stream_dquoted(struct parse_context *ctx,
static int parse_stream_dquoted(o_string *as_string,
o_string *dest,
struct in_str *input,
int dquote_end)
@ -4316,8 +4366,8 @@ static int parse_stream_dquoted(struct parse_context *ctx,
again:
ch = i_getch(input);
#if !BB_MMU
if (ctx && ch != EOF)
o_addchr(&ctx->as_string, ch);
if (as_string && ch != EOF)
o_addchr(as_string, ch);
#endif
if (ch == dquote_end) { /* may be only '"' or EOF */
dest->nonnull = 1;
@ -4360,7 +4410,7 @@ static int parse_stream_dquoted(struct parse_context *ctx,
goto again;
}
if (ch == '$') {
if (handle_dollar(ctx, dest, input) != 0) {
if (handle_dollar(as_string, dest, input) != 0) {
debug_printf_parse("parse_stream_dquoted return 1: "
"handle_dollar returned non-0\n");
return 1;
@ -4432,7 +4482,7 @@ static struct pipe *parse_stream(char **pstring,
redir_type redir_style;
if (is_in_dquote) {
if (parse_stream_dquoted(&ctx, &dest, input, '"')) {
if (parse_stream_dquoted(&ctx.as_string, &dest, input, '"')) {
goto parse_error;
}
/* We reached closing '"' */
@ -4579,8 +4629,7 @@ static struct pipe *parse_stream(char **pstring,
#endif
break;
case '$':
//NOMMU TODO!
if (handle_dollar(&ctx, &dest, input) != 0) {
if (handle_dollar(&ctx.as_string, &dest, input) != 0) {
debug_printf_parse("parse_stream parse error: "
"handle_dollar returned non-0\n");
goto parse_error;
@ -5023,6 +5072,15 @@ int hush_main(int argc, char **argv)
G.PS2 = "> ";
#endif
/* Shell is non-interactive at first. We need to call
* block_signals(0) if we are going to execute "sh script",
* "sh -c cmds" or login shell's /etc/profile and friends.
* If we later decide that we are interactive, we run block_signals(0)
* (or re-run block_signals(1) if we ran block_signals(0) before)
* in order to intercept (more) signals.
*/
/* Parse options */
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
while (1) {
opt = getopt(argc, argv, "c:xins"
@ -5136,7 +5194,9 @@ int hush_main(int argc, char **argv)
goto final_return;
}
/* Up to here, shell was non-interactive. Now it may become one. */
/* Up to here, shell was non-interactive. Now it may become one.
* NB: don't forget to (re)run block_signals(0/1) as needed.
*/
/* A shell is interactive if the '-i' flag was given, or if all of
* the following conditions are met: