aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2014-01-14 21:12:21 +0000
committerRon Yorston <rmy@pobox.com>2014-01-14 21:12:21 +0000
commitdb03ff5ea8ce258da4399cb26924e34916dc83f7 (patch)
tree2dfd4048e4c351147a8f46d89b6a72327b199721 /shell
parent1a3717342d6d3e774e4e2171eb8ea81945ec918e (diff)
downloadbusybox-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.c26
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 */
13945static void
13946reinitvar(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() */
13941static int 13965static int
13942spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) 13966spawn_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