aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-04 20:24:37 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-04 20:24:37 +0000
commit34d4d89b2d3337ea1486d98ea979c1594a6a5efe (patch)
tree1ce6c4b4da6699c66733392c27f8dfc115e2edab
parent552433bc5af76c8e5b52278b3d609e9a18c19dc2 (diff)
downloadbusybox-w32-34d4d89b2d3337ea1486d98ea979c1594a6a5efe.tar.gz
busybox-w32-34d4d89b2d3337ea1486d98ea979c1594a6a5efe.tar.bz2
busybox-w32-34d4d89b2d3337ea1486d98ea979c1594a6a5efe.zip
hush: fix NOMMU hangs in pseudo_exec_argv. Add forgotted setting
of signal mask. Reuse same help string in all shells. function old new delta builtin_exit 49 47 -2 pseudo_exec_argv 149 145 -4 builtin_help 74 63 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-17) Total: -17 bytes text data bss dec hex filename 825379 476 7616 833471 cb7bf busybox_old 825341 476 7616 833433 cb799 busybox_unstripped
-rw-r--r--shell/ash.c4
-rw-r--r--shell/hush.c124
-rw-r--r--shell/lash_unused.c5
-rw-r--r--shell/msh.c6
4 files changed, 75 insertions, 64 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 1cd205068..fe8c1bed2 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -12230,7 +12230,9 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12230 unsigned col; 12230 unsigned col;
12231 unsigned i; 12231 unsigned i;
12232 12232
12233 out1fmt("\nBuilt-in commands:\n-------------------\n"); 12233 out1fmt("\n"
12234 "Built-in commands:\n"
12235 "------------------\n");
12234 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) { 12236 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12235 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), 12237 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12236 builtintab[i].name + 1); 12238 builtintab[i].name + 1);
diff --git a/shell/hush.c b/shell/hush.c
index 61db928b2..c38420240 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -363,11 +363,13 @@ struct parse_context {
363 /* bitmask of FLAG_xxx, for figuring out valid reserved words */ 363 /* bitmask of FLAG_xxx, for figuring out valid reserved words */
364 int old_flag; 364 int old_flag;
365 /* group we are enclosed in: 365 /* group we are enclosed in:
366 * example 1: "{ { false; ..." 366 * example: "if pipe1; pipe2; then pipe3; fi"
367 * example 2: "if true; then { false; ..." 367 * when we see "if" or "then", we malloc and copy current context,
368 * example 3: "if true; then if false; ..." 368 * and make ->stack point to it. then we parse pipeN.
369 * when we find closing "}" / "fi" / whatever, we move list_head 369 * when closing "then" / fi" / whatever is found,
370 * into stack->command->group and delete ourself. 370 * we move list_head into ->stack->command->group,
371 * copy ->stack into current context, and delete ->stack.
372 * (parsing of { list } and ( list ) doesn't use this method)
371 */ 373 */
372 struct parse_context *stack; 374 struct parse_context *stack;
373#endif 375#endif
@@ -532,7 +534,6 @@ static int builtin_wait(char **argv);
532static int builtin_break(char **argv); 534static int builtin_break(char **argv);
533static int builtin_continue(char **argv); 535static int builtin_continue(char **argv);
534#endif 536#endif
535//static int builtin_not_written(char **argv);
536 537
537/* Table of built-in functions. They can be forked or not, depending on 538/* Table of built-in functions. They can be forked or not, depending on
538 * context: within pipes, they fork. As simple commands, they do not. 539 * context: within pipes, they fork. As simple commands, they do not.
@@ -554,42 +555,44 @@ struct built_in_command {
554/* For now, echo and test are unconditionally enabled. 555/* For now, echo and test are unconditionally enabled.
555 * Maybe make it configurable? */ 556 * Maybe make it configurable? */
556static const struct built_in_command bltins[] = { 557static const struct built_in_command bltins[] = {
557 BLTIN("." , builtin_source, "Run commands in a file"), 558 BLTIN("." , builtin_source , "Run commands in a file"),
558 BLTIN(":" , builtin_true, "No-op"), 559 BLTIN(":" , builtin_true , "No-op"),
559 BLTIN("[" , builtin_test, "Test condition"), 560 BLTIN("[" , builtin_test , "Test condition"),
560#if ENABLE_HUSH_JOB 561#if ENABLE_HUSH_JOB
561 BLTIN("bg" , builtin_fg_bg, "Resume a job in the background"), 562 BLTIN("bg" , builtin_fg_bg , "Resume a job in the background"),
562#endif 563#endif
563#if ENABLE_HUSH_LOOPS 564#if ENABLE_HUSH_LOOPS
564 BLTIN("break" , builtin_break, "Exit from a loop"), 565 BLTIN("break" , builtin_break , "Exit from a loop"),
565#endif 566#endif
566 BLTIN("cd" , builtin_cd, "Change directory"), 567 BLTIN("cd" , builtin_cd , "Change directory"),
567#if ENABLE_HUSH_LOOPS 568#if ENABLE_HUSH_LOOPS
568 BLTIN("continue", builtin_continue, "Start new loop iteration"), 569 BLTIN("continue", builtin_continue, "Start new loop iteration"),
569#endif 570#endif
570 BLTIN("echo" , builtin_echo, "Write to stdout"), 571 BLTIN("echo" , builtin_echo , "Write to stdout"),
571 BLTIN("eval" , builtin_eval, "Construct and run shell command"), 572 BLTIN("eval" , builtin_eval , "Construct and run shell command"),
572 BLTIN("exec" , builtin_exec, "Execute command, don't return to shell"), 573 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"),
573 BLTIN("exit" , builtin_exit, "Exit"), 574 BLTIN("exit" , builtin_exit , "Exit"),
574 BLTIN("export", builtin_export, "Set environment variable"), 575 BLTIN("export" , builtin_export , "Set environment variable"),
575#if ENABLE_HUSH_JOB 576#if ENABLE_HUSH_JOB
576 BLTIN("fg" , builtin_fg_bg, "Bring job into the foreground"), 577 BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"),
577 BLTIN("jobs" , builtin_jobs, "List active jobs"), 578#endif
578#endif
579 BLTIN("pwd" , builtin_pwd, "Print current directory"),
580 BLTIN("read" , builtin_read, "Input environment variable"),
581// BLTIN("return", builtin_not_written, "Return from a function"),
582 BLTIN("set" , builtin_set, "Set/unset shell local variables"),
583 BLTIN("shift" , builtin_shift, "Shift positional parameters"),
584 BLTIN("test" , builtin_test, "Test condition"),
585 BLTIN("trap" , builtin_trap, "Trap signals"),
586// BLTIN("ulimit", builtin_not_written, "Control resource limits"),
587 BLTIN("umask" , builtin_umask, "Set file creation mask"),
588 BLTIN("unset" , builtin_unset, "Unset environment variable"),
589 BLTIN("wait" , builtin_wait, "Wait for process"),
590#if ENABLE_HUSH_HELP 579#if ENABLE_HUSH_HELP
591 BLTIN("help" , builtin_help, "List shell built-in commands"), 580 BLTIN("help" , builtin_help , "List shell built-in commands"),
592#endif 581#endif
582#if ENABLE_HUSH_JOB
583 BLTIN("jobs" , builtin_jobs , "List active jobs"),
584#endif
585 BLTIN("pwd" , builtin_pwd , "Print current directory"),
586 BLTIN("read" , builtin_read , "Input environment variable"),
587// BLTIN("return" , builtin_return , "Return from a function"),
588 BLTIN("set" , builtin_set , "Set/unset shell local variables"),
589 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
590 BLTIN("test" , builtin_test , "Test condition"),
591 BLTIN("trap" , builtin_trap , "Trap signals"),
592// BLTIN("ulimit" , builtin_return , "Control resource limits"),
593 BLTIN("umask" , builtin_umask , "Set file creation mask"),
594 BLTIN("unset" , builtin_unset , "Unset environment variable"),
595 BLTIN("wait" , builtin_wait , "Wait for process"),
593}; 596};
594 597
595 598
@@ -2117,7 +2120,7 @@ static void restore_redirects(int squirrel[])
2117#endif 2120#endif
2118static void free_pipe_list(struct pipe *head, int indent); 2121static void free_pipe_list(struct pipe *head, int indent);
2119 2122
2120/* return code is the exit status of the pipe */ 2123/* Return code is the exit status of the pipe */
2121static void free_pipe(struct pipe *pi, int indent) 2124static void free_pipe(struct pipe *pi, int indent)
2122{ 2125{
2123 char **p; 2126 char **p;
@@ -2125,7 +2128,7 @@ static void free_pipe(struct pipe *pi, int indent)
2125 struct redir_struct *r, *rnext; 2128 struct redir_struct *r, *rnext;
2126 int a, i; 2129 int a, i;
2127 2130
2128 if (pi->stopped_cmds > 0) 2131 if (pi->stopped_cmds > 0) /* why? */
2129 return; 2132 return;
2130 debug_printf_clean("%s run pipe: (pid %d)\n", indenter(indent), getpid()); 2133 debug_printf_clean("%s run pipe: (pid %d)\n", indenter(indent), getpid());
2131 for (i = 0; i < pi->num_cmds; i++) { 2134 for (i = 0; i < pi->num_cmds; i++) {
@@ -2216,9 +2219,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
2216 char **new_env; 2219 char **new_env;
2217 const struct built_in_command *x; 2220 const struct built_in_command *x;
2218 2221
2219 /* If a variable is assigned in a forest, and nobody listens, 2222 /* Case when we are here: ... | var=val | ... */
2220 * was it ever really set?
2221 */
2222 if (!argv[assignment_cnt]) 2223 if (!argv[assignment_cnt])
2223 _exit(EXIT_SUCCESS); 2224 _exit(EXIT_SUCCESS);
2224 2225
@@ -2239,8 +2240,13 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
2239#endif 2240#endif
2240 } 2241 }
2241 2242
2242 /* 2243 /* On NOMMU, we must never block!
2243 * Check if the command matches any of the builtins. 2244 * Example: { sleep 99999 | read line } & echo Ok
2245 * read builtin will block on read syscall, leaving parent blocked
2246 * in vfork. Therefore we can't do this:
2247 */
2248#if BB_MMU
2249 /* Check if the command matches any of the builtins.
2244 * Depending on context, this might be redundant. But it's 2250 * Depending on context, this might be redundant. But it's
2245 * easier to waste a few CPU cycles than it is to figure out 2251 * easier to waste a few CPU cycles than it is to figure out
2246 * if this is one of those cases. 2252 * if this is one of those cases.
@@ -2249,33 +2255,35 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
2249 if (strcmp(argv[0], x->cmd) == 0) { 2255 if (strcmp(argv[0], x->cmd) == 0) {
2250 debug_printf_exec("running builtin '%s'\n", argv[0]); 2256 debug_printf_exec("running builtin '%s'\n", argv[0]);
2251 rcode = x->function(argv); 2257 rcode = x->function(argv);
2252 fflush(stdout); 2258 fflush(NULL);
2253 _exit(rcode); 2259 _exit(rcode);
2254 } 2260 }
2255 } 2261 }
2262#endif
2256 2263
2257 /* Check if the command matches any busybox applets */
2258#if ENABLE_FEATURE_SH_STANDALONE 2264#if ENABLE_FEATURE_SH_STANDALONE
2265 /* Check if the command matches any busybox applets */
2259 if (strchr(argv[0], '/') == NULL) { 2266 if (strchr(argv[0], '/') == NULL) {
2260 int a = find_applet_by_name(argv[0]); 2267 int a = find_applet_by_name(argv[0]);
2261 if (a >= 0) { 2268 if (a >= 0) {
2269#if BB_MMU /* see above why on NOMMU it is not allowed */
2262 if (APPLET_IS_NOEXEC(a)) { 2270 if (APPLET_IS_NOEXEC(a)) {
2263 debug_printf_exec("running applet '%s'\n", argv[0]); 2271 debug_printf_exec("running applet '%s'\n", argv[0]);
2264// is it ok that run_applet_no_and_exit() does exit(), not _exit()?
2265 run_applet_no_and_exit(a, argv); 2272 run_applet_no_and_exit(a, argv);
2266 } 2273 }
2267 /* re-exec ourselves with the new arguments */ 2274#endif
2275 /* Re-exec ourselves */
2268 debug_printf_exec("re-execing applet '%s'\n", argv[0]); 2276 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
2269 execvp(bb_busybox_exec_path, argv); 2277 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2278 execv(bb_busybox_exec_path, argv);
2270 /* If they called chroot or otherwise made the binary no longer 2279 /* If they called chroot or otherwise made the binary no longer
2271 * executable, fall through */ 2280 * executable, fall through */
2272 } 2281 }
2273 } 2282 }
2274#endif 2283#endif
2275 2284
2276 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2277
2278 debug_printf_exec("execing '%s'\n", argv[0]); 2285 debug_printf_exec("execing '%s'\n", argv[0]);
2286 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
2279 execvp(argv[0], argv); 2287 execvp(argv[0], argv);
2280 bb_perror_msg("can't exec '%s'", argv[0]); 2288 bb_perror_msg("can't exec '%s'", argv[0]);
2281 _exit(EXIT_FAILURE); 2289 _exit(EXIT_FAILURE);
@@ -2317,8 +2325,8 @@ static void pseudo_exec(nommu_save_t *nommu_save,
2317#endif 2325#endif
2318 } 2326 }
2319 2327
2320 /* Can happen. See what bash does with ">foo" by itself. */ 2328 /* Case when we are here: ... | >file */
2321 debug_printf("pseudo_exec'ed null command\n"); 2329 debug_printf_exec("pseudo_exec'ed null command\n");
2322 _exit(EXIT_SUCCESS); 2330 _exit(EXIT_SUCCESS);
2323} 2331}
2324 2332
@@ -2569,8 +2577,8 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
2569} 2577}
2570#endif 2578#endif
2571 2579
2572/* run_pipe() starts all the jobs, but doesn't wait for anything 2580/* Start all the jobs, but don't wait for anything to finish.
2573 * to finish. See checkjobs(). 2581 * See checkjobs().
2574 * 2582 *
2575 * Return code is normally -1, when the caller has to wait for children 2583 * Return code is normally -1, when the caller has to wait for children
2576 * to finish to determine the exit status of the pipe. If the pipe 2584 * to finish to determine the exit status of the pipe. If the pipe
@@ -2588,7 +2596,7 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
2588 * cmd || ... { list } || ... 2596 * cmd || ... { list } || ...
2589 * If it is, then we can run cmd as a builtin, NOFORK [do we do this?], 2597 * If it is, then we can run cmd as a builtin, NOFORK [do we do this?],
2590 * or (if SH_STANDALONE) an applet, and we can run the { list } 2598 * or (if SH_STANDALONE) an applet, and we can run the { list }
2591 * with run_list(). Otherwise, we fork and exec cmd. 2599 * with run_list(). If it isn't one of these, we fork and exec cmd.
2592 * 2600 *
2593 * Cases when we must fork: 2601 * Cases when we must fork:
2594 * non-single: cmd | cmd 2602 * non-single: cmd | cmd
@@ -3771,7 +3779,7 @@ static FILE *generate_stream_from_string(const char *s)
3771 * echo OK 3779 * echo OK
3772 */ 3780 */
3773//TODO: pass non-exported variables, traps, and functions 3781//TODO: pass non-exported variables, traps, and functions
3774 execl(CONFIG_BUSYBOX_EXEC_PATH, "hush", "-c", s, NULL); 3782 execl(bb_busybox_exec_path, "hush", "-c", s, NULL);
3775 _exit(127); 3783 _exit(127);
3776#endif 3784#endif
3777 } 3785 }
@@ -5144,7 +5152,7 @@ static int builtin_fg_bg(char **argv)
5144 found: 5152 found:
5145 // TODO: bash prints a string representation 5153 // TODO: bash prints a string representation
5146 // of job being foregrounded (like "sleep 1 | cat") 5154 // of job being foregrounded (like "sleep 1 | cat")
5147 if (*argv[0] == 'f') { 5155 if (argv[0][0] == 'f') {
5148 /* Put the job into the foreground. */ 5156 /* Put the job into the foreground. */
5149 tcsetpgrp(G_interactive_fd, pi->pgrp); 5157 tcsetpgrp(G_interactive_fd, pi->pgrp);
5150 } 5158 }
@@ -5162,12 +5170,11 @@ static int builtin_fg_bg(char **argv)
5162 if (errno == ESRCH) { 5170 if (errno == ESRCH) {
5163 delete_finished_bg_job(pi); 5171 delete_finished_bg_job(pi);
5164 return EXIT_SUCCESS; 5172 return EXIT_SUCCESS;
5165 } else {
5166 bb_perror_msg("kill (SIGCONT)");
5167 } 5173 }
5174 bb_perror_msg("kill (SIGCONT)");
5168 } 5175 }
5169 5176
5170 if (*argv[0] == 'f') { 5177 if (argv[0][0] == 'f') {
5171 remove_bg_job(pi); 5178 remove_bg_job(pi);
5172 return checkjobs_and_fg_shell(pi); 5179 return checkjobs_and_fg_shell(pi);
5173 } 5180 }
@@ -5180,8 +5187,9 @@ static int builtin_help(char **argv UNUSED_PARAM)
5180{ 5187{
5181 const struct built_in_command *x; 5188 const struct built_in_command *x;
5182 5189
5183 printf("\nBuilt-in commands:\n"); 5190 printf("\n"
5184 printf("-------------------\n"); 5191 "Built-in commands:\n"
5192 "------------------\n");
5185 for (x = bltins; x != &bltins[ARRAY_SIZE(bltins)]; x++) { 5193 for (x = bltins; x != &bltins[ARRAY_SIZE(bltins)]; x++) {
5186 printf("%s\t%s\n", x->cmd, x->descr); 5194 printf("%s\t%s\n", x->cmd, x->descr);
5187 } 5195 }
diff --git a/shell/lash_unused.c b/shell/lash_unused.c
index 90b1f56cf..21ea5471b 100644
--- a/shell/lash_unused.c
+++ b/shell/lash_unused.c
@@ -312,8 +312,9 @@ static int builtin_help(struct child_prog UNUSED_PARAM *dummy)
312{ 312{
313 const struct built_in_command *x; 313 const struct built_in_command *x;
314 314
315 printf("\nBuilt-in commands:\n" 315 printf("\n"
316 "-------------------\n"); 316 "Built-in commands:\n"
317 "------------------\n");
317 for (x = bltins; x <= &VEC_LAST(bltins); x++) { 318 for (x = bltins; x <= &VEC_LAST(bltins); x++) {
318 if (x->descr == NULL) 319 if (x->descr == NULL)
319 continue; 320 continue;
diff --git a/shell/msh.c b/shell/msh.c
index 5f8c90ef6..da1dc3576 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -35,7 +35,6 @@
35# include <assert.h> 35# include <assert.h>
36# define bb_dev_null "/dev/null" 36# define bb_dev_null "/dev/null"
37# define DEFAULT_SHELL "/proc/self/exe" 37# define DEFAULT_SHELL "/proc/self/exe"
38# define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"
39# define bb_banner "busybox standalone" 38# define bb_banner "busybox standalone"
40# define ENABLE_FEATURE_SH_STANDALONE 0 39# define ENABLE_FEATURE_SH_STANDALONE 0
41# define bb_msg_memory_exhausted "memory exhausted" 40# define bb_msg_memory_exhausted "memory exhausted"
@@ -3176,8 +3175,9 @@ static int dohelp(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM)
3176 int col; 3175 int col;
3177 const struct builtincmd *x; 3176 const struct builtincmd *x;
3178 3177
3179 puts("\nBuilt-in commands:\n" 3178 printf("\n"
3180 "-------------------"); 3179 "Built-in commands:\n"
3180 "------------------\n");
3181 3181
3182 col = 0; 3182 col = 0;
3183 x = builtincmds; 3183 x = builtincmds;