hush: pass $! thru re-execution; try harder on re-exec; give error
msg if re-exec didn't work; other tweaks in main() function old new delta hush_main 1144 1199 +55 re_execute_shell 237 286 +49 file_get 240 260 +20 clean_up_after_re_execute 58 66 +8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 132/0) Total: 132 bytes
This commit is contained in:
parent
232be3e79b
commit
46f9b6db80
94
shell/hush.c
94
shell/hush.c
@ -487,7 +487,8 @@ struct globals {
|
|||||||
int global_argc;
|
int global_argc;
|
||||||
char **global_argv;
|
char **global_argv;
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
char **argv_for_re_execing;
|
char *argv0_for_re_execing;
|
||||||
|
char **argv_from_re_execing;
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
unsigned depth_break_continue;
|
unsigned depth_break_continue;
|
||||||
@ -2356,18 +2357,19 @@ static void re_execute_shell(const char *s)
|
|||||||
char **argv, **pp, **pp2;
|
char **argv, **pp, **pp2;
|
||||||
unsigned cnt;
|
unsigned cnt;
|
||||||
|
|
||||||
/* 1:hush 2:-$<pid> 3:-?<exitcode> 4:-D<depth> <vars...>
|
/* 1:hush 2:-$<pid> 3:-!<pid> 4:-?<exitcode> 5:-D<depth> <vars...>
|
||||||
* 5:-c 6:<cmd> <argN...> 7:NULL
|
* 6:-c 7:<cmd> <argN...> 8:NULL
|
||||||
*/
|
*/
|
||||||
cnt = 7 + G.global_argc;
|
cnt = 8 + G.global_argc;
|
||||||
for (cur = G.top_var; cur; cur = cur->next) {
|
for (cur = G.top_var; cur; cur = cur->next) {
|
||||||
if (!cur->flg_export || cur->flg_read_only)
|
if (!cur->flg_export || cur->flg_read_only)
|
||||||
cnt += 2;
|
cnt += 2;
|
||||||
}
|
}
|
||||||
G.argv_for_re_execing = pp = xzalloc(sizeof(argv[0]) * cnt);
|
G.argv_from_re_execing = pp = xzalloc(sizeof(argv[0]) * cnt);
|
||||||
*pp++ = (char *) applet_name;
|
*pp++ = (char *) G.argv0_for_re_execing;
|
||||||
*pp++ = xasprintf("-$%u", G.root_pid);
|
*pp++ = xasprintf("-$%u", (unsigned) G.root_pid);
|
||||||
*pp++ = xasprintf("-?%u", G.last_return_code);
|
*pp++ = xasprintf("-!%u", (unsigned) G.last_bg_pid);
|
||||||
|
*pp++ = xasprintf("-?%u", (unsigned) G.last_return_code);
|
||||||
#if ENABLE_HUSH_LOOPS
|
#if ENABLE_HUSH_LOOPS
|
||||||
*pp++ = xasprintf("-D%u", G.depth_of_loop);
|
*pp++ = xasprintf("-D%u", G.depth_of_loop);
|
||||||
#endif
|
#endif
|
||||||
@ -2392,23 +2394,27 @@ static void re_execute_shell(const char *s)
|
|||||||
|
|
||||||
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);
|
||||||
execv(bb_busybox_exec_path, G.argv_for_re_execing);
|
execv(bb_busybox_exec_path, G.argv_from_re_execing);
|
||||||
//TODO: fallback for init=/bin/hush?
|
/* Fallback. Useful for init=/bin/hush usage etc */
|
||||||
_exit(127);
|
if (G.argv0_for_re_execing[0] == '/')
|
||||||
|
execv(G.argv0_for_re_execing, G.argv_from_re_execing);
|
||||||
|
xfunc_error_retval = 127;
|
||||||
|
bb_error_msg_and_die("can't re-execute the shell");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clean_up_after_re_execute(void)
|
static void clean_up_after_re_execute(void)
|
||||||
{
|
{
|
||||||
char **pp = G.argv_for_re_execing;
|
char **pp = G.argv_from_re_execing;
|
||||||
if (pp) {
|
if (pp) {
|
||||||
/* Must match re_execute_shell's allocations */
|
/* Must match re_execute_shell's allocations */
|
||||||
free(pp[1]);
|
free(pp[1]);
|
||||||
free(pp[2]);
|
free(pp[2]);
|
||||||
#if ENABLE_HUSH_LOOPS
|
|
||||||
free(pp[3]);
|
free(pp[3]);
|
||||||
|
#if ENABLE_HUSH_LOOPS
|
||||||
|
free(pp[4]);
|
||||||
#endif
|
#endif
|
||||||
free(pp);
|
free(pp);
|
||||||
G.argv_for_re_execing = NULL;
|
G.argv_from_re_execing = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -3001,8 +3007,8 @@ static void debug_print_tree(struct pipe *pi, int lvl)
|
|||||||
[RES_SNTX ] = "SNTX" ,
|
[RES_SNTX ] = "SNTX" ,
|
||||||
};
|
};
|
||||||
static const char *const GRPTYPE[] = {
|
static const char *const GRPTYPE[] = {
|
||||||
"()",
|
|
||||||
"{}",
|
"{}",
|
||||||
|
"()",
|
||||||
#if ENABLE_HUSH_FUNCTIONS
|
#if ENABLE_HUSH_FUNCTIONS
|
||||||
"func()",
|
"func()",
|
||||||
#endif
|
#endif
|
||||||
@ -4990,14 +4996,15 @@ int hush_main(int argc, char **argv)
|
|||||||
};
|
};
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
FILE *input;
|
|
||||||
char **e;
|
char **e;
|
||||||
struct variable *cur_var;
|
struct variable *cur_var;
|
||||||
|
|
||||||
INIT_G();
|
INIT_G();
|
||||||
|
if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, is already done */
|
||||||
G.root_pid = getpid();
|
G.last_return_code = EXIT_SUCCESS;
|
||||||
|
#if !BB_MMU
|
||||||
|
G.argv0_for_re_execing = argv[0];
|
||||||
|
#endif
|
||||||
/* Deal with HUSH_VERSION */
|
/* Deal with HUSH_VERSION */
|
||||||
G.shell_ver = const_shell_ver; /* copying struct here */
|
G.shell_ver = const_shell_ver; /* copying struct here */
|
||||||
G.top_var = &G.shell_ver;
|
G.top_var = &G.shell_ver;
|
||||||
@ -5020,11 +5027,9 @@ int hush_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
debug_printf_env("putenv '%s'\n", hush_version_str);
|
debug_printf_env("putenv '%s'\n", hush_version_str);
|
||||||
putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */
|
putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING
|
#if ENABLE_FEATURE_EDITING
|
||||||
G.line_input_state = new_line_input_t(FOR_SHELL);
|
G.line_input_state = new_line_input_t(FOR_SHELL);
|
||||||
#endif
|
#endif
|
||||||
/* XXX what should these be while sourcing /etc/profile? */
|
|
||||||
G.global_argc = argc;
|
G.global_argc = argc;
|
||||||
G.global_argv = argv;
|
G.global_argv = argv;
|
||||||
/* Initialize some more globals to non-zero values */
|
/* Initialize some more globals to non-zero values */
|
||||||
@ -5035,31 +5040,19 @@ int hush_main(int argc, char **argv)
|
|||||||
G.PS2 = "> ";
|
G.PS2 = "> ";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (EXIT_SUCCESS) /* otherwise is already done */
|
|
||||||
G.last_return_code = EXIT_SUCCESS;
|
|
||||||
|
|
||||||
if (argv[0] && argv[0][0] == '-') {
|
|
||||||
debug_printf("sourcing /etc/profile\n");
|
|
||||||
input = fopen_for_read("/etc/profile");
|
|
||||||
if (input != NULL) {
|
|
||||||
close_on_exec_on(fileno(input));
|
|
||||||
parse_and_run_file(input);
|
|
||||||
fclose(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
input = stdin;
|
|
||||||
|
|
||||||
/* 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"
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
"$:?:D:R:V:"
|
"$:!:?:D:R:V:"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (opt <= 0)
|
if (opt <= 0)
|
||||||
break;
|
break;
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c':
|
case 'c':
|
||||||
|
if (!G.root_pid)
|
||||||
|
G.root_pid = getpid();
|
||||||
G.global_argv = argv + optind;
|
G.global_argv = argv + optind;
|
||||||
if (!argv[optind]) {
|
if (!argv[optind]) {
|
||||||
/* -c 'script' (no params): prevent empty $0 */
|
/* -c 'script' (no params): prevent empty $0 */
|
||||||
@ -5082,6 +5075,9 @@ int hush_main(int argc, char **argv)
|
|||||||
case '$':
|
case '$':
|
||||||
G.root_pid = xatoi_u(optarg);
|
G.root_pid = xatoi_u(optarg);
|
||||||
break;
|
break;
|
||||||
|
case '!':
|
||||||
|
G.last_bg_pid = xatoi_u(optarg);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
G.last_return_code = xatoi_u(optarg);
|
G.last_return_code = xatoi_u(optarg);
|
||||||
break;
|
break;
|
||||||
@ -5109,6 +5105,21 @@ int hush_main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!G.root_pid)
|
||||||
|
G.root_pid = getpid();
|
||||||
|
if (argv[0] && argv[0][0] == '-') {
|
||||||
|
FILE *input;
|
||||||
|
/* XXX what should argv be while sourcing /etc/profile? */
|
||||||
|
debug_printf("sourcing /etc/profile\n");
|
||||||
|
input = fopen_for_read("/etc/profile");
|
||||||
|
if (input != NULL) {
|
||||||
|
close_on_exec_on(fileno(input));
|
||||||
|
parse_and_run_file(input);
|
||||||
|
fclose(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_JOB
|
#if ENABLE_HUSH_JOB
|
||||||
/* 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:
|
||||||
@ -5117,7 +5128,7 @@ int hush_main(int argc, char **argv)
|
|||||||
* standard input is a terminal
|
* standard input is a terminal
|
||||||
* standard output is a terminal
|
* standard output is a terminal
|
||||||
* Refer to Posix.2, the description of the 'sh' utility. */
|
* Refer to Posix.2, the description of the 'sh' utility. */
|
||||||
if (argv[optind] == NULL && input == stdin
|
if (argv[optind] == NULL
|
||||||
&& isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
|
&& isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
|
||||||
) {
|
) {
|
||||||
G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
|
G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
|
||||||
@ -5152,7 +5163,7 @@ int hush_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#elif ENABLE_HUSH_INTERACTIVE
|
#elif ENABLE_HUSH_INTERACTIVE
|
||||||
/* no job control compiled, only prompt/line editing */
|
/* no job control compiled, only prompt/line editing */
|
||||||
if (argv[optind] == NULL && input == stdin
|
if (argv[optind] == NULL
|
||||||
&& isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
|
&& isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
|
||||||
) {
|
) {
|
||||||
G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
|
G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
|
||||||
@ -5169,10 +5180,12 @@ int hush_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
init_signal_mask(); /* note: ensures SIGCHLD is not masked */
|
init_signal_mask(); /* note: ensures SIGCHLD is not masked */
|
||||||
#else
|
#else
|
||||||
|
//TODO: we didn't do it for -c or /etc/profile! Shouldn't we?
|
||||||
init_signal_mask();
|
init_signal_mask();
|
||||||
#endif
|
#endif
|
||||||
/* POSIX allows shell to re-enable SIGCHLD
|
/* POSIX allows shell to re-enable SIGCHLD
|
||||||
* even if it was SIG_IGN on entry */
|
* even if it was SIG_IGN on entry */
|
||||||
|
//TODO: we didn't do it for -c or /etc/profile! Shouldn't we?
|
||||||
// G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
|
// G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
|
||||||
signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler);
|
signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler);
|
||||||
|
|
||||||
@ -5186,18 +5199,21 @@ int hush_main(int argc, char **argv)
|
|||||||
if (argv[optind] == NULL) {
|
if (argv[optind] == NULL) {
|
||||||
parse_and_run_file(stdin);
|
parse_and_run_file(stdin);
|
||||||
} else {
|
} else {
|
||||||
|
FILE *input;
|
||||||
debug_printf("\nrunning script '%s'\n", argv[optind]);
|
debug_printf("\nrunning script '%s'\n", argv[optind]);
|
||||||
G.global_argv = argv + optind;
|
G.global_argv = argv + optind;
|
||||||
G.global_argc = argc - optind;
|
G.global_argc = argc - optind;
|
||||||
input = xfopen_for_read(argv[optind]);
|
input = xfopen_for_read(argv[optind]);
|
||||||
fcntl(fileno(input), F_SETFD, FD_CLOEXEC);
|
fcntl(fileno(input), F_SETFD, FD_CLOEXEC);
|
||||||
parse_and_run_file(input);
|
parse_and_run_file(input);
|
||||||
|
#if ENABLE_FEATURE_CLEAN_UP
|
||||||
|
fclose(input);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
final_return:
|
final_return:
|
||||||
|
|
||||||
#if ENABLE_FEATURE_CLEAN_UP
|
#if ENABLE_FEATURE_CLEAN_UP
|
||||||
fclose(input);
|
|
||||||
if (G.cwd != bb_msg_unknown)
|
if (G.cwd != bb_msg_unknown)
|
||||||
free((char*)G.cwd);
|
free((char*)G.cwd);
|
||||||
cur_var = G.top_var->next;
|
cur_var = G.top_var->next;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user