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
This commit is contained in:
Denis Vlasenko 2009-04-12 20:35:19 +00:00
parent ef1b439669
commit bc56974062

View File

@ -2322,6 +2322,9 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv)
char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4];
char *heredoc_argv[4];
struct variable *cur;
#if ENABLE_HUSH_FUNCTIONS
struct function *funcp;
#endif
char **argv, **pp;
unsigned cnt;
@ -2341,7 +2344,7 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv)
, (unsigned) G.last_exitcode
USE_HUSH_LOOPS(, G.depth_of_loop)
);
/* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...>
/* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...> <funcs...>
* 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
*/
cnt = 6;
@ -2349,6 +2352,10 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv)
if (!cur->flg_export || cur->flg_read_only)
cnt += 2;
}
#if ENABLE_HUSH_FUNCTIONS
for (funcp = G.top_func; funcp; funcp = funcp->next)
cnt += 3;
#endif
pp = g_argv;
while (*pp++)
cnt++;
@ -2366,7 +2373,13 @@ static void re_execute_shell(const char *s, char *g_argv0, char **g_argv)
*pp++ = cur->varstr;
}
}
//TODO: pass functions
#if ENABLE_HUSH_FUNCTIONS
for (funcp = G.top_func; funcp; funcp = funcp->next) {
*pp++ = (char *) "-F";
*pp++ = funcp->name;
*pp++ = funcp->body_as_string;
}
#endif
/* We can pass activated traps here. Say, -Tnn:trap_string
*
* However, POSIX says that subshells reset signals with traps
@ -2649,6 +2662,15 @@ static void free_pipe_list(struct pipe *head)
static int run_list(struct pipe *pi);
#if BB_MMU
#define parse_stream(pstring, input, end_trigger) \
parse_stream(input, end_trigger)
#endif
static struct pipe *parse_stream(char **pstring,
struct in_str *input,
int end_trigger);
static void parse_and_run_string(const char *s);
static const struct built_in_command* find_builtin(const char *name)
{
@ -2676,6 +2698,52 @@ static const struct function *find_function(const char *name)
return funcp;
}
/* Note: takes ownership on name ptr */
static struct function *new_function(char *name)
{
struct function *funcp;
struct function **funcpp = &G.top_func;
while ((funcp = *funcpp) != NULL) {
struct command *cmd;
if (strcmp(funcp->name, name) != 0) {
funcpp = &funcp->next;
continue;
}
cmd = funcp->parent_cmd;
debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
if (!cmd) {
debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
free(funcp->name);
/* Note: if !funcp->body, do not free body_as_string!
* This is a special case of "-F name body" function:
* body_as_string was not malloced! */
if (funcp->body) {
free_pipe_list(funcp->body);
#if !BB_MMU
free(funcp->body_as_string);
#endif
}
} else {
debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
cmd->argv[0] = funcp->name;
cmd->group = funcp->body;
#if !BB_MMU
cmd->group_as_string = funcp->body_as_string;
#endif
}
goto skip;
}
debug_printf_exec("remembering new function '%s'\n", command->argv[0]);
funcp = *funcpp = xzalloc(sizeof(*funcp));
/*funcp->next = NULL;*/
skip:
funcp->name = name;
return funcp;
}
static void exec_function(const struct function *funcp, char **argv) NORETURN;
static void exec_function(const struct function *funcp, char **argv)
{
@ -2687,6 +2755,7 @@ static void exec_function(const struct function *funcp, char **argv)
while (*++argv)
n++;
G.global_argc = n;
/* On MMU, funcp->body is always non-NULL */
n = run_list(funcp->body);
fflush(NULL);
_exit(n);
@ -2719,7 +2788,17 @@ static int run_function(const struct function *funcp, char **argv)
G.global_argc = n;
G.global_argv = argv;
n = run_list(funcp->body);
/* On MMU, funcp->body is always non-NULL */
#if !BB_MMU
if (!funcp->body) {
/* Function defined by -F */
parse_and_run_string(funcp->body_as_string);
n = G.last_exitcode;
} else
#endif
{
n = run_list(funcp->body);
}
if (G.global_args_malloced) {
/* function ran "set -- arg1 arg2 ..." */
@ -3201,37 +3280,9 @@ static int run_pipe(struct pipe *pi)
if (command->grp_type == GRP_FUNCTION) {
/* "executing" func () { list } */
struct function *funcp;
struct function **funcpp = &G.top_func;
while ((funcp = *funcpp) != NULL) {
if (strcmp(funcp->name, command->argv[0]) == 0) {
struct command *cmd = funcp->parent_cmd;
debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
if (!cmd) {
debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
free(funcp->name);
free_pipe_list(funcp->body);
#if !BB_MMU
free(funcp->body_as_string);
#endif
} else {
debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
cmd->argv[0] = funcp->name;
cmd->group = funcp->body;
#if !BB_MMU
cmd->group_as_string = funcp->body_as_string;
#endif
}
goto skip;
}
funcpp = &funcp->next;
}
debug_printf_exec("remembering new function '%s'\n", command->argv[0]);
funcp = *funcpp = xzalloc(sizeof(*funcp));
/*funcp->next = NULL;*/
skip:
funcp->name = command->argv[0];
funcp = new_function(command->argv[0]);
/* funcp->name is already set to argv[0] */
funcp->body = command->group;
#if !BB_MMU
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_
}
#if BB_MMU
#define parse_stream(pstring, input, end_trigger) \
parse_stream(input, end_trigger)
#endif
static struct pipe *parse_stream(char **pstring,
struct in_str *input,
int end_trigger);
static void parse_and_run_string(const char *s);
#if ENABLE_HUSH_TICK
static FILE *generate_stream_from_string(const char *s)
{
@ -5866,7 +5908,10 @@ int hush_main(int argc, char **argv)
while (1) {
opt = getopt(argc, argv, "c:xins"
#if !BB_MMU
"<:$:!:?:D:R:V:"
"<:$:R:V:"
# if ENABLE_HUSH_FUNCTIONS
"F:"
# endif
#endif
);
if (opt <= 0)
@ -5913,6 +5958,16 @@ int hush_main(int argc, char **argv)
case 'V':
set_local_var(xstrdup(optarg), 0, opt == 'R');
break;
# if ENABLE_HUSH_FUNCTIONS
case 'F': {
struct function *funcp = new_function(optarg);
/* funcp->name is already set to optarg */
/* funcp->body is set to NULL. It's a special case. */
funcp->body_as_string = argv[optind];
optind++;
break;
}
# endif
#endif
case 'n':
case 'x':