aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 8ffdfb1a8..47eff0fb8 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -481,11 +481,14 @@ struct globals {
481 smallint fake_mode; 481 smallint fake_mode;
482 /* These four support $?, $#, and $1 */ 482 /* These four support $?, $#, and $1 */
483 smalluint last_return_code; 483 smalluint last_return_code;
484 /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */ 484 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
485 smalluint global_args_malloced; 485 smalluint global_args_malloced;
486 /* how many non-NULL argv's we have. NB: $# + 1 */ 486 /* how many non-NULL argv's we have. NB: $# + 1 */
487 int global_argc; 487 int global_argc;
488 char **global_argv; 488 char **global_argv;
489#if !BB_MMU
490 char **argv_for_re_execing;
491#endif
489#if ENABLE_HUSH_LOOPS 492#if ENABLE_HUSH_LOOPS
490 unsigned depth_break_continue; 493 unsigned depth_break_continue;
491 unsigned depth_of_loop; 494 unsigned depth_of_loop;
@@ -1127,7 +1130,9 @@ static int set_local_var(char *str, int flg_export, int flg_read_only)
1127 1130
1128 set_str_and_exp: 1131 set_str_and_exp:
1129 cur->varstr = str; 1132 cur->varstr = str;
1133#if !BB_MMU
1130 cur->flg_read_only = flg_read_only; 1134 cur->flg_read_only = flg_read_only;
1135#endif
1131 exp: 1136 exp:
1132 if (flg_export == 1) 1137 if (flg_export == 1)
1133 cur->flg_export = 1; 1138 cur->flg_export = 1;
@@ -2338,6 +2343,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
2338 _exit(EXIT_FAILURE); 2343 _exit(EXIT_FAILURE);
2339} 2344}
2340 2345
2346#if !BB_MMU
2341static void re_execute_shell(const char *s) NORETURN; 2347static void re_execute_shell(const char *s) NORETURN;
2342static void re_execute_shell(const char *s) 2348static void re_execute_shell(const char *s)
2343{ 2349{
@@ -2354,7 +2360,7 @@ static void re_execute_shell(const char *s)
2354 cnt += 2; 2360 cnt += 2;
2355 } 2361 }
2356//TODO: need to free these strings in parent! 2362//TODO: need to free these strings in parent!
2357 argv = pp = xmalloc(sizeof(argv[0]) * cnt); 2363 G.argv_for_re_execing = pp = xmalloc(sizeof(argv[0]) * cnt);
2358 *pp++ = (char *) applet_name; 2364 *pp++ = (char *) applet_name;
2359 *pp++ = xasprintf("-$%u", G.root_pid); 2365 *pp++ = xasprintf("-$%u", G.root_pid);
2360 *pp++ = xasprintf("-?%u", G.last_return_code); 2366 *pp++ = xasprintf("-?%u", G.last_return_code);
@@ -2379,11 +2385,28 @@ static void re_execute_shell(const char *s)
2379//TODO: pass traps and functions 2385//TODO: pass traps and functions
2380 2386
2381 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); 2387 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
2382 execv(bb_busybox_exec_path, argv); 2388 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2389 execv(bb_busybox_exec_path, G.argv_for_re_execing);
2383//TODO: fallback for init=/bin/hush? 2390//TODO: fallback for init=/bin/hush?
2384 _exit(127); 2391 _exit(127);
2385} 2392}
2386 2393
2394static void clean_up_after_re_execute(void)
2395{
2396 char **pp = G.argv_for_re_execing;
2397 if (pp) {
2398 /* Must match re_execute_shell's allocations */
2399 free(pp[1]);
2400 free(pp[2]);
2401 free(pp[3]);
2402 free(pp);
2403 G.argv_for_re_execing = NULL;
2404 }
2405}
2406#else
2407#define clean_up_after_re_execute() ((void)0)
2408#endif
2409
2387static int run_list(struct pipe *pi); 2410static int run_list(struct pipe *pi);
2388 2411
2389/* Called after [v]fork() in run_pipe() 2412/* Called after [v]fork() in run_pipe()
@@ -2892,9 +2915,11 @@ static int run_pipe(struct pipe *pi)
2892 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded); 2915 pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
2893 /* pseudo_exec() does not return */ 2916 /* pseudo_exec() does not return */
2894 } 2917 }
2918
2895 /* parent */ 2919 /* parent */
2896#if !BB_MMU 2920#if !BB_MMU
2897 /* Clean up after vforked child */ 2921 /* Clean up after vforked child */
2922 clean_up_after_re_execute();
2898 free(nommu_save.argv); 2923 free(nommu_save.argv);
2899 free_strings_and_unsetenv(nommu_save.new_env, 1); 2924 free_strings_and_unsetenv(nommu_save.new_env, 1);
2900 putenv_all(nommu_save.old_env); 2925 putenv_all(nommu_save.old_env);
@@ -3890,6 +3915,7 @@ static FILE *generate_stream_from_string(const char *s)
3890 } 3915 }
3891 3916
3892 /* parent */ 3917 /* parent */
3918 clean_up_after_re_execute();
3893 close(channel[1]); 3919 close(channel[1]);
3894 pf = fdopen(channel[0], "r"); 3920 pf = fdopen(channel[0], "r");
3895 return pf; 3921 return pf;
@@ -4827,6 +4853,9 @@ static struct pipe *parse_stream(char **pstring,
4827 * while if false; then false; fi do break; done 4853 * while if false; then false; fi do break; done
4828 * (bash accepts it) 4854 * (bash accepts it)
4829 * while if false; then false; fi; do break; fi 4855 * while if false; then false; fi; do break; fi
4856 * Samples to catch leaks at execution:
4857 * while if (true | {true;}); then echo ok; fi; do break; done
4858 * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
4830 */ 4859 */
4831 pctx = &ctx; 4860 pctx = &ctx;
4832 do { 4861 do {