summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen2001-05-22 21:37:48 +0000
committerEric Andersen2001-05-22 21:37:48 +0000
commit9978576f15b5bc1a60543e24722584b36b574933 (patch)
treec1251e440e1546b0ab892c2f6b1974aa639beaea
parentaeb44c4da620cd4ec1c4f1e4f15fb227ec4dc8dc (diff)
downloadbusybox-9978576f15b5bc1a60543e24722584b36b574933.zip
busybox-9978576f15b5bc1a60543e24722584b36b574933.tar.gz
Fix this case. No, really this time.
unset FOO export FOO=bar FOO=baz echo "global env: " `env | grep ^FOO` echo "local env: " `set | grep ^FOO` -Erik
-rw-r--r--hush.c107
-rw-r--r--shell/hush.c107
2 files changed, 122 insertions, 92 deletions
diff --git a/hush.c b/hush.c
index a26e2f6..f995f6f 100644
--- a/hush.c
+++ b/hush.c
@@ -1243,8 +1243,10 @@ static void checkjobs()
break;
}
- if(pi==NULL)
- return;
+ if(pi==NULL) {
+ debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
+ continue;
+ }
if (WIFEXITED(status) || WIFSIGNALED(status)) {
/* child exited */
@@ -1352,7 +1354,24 @@ static int run_pipe_real(struct pipe *pi)
if (i!=0 && child->argv[i]==NULL) {
/* assignments, but no command: set the local environment */
for (i=0; child->argv[i]!=NULL; i++) {
- set_local_var(child->argv[i], 0);
+
+ /* Ok, this case is tricky. We have to decide if this is a
+ * local variable, or an already exported variable. If it is
+ * already exported, we have to export the new value. If it is
+ * not exported, we need only set this as a local variable.
+ * This junk is all to decide whether or not to export this
+ * variable. */
+ int export_me=0;
+ char *name, *value;
+ name = strdup(child->argv[i]);
+ value = strchr(name, '=');
+ if (value)
+ *value=0;
+ if ( get_local_var(name)) {
+ export_me=1;
+ }
+ free(name);
+ set_local_var(child->argv[i], export_me);
}
return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */
}
@@ -1704,7 +1723,6 @@ static int set_local_var(const char *s, int flg_export)
char *name, *value;
int result=0;
struct variables *cur;
- char *newval = 0;
name=strdup(s);
@@ -1712,55 +1730,52 @@ static int set_local_var(const char *s, int flg_export)
* NAME=VALUE format. So the first order of business is to
* split 's' on the '=' into 'name' and 'value' */
value = strchr(name, '=');
- if (value==0 || (newval = strdup(value+1))==0) {
- result = -1;
- } else {
- *value++ = 0;
+ if (value==0 && ++value==0) {
+ free(name);
+ return -1;
+ }
+ *value++ = 0;
- for(cur = top_vars; cur; cur = cur->next) {
- if(strcmp(cur->name, name)==0)
- break;
- }
+ for(cur = top_vars; cur; cur = cur->next) {
+ if(strcmp(cur->name, name)==0)
+ break;
+ }
- if(cur) {
- if(strcmp(cur->value, value)==0) {
- if(flg_export>0 && cur->flg_export==0)
- cur->flg_export=flg_export;
- else
- result++;
- free(newval);
+ if(cur) {
+ if(strcmp(cur->value, value)==0) {
+ if(flg_export>0 && cur->flg_export==0)
+ cur->flg_export=flg_export;
+ else
+ result++;
+ } else {
+ if(cur->flg_read_only) {
+ error_msg("%s: readonly variable", name);
+ result = -1;
} else {
- if(cur->flg_read_only) {
- error_msg("%s: readonly variable", name);
- free(newval);
- result = -1;
- } else {
- if(flg_export>0 || cur->flg_export>1)
- cur->flg_export=1;
- free(cur->value);
- cur->value = newval;
- }
+ if(flg_export>0 || cur->flg_export>1)
+ cur->flg_export=1;
+ free(cur->value);
+
+ cur->value = strdup(value);
}
+ }
+ } else {
+ cur = malloc(sizeof(struct variables));
+ if(!cur) {
+ result = -1;
} else {
- cur = malloc(sizeof(struct variables));
- if(cur==0) {
- free(newval);
+ cur->name = strdup(name);
+ if(cur->name == 0) {
+ free(cur);
result = -1;
} else {
- cur->name = strdup(name);
- if(cur->name == 0) {
- free(cur);
- free(newval);
- result = -1;
- } else {
- struct variables *bottom = top_vars;
- cur->value = newval;
- cur->next = 0;
- cur->flg_export = flg_export;
- cur->flg_read_only = 0;
- while(bottom->next) bottom=bottom->next;
- bottom->next = cur;
- }
+ struct variables *bottom = top_vars;
+ cur->value = strdup(value);
+ cur->next = 0;
+ cur->flg_export = flg_export;
+ cur->flg_read_only = 0;
+ while(bottom->next) bottom=bottom->next;
+ bottom->next = cur;
}
}
}
diff --git a/shell/hush.c b/shell/hush.c
index a26e2f6..f995f6f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1243,8 +1243,10 @@ static void checkjobs()
break;
}
- if(pi==NULL)
- return;
+ if(pi==NULL) {
+ debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
+ continue;
+ }
if (WIFEXITED(status) || WIFSIGNALED(status)) {
/* child exited */
@@ -1352,7 +1354,24 @@ static int run_pipe_real(struct pipe *pi)
if (i!=0 && child->argv[i]==NULL) {
/* assignments, but no command: set the local environment */
for (i=0; child->argv[i]!=NULL; i++) {
- set_local_var(child->argv[i], 0);
+
+ /* Ok, this case is tricky. We have to decide if this is a
+ * local variable, or an already exported variable. If it is
+ * already exported, we have to export the new value. If it is
+ * not exported, we need only set this as a local variable.
+ * This junk is all to decide whether or not to export this
+ * variable. */
+ int export_me=0;
+ char *name, *value;
+ name = strdup(child->argv[i]);
+ value = strchr(name, '=');
+ if (value)
+ *value=0;
+ if ( get_local_var(name)) {
+ export_me=1;
+ }
+ free(name);
+ set_local_var(child->argv[i], export_me);
}
return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */
}
@@ -1704,7 +1723,6 @@ static int set_local_var(const char *s, int flg_export)
char *name, *value;
int result=0;
struct variables *cur;
- char *newval = 0;
name=strdup(s);
@@ -1712,55 +1730,52 @@ static int set_local_var(const char *s, int flg_export)
* NAME=VALUE format. So the first order of business is to
* split 's' on the '=' into 'name' and 'value' */
value = strchr(name, '=');
- if (value==0 || (newval = strdup(value+1))==0) {
- result = -1;
- } else {
- *value++ = 0;
+ if (value==0 && ++value==0) {
+ free(name);
+ return -1;
+ }
+ *value++ = 0;
- for(cur = top_vars; cur; cur = cur->next) {
- if(strcmp(cur->name, name)==0)
- break;
- }
+ for(cur = top_vars; cur; cur = cur->next) {
+ if(strcmp(cur->name, name)==0)
+ break;
+ }
- if(cur) {
- if(strcmp(cur->value, value)==0) {
- if(flg_export>0 && cur->flg_export==0)
- cur->flg_export=flg_export;
- else
- result++;
- free(newval);
+ if(cur) {
+ if(strcmp(cur->value, value)==0) {
+ if(flg_export>0 && cur->flg_export==0)
+ cur->flg_export=flg_export;
+ else
+ result++;
+ } else {
+ if(cur->flg_read_only) {
+ error_msg("%s: readonly variable", name);
+ result = -1;
} else {
- if(cur->flg_read_only) {
- error_msg("%s: readonly variable", name);
- free(newval);
- result = -1;
- } else {
- if(flg_export>0 || cur->flg_export>1)
- cur->flg_export=1;
- free(cur->value);
- cur->value = newval;
- }
+ if(flg_export>0 || cur->flg_export>1)
+ cur->flg_export=1;
+ free(cur->value);
+
+ cur->value = strdup(value);
}
+ }
+ } else {
+ cur = malloc(sizeof(struct variables));
+ if(!cur) {
+ result = -1;
} else {
- cur = malloc(sizeof(struct variables));
- if(cur==0) {
- free(newval);
+ cur->name = strdup(name);
+ if(cur->name == 0) {
+ free(cur);
result = -1;
} else {
- cur->name = strdup(name);
- if(cur->name == 0) {
- free(cur);
- free(newval);
- result = -1;
- } else {
- struct variables *bottom = top_vars;
- cur->value = newval;
- cur->next = 0;
- cur->flg_export = flg_export;
- cur->flg_read_only = 0;
- while(bottom->next) bottom=bottom->next;
- bottom->next = cur;
- }
+ struct variables *bottom = top_vars;
+ cur->value = strdup(value);
+ cur->next = 0;
+ cur->flg_export = flg_export;
+ cur->flg_read_only = 0;
+ while(bottom->next) bottom=bottom->next;
+ bottom->next = cur;
}
}
}