ash: fix nofork bug where environment is not properly passed to a command
function old new delta listvars 144 252 +108 evalcommand 1500 1546 +46 showvars 142 147 +5 shellexec 242 245 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 162/0) Total: 162 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
f5e8b42788
commit
a5060b8364
45
shell/ash.c
45
shell/ash.c
@ -2380,8 +2380,11 @@ listsetvar(struct strlist *list_set_var, int flags)
|
||||
/*
|
||||
* Generate a list of variables satisfying the given conditions.
|
||||
*/
|
||||
#if !ENABLE_FEATURE_SH_NOFORK
|
||||
# define listvars(on, off, lp, end) listvars(on, off, end)
|
||||
#endif
|
||||
static char **
|
||||
listvars(int on, int off, char ***end)
|
||||
listvars(int on, int off, struct strlist *lp, char ***end)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
@ -2394,12 +2397,40 @@ listvars(int on, int off, char ***end)
|
||||
do {
|
||||
for (vp = *vpp; vp; vp = vp->next) {
|
||||
if ((vp->flags & mask) == on) {
|
||||
#if ENABLE_FEATURE_SH_NOFORK
|
||||
/* If variable with the same name is both
|
||||
* exported and temporarily set for a command:
|
||||
* export ZVAR=5
|
||||
* ZVAR=6 printenv
|
||||
* then "ZVAR=6" will be both in vartab and
|
||||
* lp lists. Do not pass it twice to printenv.
|
||||
*/
|
||||
struct strlist *lp1 = lp;
|
||||
while (lp1) {
|
||||
if (strcmp(lp1->text, vp->var_text) == 0)
|
||||
goto skip;
|
||||
lp1 = lp1->next;
|
||||
}
|
||||
#endif
|
||||
if (ep == stackstrend())
|
||||
ep = growstackstr();
|
||||
*ep++ = (char*)vp->var_text;
|
||||
#if ENABLE_FEATURE_SH_NOFORK
|
||||
skip: ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} while (++vpp < vartab + VTABSIZE);
|
||||
|
||||
#if ENABLE_FEATURE_SH_NOFORK
|
||||
while (lp) {
|
||||
if (ep == stackstrend())
|
||||
ep = growstackstr();
|
||||
*ep++ = lp->text;
|
||||
lp = lp->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ep == stackstrend())
|
||||
ep = growstackstr();
|
||||
if (end)
|
||||
@ -7860,7 +7891,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
|
||||
int exerrno;
|
||||
int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
|
||||
|
||||
envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
|
||||
envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
|
||||
if (strchr(prog, '/') != NULL
|
||||
#if ENABLE_FEATURE_SH_STANDALONE
|
||||
|| (applet_no = find_applet_by_name(prog)) >= 0
|
||||
@ -9930,7 +9961,11 @@ evalcommand(union node *cmd, int flags)
|
||||
/* find_command() encodes applet_no as (-2 - applet_no) */
|
||||
int applet_no = (- cmdentry.u.index - 2);
|
||||
if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
|
||||
listsetvar(varlist.list, VEXPORT|VSTACK);
|
||||
char **sv_environ;
|
||||
|
||||
INT_OFF;
|
||||
sv_environ = environ;
|
||||
environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
|
||||
/*
|
||||
* Run <applet>_main().
|
||||
* Signals (^C) can't interrupt here.
|
||||
@ -9939,8 +9974,8 @@ evalcommand(union node *cmd, int flags)
|
||||
* and/or wait for user input ineligible for NOFORK:
|
||||
* for example, "yes" or "rm" (rm -i waits for input).
|
||||
*/
|
||||
INT_OFF;
|
||||
status = run_nofork_applet(applet_no, argv);
|
||||
environ = sv_environ;
|
||||
/*
|
||||
* Try enabling NOFORK for "yes" applet.
|
||||
* ^C _will_ stop it (write returns EINTR),
|
||||
@ -10854,7 +10889,7 @@ showvars(const char *sep_prefix, int on, int off)
|
||||
const char *sep;
|
||||
char **ep, **epend;
|
||||
|
||||
ep = listvars(on, off, &epend);
|
||||
ep = listvars(on, off, /*strlist:*/ NULL, &epend);
|
||||
qsort(ep, epend - ep, sizeof(char *), vpcmp);
|
||||
|
||||
sep = *sep_prefix ? " " : sep_prefix;
|
||||
|
9
shell/ash_test/ash-standalone/nofork_env.right
Normal file
9
shell/ash_test/ash-standalone/nofork_env.right
Normal file
@ -0,0 +1,9 @@
|
||||
ZVAR=1
|
||||
ZVAR=2
|
||||
ZVAR=3
|
||||
ZVAR=4
|
||||
ZVAR=5
|
||||
ZVAR=6
|
||||
ZVAR=7
|
||||
ZVAR=8
|
||||
Ok:0
|
15
shell/ash_test/ash-standalone/nofork_env.tests
Executable file
15
shell/ash_test/ash-standalone/nofork_env.tests
Executable file
@ -0,0 +1,15 @@
|
||||
# ash had a bug where NOFORKed applet (env/printenv) was not seeing new exported variables
|
||||
|
||||
(export ZVAR=1; printenv) | grep ^ZVAR=
|
||||
(ZVAR=2 printenv) | grep ^ZVAR=
|
||||
|
||||
(export ZVAR=3; env) | grep ^ZVAR=
|
||||
(ZVAR=4 env) | grep ^ZVAR=
|
||||
|
||||
export ZVAR=5; printenv | grep ^ZVAR=
|
||||
ZVAR=6 printenv | grep ^ZVAR=
|
||||
|
||||
export ZVAR=7; env | grep ^ZVAR=
|
||||
ZVAR=8 env | grep ^ZVAR=
|
||||
|
||||
echo Ok:$?
|
9
shell/hush_test/hush-standalone/nofork_env.right
Normal file
9
shell/hush_test/hush-standalone/nofork_env.right
Normal file
@ -0,0 +1,9 @@
|
||||
ZVAR=1
|
||||
ZVAR=2
|
||||
ZVAR=3
|
||||
ZVAR=4
|
||||
ZVAR=5
|
||||
ZVAR=6
|
||||
ZVAR=7
|
||||
ZVAR=8
|
||||
Ok:0
|
15
shell/hush_test/hush-standalone/nofork_env.tests
Executable file
15
shell/hush_test/hush-standalone/nofork_env.tests
Executable file
@ -0,0 +1,15 @@
|
||||
# ash had a bug where NOFORKed applet (env/printenv) was not seeing new exported variables
|
||||
|
||||
(export ZVAR=1; printenv) | grep ^ZVAR=
|
||||
(ZVAR=2 printenv) | grep ^ZVAR=
|
||||
|
||||
(export ZVAR=3; env) | grep ^ZVAR=
|
||||
(ZVAR=4 env) | grep ^ZVAR=
|
||||
|
||||
export ZVAR=5; printenv | grep ^ZVAR=
|
||||
ZVAR=6 printenv | grep ^ZVAR=
|
||||
|
||||
export ZVAR=7; env | grep ^ZVAR=
|
||||
ZVAR=8 env | grep ^ZVAR=
|
||||
|
||||
echo Ok:$?
|
Loading…
Reference in New Issue
Block a user