diff options
author | Ron Yorston <rmy@pobox.com> | 2014-01-14 21:12:21 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2014-01-14 21:12:21 +0000 |
commit | db03ff5ea8ce258da4399cb26924e34916dc83f7 (patch) | |
tree | 2dfd4048e4c351147a8f46d89b6a72327b199721 /shell | |
parent | 1a3717342d6d3e774e4e2171eb8ea81945ec918e (diff) | |
download | busybox-w32-db03ff5ea8ce258da4399cb26924e34916dc83f7.tar.gz busybox-w32-db03ff5ea8ce258da4399cb26924e34916dc83f7.tar.bz2 busybox-w32-db03ff5ea8ce258da4399cb26924e34916dc83f7.zip |
ash: reset pointers to builtin environment variables after fork
The builtin environment variables can be accessed using macros
that reference the varinit array. initvar puts pointers to varinit
into the variable hash table. During forkshell_prepare two copies
of the builtin variables are made: once as the varinit array and
again through the pointers in the hash table. One of these copies
is accessed by code that uses the macros and the other by code that
looks up the variable by name.
This is the cause of the strange behaviour of IFS in backticks:
https://github.com/pclouds/busybox-w32/issues/12
To avoid the problem the pointers in the hash table are reset to
the varinit array in forkshell_init. It seemed easier to do it
this way than to try and prevent the duplicate copies being made
in the first place.
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/shell/ash.c b/shell/ash.c index 6b7c9f2a2..40660dad5 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -13937,6 +13937,30 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13937 | } | 13937 | } |
13938 | 13938 | ||
13939 | #if ENABLE_PLATFORM_MINGW32 | 13939 | #if ENABLE_PLATFORM_MINGW32 |
13940 | /* | ||
13941 | * Reset the pointers to the builtin environment variables in the hash | ||
13942 | * table to point to varinit rather than the bogus copy created during | ||
13943 | * forkshell_prepare. | ||
13944 | */ | ||
13945 | static void | ||
13946 | reinitvar(void) | ||
13947 | { | ||
13948 | struct var *vp; | ||
13949 | struct var *end; | ||
13950 | struct var **vpp; | ||
13951 | struct var **old; | ||
13952 | |||
13953 | vp = varinit; | ||
13954 | end = vp + ARRAY_SIZE(varinit); | ||
13955 | do { | ||
13956 | vpp = hashvar(vp->var_text); | ||
13957 | if ( (old=findvar(vpp, vp->var_text)) != NULL ) { | ||
13958 | vp->next = (*old)->next; | ||
13959 | *old = vp; | ||
13960 | } | ||
13961 | } while (++vp < end); | ||
13962 | } | ||
13963 | |||
13940 | /* FIXME: should consider running forkparent() and forkchild() */ | 13964 | /* FIXME: should consider running forkparent() and forkchild() */ |
13941 | static int | 13965 | static int |
13942 | spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) | 13966 | spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) |
@@ -14424,6 +14448,8 @@ forkshell_init(const char *idstr) | |||
14424 | *gmpp = fs->gmp; | 14448 | *gmpp = fs->gmp; |
14425 | cmdtable = fs->cmdtable; | 14449 | cmdtable = fs->cmdtable; |
14426 | 14450 | ||
14451 | reinitvar(); | ||
14452 | |||
14427 | fs->fp(fs); | 14453 | fs->fp(fs); |
14428 | } | 14454 | } |
14429 | 14455 | ||