mirror of
https://github.com/sheumann/hush.git
synced 2024-12-22 14:30:31 +00:00
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:
parent
ef1b439669
commit
bc56974062
141
shell/hush.c
141
shell/hush.c
@ -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':
|
||||
|
Loading…
Reference in New Issue
Block a user