aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-12 20:35:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-12 20:35:19 +0000
commitbc5697406270bb94b8d33d8b61d15373bd6e10ae (patch)
treec89e518f6376db96d55e4590e78300c90e929687 /shell
parentef1b439669f7f952633eea3879defb357224eb4c (diff)
downloadbusybox-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.c141
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
2651static int run_list(struct pipe *pi); 2664static 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
2669static struct pipe *parse_stream(char **pstring,
2670 struct in_str *input,
2671 int end_trigger);
2672static void parse_and_run_string(const char *s);
2673
2652 2674
2653static const struct built_in_command* find_builtin(const char *name) 2675static 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 */
2702static 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
2679static void exec_function(const struct function *funcp, char **argv) NORETURN; 2747static void exec_function(const struct function *funcp, char **argv) NORETURN;
2680static void exec_function(const struct function *funcp, char **argv) 2748static 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
4606static struct pipe *parse_stream(char **pstring,
4607 struct in_str *input,
4608 int end_trigger);
4609static void parse_and_run_string(const char *s);
4610
4611#if ENABLE_HUSH_TICK 4653#if ENABLE_HUSH_TICK
4612static FILE *generate_stream_from_string(const char *s) 4654static 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':