aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 9920e98c6..3959da1ea 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2180,10 +2180,21 @@ static void re_execute_shell(const char *s, int is_heredoc) NORETURN;
static void re_execute_shell(const char *s, int is_heredoc)
{
char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4];
+ char *heredoc_argv[4];
struct variable *cur;
char **argv, **pp, **pp2;
unsigned cnt;
+ if (is_heredoc) {
+ argv = heredoc_argv;
+ argv[0] = (char *) G.argv0_for_re_execing;
+ argv[1] = (char *) "-<";
+ argv[2] = (char *) s;
+ argv[3] = NULL;
+ pp = &argv[3]; /* used as pointer to empty environmaent */
+ goto do_exec;
+ }
+
sprintf(param_buf, "-$%x:%x:%x" USE_HUSH_LOOPS(":%x")
, (unsigned) G.root_pid
, (unsigned) G.last_bg_pid
@@ -2198,7 +2209,7 @@ static void re_execute_shell(const char *s, int is_heredoc)
if (!cur->flg_export || cur->flg_read_only)
cnt += 2;
}
- G.argv_from_re_execing = pp = xzalloc(sizeof(argv[0]) * cnt);
+ G.argv_from_re_execing = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
*pp++ = (char *) G.argv0_for_re_execing;
*pp++ = param_buf;
for (cur = G.top_var; cur; cur = cur->next) {
@@ -2232,22 +2243,21 @@ static void re_execute_shell(const char *s, int is_heredoc)
* 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 *) (is_heredoc ? "-<" : "-c");
+ *pp++ = (char *) "-c";
*pp++ = (char *) s;
pp2 = G.global_argv;
while (*pp2)
*pp++ = *pp2++;
/* *pp = NULL; - is already there */
+ pp = environ;
+ do_exec:
debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
- execve(bb_busybox_exec_path,
- G.argv_from_re_execing,
- (is_heredoc ? pp /* points to NULL ptr */ : environ)
- );
+ execve(bb_busybox_exec_path, argv, pp);
/* Fallback. Useful for init=/bin/hush usage etc */
- if (G.argv0_for_re_execing[0] == '/')
- execv(G.argv0_for_re_execing, G.argv_from_re_execing);
+ if (argv[0][0] == '/')
+ execve(argv[0], argv, pp);
xfunc_error_retval = 127;
bb_error_msg_and_die("can't re-execute the shell");
}
@@ -2281,6 +2291,7 @@ static void setup_heredoc(struct redir_struct *redir)
}
len = strlen(heredoc);
+ close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
xpiped_pair(pair);
xmove_fd(pair.rd, redir->rd_fd);