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
This commit is contained in:
Eric Andersen 2001-05-22 21:37:48 +00:00
parent aeb44c4da6
commit 9978576f15
2 changed files with 126 additions and 96 deletions

45
hush.c
View File

@ -1243,8 +1243,10 @@ static void checkjobs()
break; break;
} }
if(pi==NULL) if(pi==NULL) {
return; debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
continue;
}
if (WIFEXITED(status) || WIFSIGNALED(status)) { if (WIFEXITED(status) || WIFSIGNALED(status)) {
/* child exited */ /* child exited */
@ -1352,7 +1354,24 @@ static int run_pipe_real(struct pipe *pi)
if (i!=0 && child->argv[i]==NULL) { if (i!=0 && child->argv[i]==NULL) {
/* assignments, but no command: set the local environment */ /* assignments, but no command: set the local environment */
for (i=0; child->argv[i]!=NULL; i++) { 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 */ 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; char *name, *value;
int result=0; int result=0;
struct variables *cur; struct variables *cur;
char *newval = 0;
name=strdup(s); name=strdup(s);
@ -1712,9 +1730,10 @@ static int set_local_var(const char *s, int flg_export)
* NAME=VALUE format. So the first order of business is to * NAME=VALUE format. So the first order of business is to
* split 's' on the '=' into 'name' and 'value' */ * split 's' on the '=' into 'name' and 'value' */
value = strchr(name, '='); value = strchr(name, '=');
if (value==0 || (newval = strdup(value+1))==0) { if (value==0 && ++value==0) {
result = -1; free(name);
} else { return -1;
}
*value++ = 0; *value++ = 0;
for(cur = top_vars; cur; cur = cur->next) { for(cur = top_vars; cur; cur = cur->next) {
@ -1728,33 +1747,30 @@ static int set_local_var(const char *s, int flg_export)
cur->flg_export=flg_export; cur->flg_export=flg_export;
else else
result++; result++;
free(newval);
} else { } else {
if(cur->flg_read_only) { if(cur->flg_read_only) {
error_msg("%s: readonly variable", name); error_msg("%s: readonly variable", name);
free(newval);
result = -1; result = -1;
} else { } else {
if(flg_export>0 || cur->flg_export>1) if(flg_export>0 || cur->flg_export>1)
cur->flg_export=1; cur->flg_export=1;
free(cur->value); free(cur->value);
cur->value = newval;
cur->value = strdup(value);
} }
} }
} else { } else {
cur = malloc(sizeof(struct variables)); cur = malloc(sizeof(struct variables));
if(cur==0) { if(!cur) {
free(newval);
result = -1; result = -1;
} else { } else {
cur->name = strdup(name); cur->name = strdup(name);
if(cur->name == 0) { if(cur->name == 0) {
free(cur); free(cur);
free(newval);
result = -1; result = -1;
} else { } else {
struct variables *bottom = top_vars; struct variables *bottom = top_vars;
cur->value = newval; cur->value = strdup(value);
cur->next = 0; cur->next = 0;
cur->flg_export = flg_export; cur->flg_export = flg_export;
cur->flg_read_only = 0; cur->flg_read_only = 0;
@ -1763,7 +1779,6 @@ static int set_local_var(const char *s, int flg_export)
} }
} }
} }
}
if(result==0 && cur->flg_export==1) { if(result==0 && cur->flg_export==1) {
*(value-1) = '='; *(value-1) = '=';

View File

@ -1243,8 +1243,10 @@ static void checkjobs()
break; break;
} }
if(pi==NULL) if(pi==NULL) {
return; debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
continue;
}
if (WIFEXITED(status) || WIFSIGNALED(status)) { if (WIFEXITED(status) || WIFSIGNALED(status)) {
/* child exited */ /* child exited */
@ -1352,7 +1354,24 @@ static int run_pipe_real(struct pipe *pi)
if (i!=0 && child->argv[i]==NULL) { if (i!=0 && child->argv[i]==NULL) {
/* assignments, but no command: set the local environment */ /* assignments, but no command: set the local environment */
for (i=0; child->argv[i]!=NULL; i++) { 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 */ 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; char *name, *value;
int result=0; int result=0;
struct variables *cur; struct variables *cur;
char *newval = 0;
name=strdup(s); name=strdup(s);
@ -1712,9 +1730,10 @@ static int set_local_var(const char *s, int flg_export)
* NAME=VALUE format. So the first order of business is to * NAME=VALUE format. So the first order of business is to
* split 's' on the '=' into 'name' and 'value' */ * split 's' on the '=' into 'name' and 'value' */
value = strchr(name, '='); value = strchr(name, '=');
if (value==0 || (newval = strdup(value+1))==0) { if (value==0 && ++value==0) {
result = -1; free(name);
} else { return -1;
}
*value++ = 0; *value++ = 0;
for(cur = top_vars; cur; cur = cur->next) { for(cur = top_vars; cur; cur = cur->next) {
@ -1728,33 +1747,30 @@ static int set_local_var(const char *s, int flg_export)
cur->flg_export=flg_export; cur->flg_export=flg_export;
else else
result++; result++;
free(newval);
} else { } else {
if(cur->flg_read_only) { if(cur->flg_read_only) {
error_msg("%s: readonly variable", name); error_msg("%s: readonly variable", name);
free(newval);
result = -1; result = -1;
} else { } else {
if(flg_export>0 || cur->flg_export>1) if(flg_export>0 || cur->flg_export>1)
cur->flg_export=1; cur->flg_export=1;
free(cur->value); free(cur->value);
cur->value = newval;
cur->value = strdup(value);
} }
} }
} else { } else {
cur = malloc(sizeof(struct variables)); cur = malloc(sizeof(struct variables));
if(cur==0) { if(!cur) {
free(newval);
result = -1; result = -1;
} else { } else {
cur->name = strdup(name); cur->name = strdup(name);
if(cur->name == 0) { if(cur->name == 0) {
free(cur); free(cur);
free(newval);
result = -1; result = -1;
} else { } else {
struct variables *bottom = top_vars; struct variables *bottom = top_vars;
cur->value = newval; cur->value = strdup(value);
cur->next = 0; cur->next = 0;
cur->flg_export = flg_export; cur->flg_export = flg_export;
cur->flg_read_only = 0; cur->flg_read_only = 0;
@ -1763,7 +1779,6 @@ static int set_local_var(const char *s, int flg_export)
} }
} }
} }
}
if(result==0 && cur->flg_export==1) { if(result==0 && cur->flg_export==1) {
*(value-1) = '='; *(value-1) = '=';