diff --git a/include/libbb.h b/include/libbb.h index 32bb3113d..1859a3f09 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -512,6 +512,7 @@ int wait_nohang(int *wstat); /* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */ int spawn_and_wait(char **argv); struct nofork_save_area { + jmp_buf die_jmp; const struct bb_applet *current_applet; int xfunc_error_retval; uint32_t option_mask32; diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c index 20d971591..0e99a03cf 100644 --- a/libbb/error_msg_and_die.c +++ b/libbb/error_msg_and_die.c @@ -27,9 +27,9 @@ void xfunc_die(void) * p = xmalloc(10); * q = xmalloc(10); // BUG! if this dies, we leak p! */ - /* -111 means "zero" (longjmp can't pass 0) - * spawn_and_wait() catches -111. */ - longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -111); + /* -2222 means "zero" (longjmp can't pass 0) + * run_nofork_applet() catches -2222. */ + longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222); } sleep(die_sleep); } diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index a2572b0a9..349628796 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -103,6 +103,7 @@ int wait_pid(int *wstat, int pid) #if ENABLE_FEATURE_PREFER_APPLETS void save_nofork_data(struct nofork_save_area *save) { + memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); save->current_applet = current_applet; save->xfunc_error_retval = xfunc_error_retval; save->option_mask32 = option_mask32; @@ -112,6 +113,7 @@ void save_nofork_data(struct nofork_save_area *save) void restore_nofork_data(struct nofork_save_area *save) { + memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); current_applet = save->current_applet; xfunc_error_retval = save->xfunc_error_retval; option_mask32 = save->option_mask32; @@ -147,7 +149,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet rc = a->main(argc, tmp_argv); } else { /* xfunc died in NOFORK applet */ /* in case they meant to return 0... */ - if (rc == -111) + if (rc == -2222) rc = 0; } @@ -159,6 +161,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet int run_nofork_applet(const struct bb_applet *a, char **argv) { struct nofork_save_area old; + /* Saving globals */ save_nofork_data(&old); return run_nofork_applet_prime(&old, a, argv); diff --git a/shell/hush.c b/shell/hush.c index 579950ff9..1ff7b0df6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -427,13 +427,15 @@ enum { run_list_level = 0 }; /* Normal */ static void syntax(const char *msg) { - bb_error_msg(msg ? "%s: %s" : "syntax error", "syntax error", msg); + (interactive_fd ? bb_error_msg : bb_error_msg_and_die) + (msg ? "%s: %s" : "syntax error", "syntax error", msg); } #else /* Debug */ static void syntax_lineno(int line) { - bb_error_msg("syntax error hush.c:%d", line); + (interactive_fd ? bb_error_msg : bb_error_msg_and_die) + ("syntax error hush.c:%d", line); } #define syntax(str) syntax_lineno(__LINE__) #endif @@ -3309,13 +3311,13 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i /* XXX maybe someone will try to escape the '}' */ while (1) { ch = b_getch(input); - if (ch == EOF) { + if (ch == '}') + break; + if (!isalnum(ch) && ch != '_') { syntax("unterminated ${name}"); debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); return 1; } - if (ch == '}') - break; debug_printf_parse(": '%c'\n", ch); b_addchr(dest, ch | quote_mask); quote_mask = 0;