aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 10:39:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 10:39:03 +0000
commit46f9b6db80e4fd0a1c50d435bc387ad28d12abb2 (patch)
tree99bf6bc0b7db612cfac96ae5d4ac4b653d3b3a3e /shell
parent232be3e79b97eceae617fe8af020d23b49e01de1 (diff)
downloadbusybox-w32-46f9b6db80e4fd0a1c50d435bc387ad28d12abb2.tar.gz
busybox-w32-46f9b6db80e4fd0a1c50d435bc387ad28d12abb2.tar.bz2
busybox-w32-46f9b6db80e4fd0a1c50d435bc387ad28d12abb2.zip
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
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c98
1 files changed, 57 insertions, 41 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 39d3c01de..eba7a86df 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -487,7 +487,8 @@ struct globals {
487 int global_argc; 487 int global_argc;
488 char **global_argv; 488 char **global_argv;
489#if !BB_MMU 489#if !BB_MMU
490 char **argv_for_re_execing; 490 char *argv0_for_re_execing;
491 char **argv_from_re_execing;
491#endif 492#endif
492#if ENABLE_HUSH_LOOPS 493#if ENABLE_HUSH_LOOPS
493 unsigned depth_break_continue; 494 unsigned depth_break_continue;
@@ -2356,18 +2357,19 @@ static void re_execute_shell(const char *s)
2356 char **argv, **pp, **pp2; 2357 char **argv, **pp, **pp2;
2357 unsigned cnt; 2358 unsigned cnt;
2358 2359
2359 /* 1:hush 2:-$<pid> 3:-?<exitcode> 4:-D<depth> <vars...> 2360 /* 1:hush 2:-$<pid> 3:-!<pid> 4:-?<exitcode> 5:-D<depth> <vars...>
2360 * 5:-c 6:<cmd> <argN...> 7:NULL 2361 * 6:-c 7:<cmd> <argN...> 8:NULL
2361 */ 2362 */
2362 cnt = 7 + G.global_argc; 2363 cnt = 8 + G.global_argc;
2363 for (cur = G.top_var; cur; cur = cur->next) { 2364 for (cur = G.top_var; cur; cur = cur->next) {
2364 if (!cur->flg_export || cur->flg_read_only) 2365 if (!cur->flg_export || cur->flg_read_only)
2365 cnt += 2; 2366 cnt += 2;
2366 } 2367 }
2367 G.argv_for_re_execing = pp = xzalloc(sizeof(argv[0]) * cnt); 2368 G.argv_from_re_execing = pp = xzalloc(sizeof(argv[0]) * cnt);
2368 *pp++ = (char *) applet_name; 2369 *pp++ = (char *) G.argv0_for_re_execing;
2369 *pp++ = xasprintf("-$%u", G.root_pid); 2370 *pp++ = xasprintf("-$%u", (unsigned) G.root_pid);
2370 *pp++ = xasprintf("-?%u", G.last_return_code); 2371 *pp++ = xasprintf("-!%u", (unsigned) G.last_bg_pid);
2372 *pp++ = xasprintf("-?%u", (unsigned) G.last_return_code);
2371#if ENABLE_HUSH_LOOPS 2373#if ENABLE_HUSH_LOOPS
2372 *pp++ = xasprintf("-D%u", G.depth_of_loop); 2374 *pp++ = xasprintf("-D%u", G.depth_of_loop);
2373#endif 2375#endif
@@ -2392,23 +2394,27 @@ static void re_execute_shell(const char *s)
2392 2394
2393 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); 2395 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
2394 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 2396 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2395 execv(bb_busybox_exec_path, G.argv_for_re_execing); 2397 execv(bb_busybox_exec_path, G.argv_from_re_execing);
2396//TODO: fallback for init=/bin/hush? 2398 /* Fallback. Useful for init=/bin/hush usage etc */
2397 _exit(127); 2399 if (G.argv0_for_re_execing[0] == '/')
2400 execv(G.argv0_for_re_execing, G.argv_from_re_execing);
2401 xfunc_error_retval = 127;
2402 bb_error_msg_and_die("can't re-execute the shell");
2398} 2403}
2399 2404
2400static void clean_up_after_re_execute(void) 2405static void clean_up_after_re_execute(void)
2401{ 2406{
2402 char **pp = G.argv_for_re_execing; 2407 char **pp = G.argv_from_re_execing;
2403 if (pp) { 2408 if (pp) {
2404 /* Must match re_execute_shell's allocations */ 2409 /* Must match re_execute_shell's allocations */
2405 free(pp[1]); 2410 free(pp[1]);
2406 free(pp[2]); 2411 free(pp[2]);
2407#if ENABLE_HUSH_LOOPS
2408 free(pp[3]); 2412 free(pp[3]);
2413#if ENABLE_HUSH_LOOPS
2414 free(pp[4]);
2409#endif 2415#endif
2410 free(pp); 2416 free(pp);
2411 G.argv_for_re_execing = NULL; 2417 G.argv_from_re_execing = NULL;
2412 } 2418 }
2413} 2419}
2414#else 2420#else
@@ -3001,8 +3007,8 @@ static void debug_print_tree(struct pipe *pi, int lvl)
3001 [RES_SNTX ] = "SNTX" , 3007 [RES_SNTX ] = "SNTX" ,
3002 }; 3008 };
3003 static const char *const GRPTYPE[] = { 3009 static const char *const GRPTYPE[] = {
3004 "()",
3005 "{}", 3010 "{}",
3011 "()",
3006#if ENABLE_HUSH_FUNCTIONS 3012#if ENABLE_HUSH_FUNCTIONS
3007 "func()", 3013 "func()",
3008#endif 3014#endif
@@ -4990,14 +4996,15 @@ int hush_main(int argc, char **argv)
4990 }; 4996 };
4991 4997
4992 int opt; 4998 int opt;
4993 FILE *input;
4994 char **e; 4999 char **e;
4995 struct variable *cur_var; 5000 struct variable *cur_var;
4996 5001
4997 INIT_G(); 5002 INIT_G();
4998 5003 if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, is already done */
4999 G.root_pid = getpid(); 5004 G.last_return_code = EXIT_SUCCESS;
5000 5005#if !BB_MMU
5006 G.argv0_for_re_execing = argv[0];
5007#endif
5001 /* Deal with HUSH_VERSION */ 5008 /* Deal with HUSH_VERSION */
5002 G.shell_ver = const_shell_ver; /* copying struct here */ 5009 G.shell_ver = const_shell_ver; /* copying struct here */
5003 G.top_var = &G.shell_ver; 5010 G.top_var = &G.shell_ver;
@@ -5020,11 +5027,9 @@ int hush_main(int argc, char **argv)
5020 } 5027 }
5021 debug_printf_env("putenv '%s'\n", hush_version_str); 5028 debug_printf_env("putenv '%s'\n", hush_version_str);
5022 putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */ 5029 putenv((char *)hush_version_str); /* reinstate HUSH_VERSION */
5023
5024#if ENABLE_FEATURE_EDITING 5030#if ENABLE_FEATURE_EDITING
5025 G.line_input_state = new_line_input_t(FOR_SHELL); 5031 G.line_input_state = new_line_input_t(FOR_SHELL);
5026#endif 5032#endif
5027 /* XXX what should these be while sourcing /etc/profile? */
5028 G.global_argc = argc; 5033 G.global_argc = argc;
5029 G.global_argv = argv; 5034 G.global_argv = argv;
5030 /* Initialize some more globals to non-zero values */ 5035 /* Initialize some more globals to non-zero values */
@@ -5035,31 +5040,19 @@ int hush_main(int argc, char **argv)
5035 G.PS2 = "> "; 5040 G.PS2 = "> ";
5036#endif 5041#endif
5037 5042
5038 if (EXIT_SUCCESS) /* otherwise is already done */
5039 G.last_return_code = EXIT_SUCCESS;
5040
5041 if (argv[0] && argv[0][0] == '-') {
5042 debug_printf("sourcing /etc/profile\n");
5043 input = fopen_for_read("/etc/profile");
5044 if (input != NULL) {
5045 close_on_exec_on(fileno(input));
5046 parse_and_run_file(input);
5047 fclose(input);
5048 }
5049 }
5050 input = stdin;
5051
5052 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ 5043 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
5053 while (1) { 5044 while (1) {
5054 opt = getopt(argc, argv, "c:xins" 5045 opt = getopt(argc, argv, "c:xins"
5055#if !BB_MMU 5046#if !BB_MMU
5056 "$:?:D:R:V:" 5047 "$:!:?:D:R:V:"
5057#endif 5048#endif
5058 ); 5049 );
5059 if (opt <= 0) 5050 if (opt <= 0)
5060 break; 5051 break;
5061 switch (opt) { 5052 switch (opt) {
5062 case 'c': 5053 case 'c':
5054 if (!G.root_pid)
5055 G.root_pid = getpid();
5063 G.global_argv = argv + optind; 5056 G.global_argv = argv + optind;
5064 if (!argv[optind]) { 5057 if (!argv[optind]) {
5065 /* -c 'script' (no params): prevent empty $0 */ 5058 /* -c 'script' (no params): prevent empty $0 */
@@ -5082,6 +5075,9 @@ int hush_main(int argc, char **argv)
5082 case '$': 5075 case '$':
5083 G.root_pid = xatoi_u(optarg); 5076 G.root_pid = xatoi_u(optarg);
5084 break; 5077 break;
5078 case '!':
5079 G.last_bg_pid = xatoi_u(optarg);
5080 break;
5085 case '?': 5081 case '?':
5086 G.last_return_code = xatoi_u(optarg); 5082 G.last_return_code = xatoi_u(optarg);
5087 break; 5083 break;
@@ -5109,6 +5105,21 @@ int hush_main(int argc, char **argv)
5109#endif 5105#endif
5110 } 5106 }
5111 } 5107 }
5108
5109 if (!G.root_pid)
5110 G.root_pid = getpid();
5111 if (argv[0] && argv[0][0] == '-') {
5112 FILE *input;
5113 /* XXX what should argv be while sourcing /etc/profile? */
5114 debug_printf("sourcing /etc/profile\n");
5115 input = fopen_for_read("/etc/profile");
5116 if (input != NULL) {
5117 close_on_exec_on(fileno(input));
5118 parse_and_run_file(input);
5119 fclose(input);
5120 }
5121 }
5122
5112#if ENABLE_HUSH_JOB 5123#if ENABLE_HUSH_JOB
5113 /* A shell is interactive if the '-i' flag was given, or if all of 5124 /* A shell is interactive if the '-i' flag was given, or if all of
5114 * the following conditions are met: 5125 * the following conditions are met:
@@ -5117,7 +5128,7 @@ int hush_main(int argc, char **argv)
5117 * standard input is a terminal 5128 * standard input is a terminal
5118 * standard output is a terminal 5129 * standard output is a terminal
5119 * Refer to Posix.2, the description of the 'sh' utility. */ 5130 * Refer to Posix.2, the description of the 'sh' utility. */
5120 if (argv[optind] == NULL && input == stdin 5131 if (argv[optind] == NULL
5121 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 5132 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
5122 ) { 5133 ) {
5123 G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); 5134 G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
@@ -5132,8 +5143,8 @@ int hush_main(int argc, char **argv)
5132 /* give up */ 5143 /* give up */
5133 G_interactive_fd = 0; 5144 G_interactive_fd = 0;
5134 } 5145 }
5135 // TODO: track & disallow any attempts of user 5146// TODO: track & disallow any attempts of user
5136 // to (inadvertently) close/redirect it 5147// to (inadvertently) close/redirect it
5137 } 5148 }
5138 } 5149 }
5139 init_signal_mask(); /* note: ensures SIGCHLD is not masked */ 5150 init_signal_mask(); /* note: ensures SIGCHLD is not masked */
@@ -5152,7 +5163,7 @@ int hush_main(int argc, char **argv)
5152 } 5163 }
5153#elif ENABLE_HUSH_INTERACTIVE 5164#elif ENABLE_HUSH_INTERACTIVE
5154/* no job control compiled, only prompt/line editing */ 5165/* no job control compiled, only prompt/line editing */
5155 if (argv[optind] == NULL && input == stdin 5166 if (argv[optind] == NULL
5156 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 5167 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
5157 ) { 5168 ) {
5158 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 5169 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
@@ -5169,10 +5180,12 @@ int hush_main(int argc, char **argv)
5169 } 5180 }
5170 init_signal_mask(); /* note: ensures SIGCHLD is not masked */ 5181 init_signal_mask(); /* note: ensures SIGCHLD is not masked */
5171#else 5182#else
5183//TODO: we didn't do it for -c or /etc/profile! Shouldn't we?
5172 init_signal_mask(); 5184 init_signal_mask();
5173#endif 5185#endif
5174 /* POSIX allows shell to re-enable SIGCHLD 5186 /* POSIX allows shell to re-enable SIGCHLD
5175 * even if it was SIG_IGN on entry */ 5187 * even if it was SIG_IGN on entry */
5188//TODO: we didn't do it for -c or /etc/profile! Shouldn't we?
5176// G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ 5189// G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
5177 signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler); 5190 signal(SIGCHLD, SIG_DFL); // SIGCHLD_handler);
5178 5191
@@ -5186,18 +5199,21 @@ int hush_main(int argc, char **argv)
5186 if (argv[optind] == NULL) { 5199 if (argv[optind] == NULL) {
5187 parse_and_run_file(stdin); 5200 parse_and_run_file(stdin);
5188 } else { 5201 } else {
5202 FILE *input;
5189 debug_printf("\nrunning script '%s'\n", argv[optind]); 5203 debug_printf("\nrunning script '%s'\n", argv[optind]);
5190 G.global_argv = argv + optind; 5204 G.global_argv = argv + optind;
5191 G.global_argc = argc - optind; 5205 G.global_argc = argc - optind;
5192 input = xfopen_for_read(argv[optind]); 5206 input = xfopen_for_read(argv[optind]);
5193 fcntl(fileno(input), F_SETFD, FD_CLOEXEC); 5207 fcntl(fileno(input), F_SETFD, FD_CLOEXEC);
5194 parse_and_run_file(input); 5208 parse_and_run_file(input);
5209#if ENABLE_FEATURE_CLEAN_UP
5210 fclose(input);
5211#endif
5195 } 5212 }
5196 5213
5197 final_return: 5214 final_return:
5198 5215
5199#if ENABLE_FEATURE_CLEAN_UP 5216#if ENABLE_FEATURE_CLEAN_UP
5200 fclose(input);
5201 if (G.cwd != bb_msg_unknown) 5217 if (G.cwd != bb_msg_unknown)
5202 free((char*)G.cwd); 5218 free((char*)G.cwd);
5203 cur_var = G.top_var->next; 5219 cur_var = G.top_var->next;