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': |