mirror of
https://github.com/sheumann/hush.git
synced 2024-10-12 01:24:10 +00:00
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:
parent
f937528571
commit
c4a7af55e9
124
shell/hush.c
124
shell/hush.c
@ -1603,10 +1603,10 @@ static int process_command_subs(o_string *dest, const char *s);
|
|||||||
#endif
|
#endif
|
||||||
static char *expand_string_to_string(const char *str);
|
static char *expand_string_to_string(const char *str);
|
||||||
#if BB_MMU
|
#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)
|
parse_stream_dquoted(dest, input, dquote_end)
|
||||||
#endif
|
#endif
|
||||||
static int parse_stream_dquoted(struct parse_context *ctx,
|
static int parse_stream_dquoted(o_string *as_string,
|
||||||
o_string *dest,
|
o_string *dest,
|
||||||
struct in_str *input,
|
struct in_str *input,
|
||||||
int dquote_end);
|
int dquote_end);
|
||||||
@ -2275,7 +2275,38 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
|
|||||||
_exit(EXIT_FAILURE);
|
_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) NORETURN;
|
||||||
static void re_execute_shell(const char *s)
|
static void re_execute_shell(const char *s)
|
||||||
{
|
{
|
||||||
@ -2310,13 +2341,32 @@ static void re_execute_shell(const char *s)
|
|||||||
*pp++ = cur->varstr;
|
*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 *) "-c";
|
||||||
*pp++ = (char *) s;
|
*pp++ = (char *) s;
|
||||||
pp2 = G.global_argv;
|
pp2 = G.global_argv;
|
||||||
while (*pp2)
|
while (*pp2)
|
||||||
*pp++ = *pp2++;
|
*pp++ = *pp2++;
|
||||||
/* *pp = NULL; - is already there */
|
/* *pp = NULL; - is already there */
|
||||||
//TODO: pass traps and functions
|
|
||||||
|
|
||||||
debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
|
debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
|
||||||
sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
|
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;
|
G.argv_from_re_execing = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define clean_up_after_re_execute() ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int run_list(struct pipe *pi);
|
static int run_list(struct pipe *pi);
|
||||||
@ -2373,6 +2421,7 @@ static void pseudo_exec(nommu_save_t *nommu_save,
|
|||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
int rcode;
|
int rcode;
|
||||||
debug_printf_exec("pseudo_exec: run_list\n");
|
debug_printf_exec("pseudo_exec: run_list\n");
|
||||||
|
reset_traps_to_defaults();
|
||||||
rcode = run_list(command->group);
|
rcode = run_list(command->group);
|
||||||
/* OK to leak memory by not calling free_pipe_list,
|
/* OK to leak memory by not calling free_pipe_list,
|
||||||
* since this process is about to exit */
|
* 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 */
|
/* Prevent it from trying to handle ctrl-z etc */
|
||||||
USE_HUSH_JOB(G.run_list_level = 1;)
|
USE_HUSH_JOB(G.run_list_level = 1;)
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
|
reset_traps_to_defaults();
|
||||||
parse_and_run_string(s);
|
parse_and_run_string(s);
|
||||||
_exit(G.last_return_code);
|
_exit(G.last_return_code);
|
||||||
#else
|
#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 */
|
/* Return code: 0 for OK, 1 for syntax error */
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
#define handle_dollar(ctx, dest, input) \
|
#define handle_dollar(as_string, dest, input) \
|
||||||
handle_dollar(dest, input)
|
handle_dollar(dest, input)
|
||||||
#endif
|
#endif
|
||||||
static int handle_dollar(struct parse_context *ctx,
|
static int handle_dollar(o_string *as_string,
|
||||||
o_string *dest,
|
o_string *dest,
|
||||||
struct in_str *input)
|
struct in_str *input)
|
||||||
{
|
{
|
||||||
@ -4112,7 +4162,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
if (isalpha(ch)) {
|
if (isalpha(ch)) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
make_var:
|
make_var:
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
@ -4125,7 +4175,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
break;
|
break;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
@ -4133,7 +4183,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
make_one_char_var:
|
make_one_char_var:
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
debug_printf_parse(": '%c'\n", ch);
|
debug_printf_parse(": '%c'\n", ch);
|
||||||
@ -4153,7 +4203,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
/* XXX maybe someone will try to escape the '}' */
|
/* XXX maybe someone will try to escape the '}' */
|
||||||
expansion = 0;
|
expansion = 0;
|
||||||
@ -4162,7 +4212,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
while (1) {
|
while (1) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
if (ch == '}')
|
if (ch == '}')
|
||||||
break;
|
break;
|
||||||
@ -4235,13 +4285,13 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
# endif
|
# endif
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
# endif
|
# endif
|
||||||
# if ENABLE_SH_MATH_SUPPORT
|
# if ENABLE_SH_MATH_SUPPORT
|
||||||
if (i_peek(input) == '(') {
|
if (i_peek(input) == '(') {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
# endif
|
# endif
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
o_addchr(dest, /*quote_mask |*/ '+');
|
o_addchr(dest, /*quote_mask |*/ '+');
|
||||||
@ -4250,10 +4300,10 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
# endif
|
# endif
|
||||||
add_till_closing_paren(dest, input, true);
|
add_till_closing_paren(dest, input, true);
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
if (ctx) {
|
if (as_string) {
|
||||||
o_addstr(&ctx->as_string, dest->data + pos);
|
o_addstr(as_string, dest->data + pos);
|
||||||
o_addchr(&ctx->as_string, ')');
|
o_addchr(as_string, ')');
|
||||||
o_addchr(&ctx->as_string, ')');
|
o_addchr(as_string, ')');
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
@ -4269,9 +4319,9 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
# endif
|
# endif
|
||||||
add_till_closing_paren(dest, input, false);
|
add_till_closing_paren(dest, input, false);
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
if (ctx) {
|
if (as_string) {
|
||||||
o_addstr(&ctx->as_string, dest->data + pos);
|
o_addstr(as_string, dest->data + pos);
|
||||||
o_addchr(&ctx->as_string, '`');
|
o_addchr(as_string, '`');
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
|
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
|
||||||
@ -4283,7 +4333,7 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
case '_':
|
case '_':
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx) o_addchr(&ctx->as_string, ch);
|
if (as_string) o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
ch = i_peek(input);
|
ch = i_peek(input);
|
||||||
if (isalnum(ch)) { /* it's $_name or $_123 */
|
if (isalnum(ch)) { /* it's $_name or $_123 */
|
||||||
@ -4302,10 +4352,10 @@ static int handle_dollar(struct parse_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BB_MMU
|
#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)
|
parse_stream_dquoted(dest, input, dquote_end)
|
||||||
#endif
|
#endif
|
||||||
static int parse_stream_dquoted(struct parse_context *ctx,
|
static int parse_stream_dquoted(o_string *as_string,
|
||||||
o_string *dest,
|
o_string *dest,
|
||||||
struct in_str *input,
|
struct in_str *input,
|
||||||
int dquote_end)
|
int dquote_end)
|
||||||
@ -4316,8 +4366,8 @@ static int parse_stream_dquoted(struct parse_context *ctx,
|
|||||||
again:
|
again:
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
if (ctx && ch != EOF)
|
if (as_string && ch != EOF)
|
||||||
o_addchr(&ctx->as_string, ch);
|
o_addchr(as_string, ch);
|
||||||
#endif
|
#endif
|
||||||
if (ch == dquote_end) { /* may be only '"' or EOF */
|
if (ch == dquote_end) { /* may be only '"' or EOF */
|
||||||
dest->nonnull = 1;
|
dest->nonnull = 1;
|
||||||
@ -4360,7 +4410,7 @@ static int parse_stream_dquoted(struct parse_context *ctx,
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
if (ch == '$') {
|
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: "
|
debug_printf_parse("parse_stream_dquoted return 1: "
|
||||||
"handle_dollar returned non-0\n");
|
"handle_dollar returned non-0\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -4432,7 +4482,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
redir_type redir_style;
|
redir_type redir_style;
|
||||||
|
|
||||||
if (is_in_dquote) {
|
if (is_in_dquote) {
|
||||||
if (parse_stream_dquoted(&ctx, &dest, input, '"')) {
|
if (parse_stream_dquoted(&ctx.as_string, &dest, input, '"')) {
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
}
|
}
|
||||||
/* We reached closing '"' */
|
/* We reached closing '"' */
|
||||||
@ -4579,8 +4629,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
//NOMMU TODO!
|
if (handle_dollar(&ctx.as_string, &dest, input) != 0) {
|
||||||
if (handle_dollar(&ctx, &dest, input) != 0) {
|
|
||||||
debug_printf_parse("parse_stream parse error: "
|
debug_printf_parse("parse_stream parse error: "
|
||||||
"handle_dollar returned non-0\n");
|
"handle_dollar returned non-0\n");
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
@ -5023,6 +5072,15 @@ int hush_main(int argc, char **argv)
|
|||||||
G.PS2 = "> ";
|
G.PS2 = "> ";
|
||||||
#endif
|
#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 */
|
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
|
||||||
while (1) {
|
while (1) {
|
||||||
opt = getopt(argc, argv, "c:xins"
|
opt = getopt(argc, argv, "c:xins"
|
||||||
@ -5136,7 +5194,9 @@ int hush_main(int argc, char **argv)
|
|||||||
goto final_return;
|
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
|
/* A shell is interactive if the '-i' flag was given, or if all of
|
||||||
* the following conditions are met:
|
* the following conditions are met:
|
||||||
|
Loading…
Reference in New Issue
Block a user