diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-12 20:35:19 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-12 20:35:19 +0000 |
| commit | bc5697406270bb94b8d33d8b61d15373bd6e10ae (patch) | |
| tree | c89e518f6376db96d55e4590e78300c90e929687 /shell | |
| parent | ef1b439669f7f952633eea3879defb357224eb4c (diff) | |
| download | busybox-w32-bc5697406270bb94b8d33d8b61d15373bd6e10ae.tar.gz busybox-w32-bc5697406270bb94b8d33d8b61d15373bd6e10ae.tar.bz2 busybox-w32-bc5697406270bb94b8d33d8b61d15373bd6e10ae.zip | |
hush: pass functions to child shells on NOMMU
function old new delta
new_function - 123 +123
hush_main 1198 1262 +64
re_execute_shell 341 387 +46
run_pipe 1872 1790 -82
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/1 up/down: 233/-82) Total: 151 bytes
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 141 |
1 files changed, 98 insertions, 43 deletions
diff --git a/shell/hush.c b/shell/hush.c index 16a4d73e7..9c2c0f324 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -2322,6 +2322,9 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) | |||
| 2322 | char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4]; | 2322 | char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4]; |
| 2323 | char *heredoc_argv[4]; | 2323 | char *heredoc_argv[4]; |
| 2324 | struct variable *cur; | 2324 | struct variable *cur; |
| 2325 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2326 | struct function *funcp; | ||
| 2327 | #endif | ||
| 2325 | char **argv, **pp; | 2328 | char **argv, **pp; |
| 2326 | unsigned cnt; | 2329 | unsigned cnt; |
| 2327 | 2330 | ||
| @@ -2341,7 +2344,7 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) | |||
| 2341 | , (unsigned) G.last_exitcode | 2344 | , (unsigned) G.last_exitcode |
| 2342 | USE_HUSH_LOOPS(, G.depth_of_loop) | 2345 | USE_HUSH_LOOPS(, G.depth_of_loop) |
| 2343 | ); | 2346 | ); |
| 2344 | /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...> | 2347 | /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...> <funcs...> |
| 2345 | * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL | 2348 | * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL |
| 2346 | */ | 2349 | */ |
| 2347 | cnt = 6; | 2350 | cnt = 6; |
| @@ -2349,6 +2352,10 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) | |||
| 2349 | if (!cur->flg_export || cur->flg_read_only) | 2352 | if (!cur->flg_export || cur->flg_read_only) |
| 2350 | cnt += 2; | 2353 | cnt += 2; |
| 2351 | } | 2354 | } |
| 2355 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2356 | for (funcp = G.top_func; funcp; funcp = funcp->next) | ||
| 2357 | cnt += 3; | ||
| 2358 | #endif | ||
| 2352 | pp = g_argv; | 2359 | pp = g_argv; |
| 2353 | while (*pp++) | 2360 | while (*pp++) |
| 2354 | cnt++; | 2361 | cnt++; |
| @@ -2366,7 +2373,13 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) | |||
| 2366 | *pp++ = cur->varstr; | 2373 | *pp++ = cur->varstr; |
| 2367 | } | 2374 | } |
| 2368 | } | 2375 | } |
| 2369 | //TODO: pass functions | 2376 | #if ENABLE_HUSH_FUNCTIONS |
| 2377 | for (funcp = G.top_func; funcp; funcp = funcp->next) { | ||
| 2378 | *pp++ = (char *) "-F"; | ||
| 2379 | *pp++ = funcp->name; | ||
| 2380 | *pp++ = funcp->body_as_string; | ||
| 2381 | } | ||
| 2382 | #endif | ||
| 2370 | /* We can pass activated traps here. Say, -Tnn:trap_string | 2383 | /* We can pass activated traps here. Say, -Tnn:trap_string |
| 2371 | * | 2384 | * |
| 2372 | * However, POSIX says that subshells reset signals with traps | 2385 | * However, POSIX says that subshells reset signals with traps |
| @@ -2649,6 +2662,15 @@ static void free_pipe_list(struct pipe *head) | |||
| 2649 | 2662 | ||
| 2650 | 2663 | ||
| 2651 | static int run_list(struct pipe *pi); | 2664 | static int run_list(struct pipe *pi); |
| 2665 | #if BB_MMU | ||
| 2666 | #define parse_stream(pstring, input, end_trigger) \ | ||
| 2667 | parse_stream(input, end_trigger) | ||
| 2668 | #endif | ||
| 2669 | static struct pipe *parse_stream(char **pstring, | ||
| 2670 | struct in_str *input, | ||
| 2671 | int end_trigger); | ||
| 2672 | static void parse_and_run_string(const char *s); | ||
| 2673 | |||
| 2652 | 2674 | ||
| 2653 | static const struct built_in_command* find_builtin(const char *name) | 2675 | static const struct built_in_command* find_builtin(const char *name) |
| 2654 | { | 2676 | { |
| @@ -2676,6 +2698,52 @@ static const struct function *find_function(const char *name) | |||
| 2676 | return funcp; | 2698 | return funcp; |
| 2677 | } | 2699 | } |
| 2678 | 2700 | ||
| 2701 | /* Note: takes ownership on name ptr */ | ||
| 2702 | static struct function *new_function(char *name) | ||
| 2703 | { | ||
| 2704 | struct function *funcp; | ||
| 2705 | struct function **funcpp = &G.top_func; | ||
| 2706 | |||
| 2707 | while ((funcp = *funcpp) != NULL) { | ||
| 2708 | struct command *cmd; | ||
| 2709 | |||
| 2710 | if (strcmp(funcp->name, name) != 0) { | ||
| 2711 | funcpp = &funcp->next; | ||
| 2712 | continue; | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | cmd = funcp->parent_cmd; | ||
| 2716 | debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd); | ||
| 2717 | if (!cmd) { | ||
| 2718 | debug_printf_exec("freeing & replacing function '%s'\n", funcp->name); | ||
| 2719 | free(funcp->name); | ||
| 2720 | /* Note: if !funcp->body, do not free body_as_string! | ||
| 2721 | * This is a special case of "-F name body" function: | ||
| 2722 | * body_as_string was not malloced! */ | ||
| 2723 | if (funcp->body) { | ||
| 2724 | free_pipe_list(funcp->body); | ||
| 2725 | #if !BB_MMU | ||
| 2726 | free(funcp->body_as_string); | ||
| 2727 | #endif | ||
| 2728 | } | ||
| 2729 | } else { | ||
| 2730 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); | ||
| 2731 | cmd->argv[0] = funcp->name; | ||
| 2732 | cmd->group = funcp->body; | ||
| 2733 | #if !BB_MMU | ||
| 2734 | cmd->group_as_string = funcp->body_as_string; | ||
| 2735 | #endif | ||
| 2736 | } | ||
| 2737 | goto skip; | ||
| 2738 | } | ||
| 2739 | debug_printf_exec("remembering new function '%s'\n", command->argv[0]); | ||
| 2740 | funcp = *funcpp = xzalloc(sizeof(*funcp)); | ||
| 2741 | /*funcp->next = NULL;*/ | ||
| 2742 | skip: | ||
| 2743 | funcp->name = name; | ||
| 2744 | return funcp; | ||
| 2745 | } | ||
| 2746 | |||
| 2679 | static void exec_function(const struct function *funcp, char **argv) NORETURN; | 2747 | static void exec_function(const struct function *funcp, char **argv) NORETURN; |
| 2680 | static void exec_function(const struct function *funcp, char **argv) | 2748 | static void exec_function(const struct function *funcp, char **argv) |
| 2681 | { | 2749 | { |
| @@ -2687,6 +2755,7 @@ static void exec_function(const struct function *funcp, char **argv) | |||
| 2687 | while (*++argv) | 2755 | while (*++argv) |
| 2688 | n++; | 2756 | n++; |
| 2689 | G.global_argc = n; | 2757 | G.global_argc = n; |
| 2758 | /* On MMU, funcp->body is always non-NULL */ | ||
| 2690 | n = run_list(funcp->body); | 2759 | n = run_list(funcp->body); |
| 2691 | fflush(NULL); | 2760 | fflush(NULL); |
| 2692 | _exit(n); | 2761 | _exit(n); |
| @@ -2719,7 +2788,17 @@ static int run_function(const struct function *funcp, char **argv) | |||
| 2719 | G.global_argc = n; | 2788 | G.global_argc = n; |
| 2720 | G.global_argv = argv; | 2789 | G.global_argv = argv; |
| 2721 | 2790 | ||
| 2722 | n = run_list(funcp->body); | 2791 | /* On MMU, funcp->body is always non-NULL */ |
| 2792 | #if !BB_MMU | ||
| 2793 | if (!funcp->body) { | ||
| 2794 | /* Function defined by -F */ | ||
| 2795 | parse_and_run_string(funcp->body_as_string); | ||
| 2796 | n = G.last_exitcode; | ||
| 2797 | } else | ||
| 2798 | #endif | ||
| 2799 | { | ||
| 2800 | n = run_list(funcp->body); | ||
| 2801 | } | ||
| 2723 | 2802 | ||
| 2724 | if (G.global_args_malloced) { | 2803 | if (G.global_args_malloced) { |
| 2725 | /* function ran "set -- arg1 arg2 ..." */ | 2804 | /* function ran "set -- arg1 arg2 ..." */ |
| @@ -3201,37 +3280,9 @@ static int run_pipe(struct pipe *pi) | |||
| 3201 | if (command->grp_type == GRP_FUNCTION) { | 3280 | if (command->grp_type == GRP_FUNCTION) { |
| 3202 | /* "executing" func () { list } */ | 3281 | /* "executing" func () { list } */ |
| 3203 | struct function *funcp; | 3282 | struct function *funcp; |
| 3204 | struct function **funcpp = &G.top_func; | ||
| 3205 | |||
| 3206 | while ((funcp = *funcpp) != NULL) { | ||
| 3207 | if (strcmp(funcp->name, command->argv[0]) == 0) { | ||
| 3208 | struct command *cmd = funcp->parent_cmd; | ||
| 3209 | 3283 | ||
| 3210 | debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd); | 3284 | funcp = new_function(command->argv[0]); |
| 3211 | if (!cmd) { | 3285 | /* funcp->name is already set to argv[0] */ |
| 3212 | debug_printf_exec("freeing & replacing function '%s'\n", funcp->name); | ||
| 3213 | free(funcp->name); | ||
| 3214 | free_pipe_list(funcp->body); | ||
| 3215 | #if !BB_MMU | ||
| 3216 | free(funcp->body_as_string); | ||
| 3217 | #endif | ||
| 3218 | } else { | ||
| 3219 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); | ||
| 3220 | cmd->argv[0] = funcp->name; | ||
| 3221 | cmd->group = funcp->body; | ||
| 3222 | #if !BB_MMU | ||
| 3223 | cmd->group_as_string = funcp->body_as_string; | ||
| 3224 | #endif | ||
| 3225 | } | ||
| 3226 | goto skip; | ||
| 3227 | } | ||
| 3228 | funcpp = &funcp->next; | ||
| 3229 | } | ||
| 3230 | debug_printf_exec("remembering new function '%s'\n", command->argv[0]); | ||
| 3231 | funcp = *funcpp = xzalloc(sizeof(*funcp)); | ||
| 3232 | /*funcp->next = NULL;*/ | ||
| 3233 | skip: | ||
| 3234 | funcp->name = command->argv[0]; | ||
| 3235 | funcp->body = command->group; | 3286 | funcp->body = command->group; |
| 3236 | #if !BB_MMU | 3287 | #if !BB_MMU |
| 3237 | funcp->body_as_string = command->group_as_string; | 3288 | funcp->body_as_string = command->group_as_string; |
| @@ -4599,15 +4650,6 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
| 4599 | } | 4650 | } |
| 4600 | 4651 | ||
| 4601 | 4652 | ||
| 4602 | #if BB_MMU | ||
| 4603 | #define parse_stream(pstring, input, end_trigger) \ | ||
| 4604 | parse_stream(input, end_trigger) | ||
| 4605 | #endif | ||
| 4606 | static struct pipe *parse_stream(char **pstring, | ||
| 4607 | struct in_str *input, | ||
| 4608 | int end_trigger); | ||
| 4609 | static void parse_and_run_string(const char *s); | ||
| 4610 | |||
| 4611 | #if ENABLE_HUSH_TICK | 4653 | #if ENABLE_HUSH_TICK |
| 4612 | static FILE *generate_stream_from_string(const char *s) | 4654 | static FILE *generate_stream_from_string(const char *s) |
| 4613 | { | 4655 | { |
| @@ -5866,7 +5908,10 @@ int hush_main(int argc, char **argv) | |||
| 5866 | while (1) { | 5908 | while (1) { |
| 5867 | opt = getopt(argc, argv, "c:xins" | 5909 | opt = getopt(argc, argv, "c:xins" |
| 5868 | #if !BB_MMU | 5910 | #if !BB_MMU |
| 5869 | "<:$:!:?:D:R:V:" | 5911 | "<:$:R:V:" |
| 5912 | # if ENABLE_HUSH_FUNCTIONS | ||
| 5913 | "F:" | ||
| 5914 | # endif | ||
| 5870 | #endif | 5915 | #endif |
| 5871 | ); | 5916 | ); |
| 5872 | if (opt <= 0) | 5917 | if (opt <= 0) |
| @@ -5913,6 +5958,16 @@ int hush_main(int argc, char **argv) | |||
| 5913 | case 'V': | 5958 | case 'V': |
| 5914 | set_local_var(xstrdup(optarg), 0, opt == 'R'); | 5959 | set_local_var(xstrdup(optarg), 0, opt == 'R'); |
| 5915 | break; | 5960 | break; |
| 5961 | # if ENABLE_HUSH_FUNCTIONS | ||
| 5962 | case 'F': { | ||
| 5963 | struct function *funcp = new_function(optarg); | ||
| 5964 | /* funcp->name is already set to optarg */ | ||
| 5965 | /* funcp->body is set to NULL. It's a special case. */ | ||
| 5966 | funcp->body_as_string = argv[optind]; | ||
| 5967 | optind++; | ||
| 5968 | break; | ||
| 5969 | } | ||
| 5970 | # endif | ||
| 5916 | #endif | 5971 | #endif |
| 5917 | case 'n': | 5972 | case 'n': |
| 5918 | case 'x': | 5973 | case 'x': |
