aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c111
1 files changed, 53 insertions, 58 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 54aee882e..ae2876ac7 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1344,11 +1344,14 @@ static void hush_exit(int exitcode)
/* Prevent recursion:
* trap "echo Hi; exit" EXIT; exit
*/
- char *argv[] = { NULL, G.traps[0], NULL };
+ char *argv[3];
+ /* argv[0] is unused */
+ argv[1] = G.traps[0];
+ argv[2] = NULL;
G.traps[0] = NULL;
G.exiting = 1;
builtin_eval(argv);
- free(argv[1]);
+ /* free(argv[1]); - why bother */
}
#if ENABLE_HUSH_JOB
@@ -1376,10 +1379,12 @@ static int check_and_run_traps(int sig)
if (G.traps && G.traps[sig]) {
if (G.traps[sig][0]) {
/* We have user-defined handler */
- char *argv[] = { NULL, xstrdup(G.traps[sig]), NULL };
+ char *argv[3];
+ /* argv[0] is unused */
+ argv[1] = G.traps[sig];
+ argv[2] = NULL;
save_rcode = G.last_exitcode;
builtin_eval(argv);
- free(argv[1]);
G.last_exitcode = save_rcode;
} /* else: "" trap, ignoring signal */
continue;
@@ -1439,13 +1444,11 @@ static const char *get_cwd(int force)
/*
* Shell and environment variable support
*/
-static struct variable **get_ptr_to_local_var(const char *name)
+static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
{
struct variable **pp;
struct variable *cur;
- int len;
- len = strlen(name);
pp = &G.top_var;
while ((cur = *pp) != NULL) {
if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
@@ -1455,21 +1458,13 @@ static struct variable **get_ptr_to_local_var(const char *name)
return NULL;
}
-static struct variable *get_local_var(const char *name)
-{
- struct variable **pp = get_ptr_to_local_var(name);
- if (pp)
- return *pp;
- return NULL;
-}
-
static const char* FAST_FUNC get_local_var_value(const char *name)
{
struct variable **vpp;
+ unsigned len = strlen(name);
if (G.expanded_assignments) {
char **cpp = G.expanded_assignments;
- int len = strlen(name);
while (*cpp) {
char *cp = *cpp;
if (strncmp(cp, name, len) == 0 && cp[len] == '=')
@@ -1478,17 +1473,16 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
}
}
- vpp = get_ptr_to_local_var(name);
+ vpp = get_ptr_to_local_var(name, len);
if (vpp)
- return strchr((*vpp)->varstr, '=') + 1;
+ return (*vpp)->varstr + len + 1;
if (strcmp(name, "PPID") == 0)
return utoa(G.root_ppid);
// bash compat: UID? EUID?
#if ENABLE_HUSH_RANDOM_SUPPORT
- if (strcmp(name, "RANDOM") == 0) {
+ if (strcmp(name, "RANDOM") == 0)
return utoa(next_random(&G.random_gen));
- }
#endif
return NULL;
}
@@ -1738,9 +1732,7 @@ static struct variable *set_vars_and_save_old(char **strings)
eq = strchr(*s, '=');
if (eq) {
- *eq = '\0';
- var_pp = get_ptr_to_local_var(*s);
- *eq = '=';
+ var_pp = get_ptr_to_local_var(*s, eq - *s);
if (var_pp) {
/* Remove variable from global linked list */
var_p = *var_pp;
@@ -2500,33 +2492,36 @@ static char **o_finalize_list(o_string *o, int n)
list[--n] = NULL;
while (n) {
n--;
- list[n] = o->data + (int)(ptrdiff_t)list[n] + string_start;
+ list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
}
return list;
}
-static void free_pipe_list(struct pipe *head);
+static void free_pipe_list(struct pipe *pi);
-/* Return code is the exit status of the pipe */
-static void free_pipe(struct pipe *pi)
+/* Returns pi->next - next pipe in the list */
+static struct pipe *free_pipe(struct pipe *pi)
{
- char **p;
- struct command *command;
- struct redir_struct *r, *rnext;
- int a, i;
+ struct pipe *next;
+ int i;
- if (pi->stopped_cmds > 0) /* why? */
- return;
- debug_printf_clean("run pipe: (pid %d)\n", getpid());
+ debug_printf_clean("free_pipe (pid %d)\n", getpid());
for (i = 0; i < pi->num_cmds; i++) {
+ struct command *command;
+ struct redir_struct *r, *rnext;
+
command = &pi->cmds[i];
debug_printf_clean(" command %d:\n", i);
if (command->argv) {
- for (a = 0, p = command->argv; *p; a++, p++) {
- debug_printf_clean(" argv[%d] = %s\n", a, *p);
+ if (DEBUG_CLEAN) {
+ int a;
+ char **p;
+ for (a = 0, p = command->argv; *p; a++, p++) {
+ debug_printf_clean(" argv[%d] = %s\n", a, *p);
+ }
}
free_strings(command->argv);
- command->argv = NULL;
+ //command->argv = NULL;
}
/* not "else if": on syntax error, we may have both! */
if (command->group) {
@@ -2534,7 +2529,7 @@ static void free_pipe(struct pipe *pi)
command->cmd_type);
free_pipe_list(command->group);
debug_printf_clean(" end group\n");
- command->group = NULL;
+ //command->group = NULL;
}
/* else is crucial here.
* If group != NULL, child_func is meaningless */
@@ -2546,7 +2541,7 @@ static void free_pipe(struct pipe *pi)
#endif
#if !BB_MMU
free(command->group_as_string);
- command->group_as_string = NULL;
+ //command->group_as_string = NULL;
#endif
for (r = command->redirects; r; r = rnext) {
debug_printf_clean(" redirect %d%s",
@@ -2555,35 +2550,34 @@ static void free_pipe(struct pipe *pi)
if (r->rd_filename) {
debug_printf_clean(" fname:'%s'\n", r->rd_filename);
free(r->rd_filename);
- r->rd_filename = NULL;
+ //r->rd_filename = NULL;
}
debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
rnext = r->next;
free(r);
}
- command->redirects = NULL;
+ //command->redirects = NULL;
}
free(pi->cmds); /* children are an array, they get freed all at once */
- pi->cmds = NULL;
+ //pi->cmds = NULL;
#if ENABLE_HUSH_JOB
free(pi->cmdtext);
- pi->cmdtext = NULL;
+ //pi->cmdtext = NULL;
#endif
+
+ next = pi->next;
+ free(pi);
+ return next;
}
-static void free_pipe_list(struct pipe *head)
+static void free_pipe_list(struct pipe *pi)
{
- struct pipe *pi, *next;
-
- for (pi = head; pi; pi = next) {
+ while (pi) {
#if HAS_KEYWORDS
- debug_printf_clean(" pipe reserved word %d\n", pi->res_word);
+ debug_printf_clean("pipe reserved word %d\n", pi->res_word);
#endif
- free_pipe(pi);
debug_printf_clean("pipe followup code %d\n", pi->followup);
- next = pi->next;
- /*pi->next = NULL;*/
- free(pi);
+ pi = free_pipe(pi);
}
}
@@ -6184,15 +6178,13 @@ static void remove_bg_job(struct pipe *pi)
static void delete_finished_bg_job(struct pipe *pi)
{
remove_bg_job(pi);
- pi->stopped_cmds = 0;
free_pipe(pi);
- free(pi);
}
#endif /* JOB */
/* Check to see if any processes have exited -- if they
* have, figure out why and see if a job has completed */
-static int checkjobs(struct pipe* fg_pipe)
+static int checkjobs(struct pipe *fg_pipe)
{
int attributes;
int status;
@@ -7879,13 +7871,16 @@ static void helper_export_local(char **argv, int exp, int lvl)
{
do {
char *name = *argv;
+ char *name_end = strchrnul(name, '=');
/* So far we do not check that name is valid (TODO?) */
- if (strchr(name, '=') == NULL) {
- struct variable *var;
+ if (*name_end == '\0') {
+ struct variable *var, **vpp;
+
+ vpp = get_ptr_to_local_var(name, name_end - name);
+ var = vpp ? *vpp : NULL;
- var = get_local_var(name);
if (exp == -1) { /* unexporting? */
/* export -n NAME (without =VALUE) */
if (var) {