aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-11-03 14:16:25 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-11-03 14:16:25 +0100
commita5060b8364faa7c677c8950f1315c451403b0660 (patch)
treef62638268fb4edd79cd1a062d63092df1a5b4513
parentf5e8b4278822f2413bf7e47466f55cc1a0fcca9a (diff)
downloadbusybox-w32-a5060b8364faa7c677c8950f1315c451403b0660.tar.gz
busybox-w32-a5060b8364faa7c677c8950f1315c451403b0660.tar.bz2
busybox-w32-a5060b8364faa7c677c8950f1315c451403b0660.zip
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>
-rw-r--r--shell/ash.c45
-rw-r--r--shell/ash_test/ash-standalone/nofork_env.right9
-rwxr-xr-xshell/ash_test/ash-standalone/nofork_env.tests15
-rw-r--r--shell/hush_test/hush-standalone/nofork_env.right9
-rwxr-xr-xshell/hush_test/hush-standalone/nofork_env.tests15
5 files changed, 88 insertions, 5 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7a0b88c68..e69ddb4ff 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2380,8 +2380,11 @@ listsetvar(struct strlist *list_set_var, int flags)
2380/* 2380/*
2381 * Generate a list of variables satisfying the given conditions. 2381 * Generate a list of variables satisfying the given conditions.
2382 */ 2382 */
2383#if !ENABLE_FEATURE_SH_NOFORK
2384# define listvars(on, off, lp, end) listvars(on, off, end)
2385#endif
2383static char ** 2386static char **
2384listvars(int on, int off, char ***end) 2387listvars(int on, int off, struct strlist *lp, char ***end)
2385{ 2388{
2386 struct var **vpp; 2389 struct var **vpp;
2387 struct var *vp; 2390 struct var *vp;
@@ -2394,12 +2397,40 @@ listvars(int on, int off, char ***end)
2394 do { 2397 do {
2395 for (vp = *vpp; vp; vp = vp->next) { 2398 for (vp = *vpp; vp; vp = vp->next) {
2396 if ((vp->flags & mask) == on) { 2399 if ((vp->flags & mask) == on) {
2400#if ENABLE_FEATURE_SH_NOFORK
2401 /* If variable with the same name is both
2402 * exported and temporarily set for a command:
2403 * export ZVAR=5
2404 * ZVAR=6 printenv
2405 * then "ZVAR=6" will be both in vartab and
2406 * lp lists. Do not pass it twice to printenv.
2407 */
2408 struct strlist *lp1 = lp;
2409 while (lp1) {
2410 if (strcmp(lp1->text, vp->var_text) == 0)
2411 goto skip;
2412 lp1 = lp1->next;
2413 }
2414#endif
2397 if (ep == stackstrend()) 2415 if (ep == stackstrend())
2398 ep = growstackstr(); 2416 ep = growstackstr();
2399 *ep++ = (char*)vp->var_text; 2417 *ep++ = (char*)vp->var_text;
2418#if ENABLE_FEATURE_SH_NOFORK
2419 skip: ;
2420#endif
2400 } 2421 }
2401 } 2422 }
2402 } while (++vpp < vartab + VTABSIZE); 2423 } while (++vpp < vartab + VTABSIZE);
2424
2425#if ENABLE_FEATURE_SH_NOFORK
2426 while (lp) {
2427 if (ep == stackstrend())
2428 ep = growstackstr();
2429 *ep++ = lp->text;
2430 lp = lp->next;
2431 }
2432#endif
2433
2403 if (ep == stackstrend()) 2434 if (ep == stackstrend())
2404 ep = growstackstr(); 2435 ep = growstackstr();
2405 if (end) 2436 if (end)
@@ -7860,7 +7891,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
7860 int exerrno; 7891 int exerrno;
7861 int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ 7892 int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7862 7893
7863 envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL); 7894 envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
7864 if (strchr(prog, '/') != NULL 7895 if (strchr(prog, '/') != NULL
7865#if ENABLE_FEATURE_SH_STANDALONE 7896#if ENABLE_FEATURE_SH_STANDALONE
7866 || (applet_no = find_applet_by_name(prog)) >= 0 7897 || (applet_no = find_applet_by_name(prog)) >= 0
@@ -9930,7 +9961,11 @@ evalcommand(union node *cmd, int flags)
9930 /* find_command() encodes applet_no as (-2 - applet_no) */ 9961 /* find_command() encodes applet_no as (-2 - applet_no) */
9931 int applet_no = (- cmdentry.u.index - 2); 9962 int applet_no = (- cmdentry.u.index - 2);
9932 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { 9963 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9933 listsetvar(varlist.list, VEXPORT|VSTACK); 9964 char **sv_environ;
9965
9966 INT_OFF;
9967 sv_environ = environ;
9968 environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
9934 /* 9969 /*
9935 * Run <applet>_main(). 9970 * Run <applet>_main().
9936 * Signals (^C) can't interrupt here. 9971 * Signals (^C) can't interrupt here.
@@ -9939,8 +9974,8 @@ evalcommand(union node *cmd, int flags)
9939 * and/or wait for user input ineligible for NOFORK: 9974 * and/or wait for user input ineligible for NOFORK:
9940 * for example, "yes" or "rm" (rm -i waits for input). 9975 * for example, "yes" or "rm" (rm -i waits for input).
9941 */ 9976 */
9942 INT_OFF;
9943 status = run_nofork_applet(applet_no, argv); 9977 status = run_nofork_applet(applet_no, argv);
9978 environ = sv_environ;
9944 /* 9979 /*
9945 * Try enabling NOFORK for "yes" applet. 9980 * Try enabling NOFORK for "yes" applet.
9946 * ^C _will_ stop it (write returns EINTR), 9981 * ^C _will_ stop it (write returns EINTR),
@@ -10854,7 +10889,7 @@ showvars(const char *sep_prefix, int on, int off)
10854 const char *sep; 10889 const char *sep;
10855 char **ep, **epend; 10890 char **ep, **epend;
10856 10891
10857 ep = listvars(on, off, &epend); 10892 ep = listvars(on, off, /*strlist:*/ NULL, &epend);
10858 qsort(ep, epend - ep, sizeof(char *), vpcmp); 10893 qsort(ep, epend - ep, sizeof(char *), vpcmp);
10859 10894
10860 sep = *sep_prefix ? " " : sep_prefix; 10895 sep = *sep_prefix ? " " : sep_prefix;
diff --git a/shell/ash_test/ash-standalone/nofork_env.right b/shell/ash_test/ash-standalone/nofork_env.right
new file mode 100644
index 000000000..3f16ff458
--- /dev/null
+++ b/shell/ash_test/ash-standalone/nofork_env.right
@@ -0,0 +1,9 @@
1ZVAR=1
2ZVAR=2
3ZVAR=3
4ZVAR=4
5ZVAR=5
6ZVAR=6
7ZVAR=7
8ZVAR=8
9Ok:0
diff --git a/shell/ash_test/ash-standalone/nofork_env.tests b/shell/ash_test/ash-standalone/nofork_env.tests
new file mode 100755
index 000000000..111e564d2
--- /dev/null
+++ b/shell/ash_test/ash-standalone/nofork_env.tests
@@ -0,0 +1,15 @@
1# ash had a bug where NOFORKed applet (env/printenv) was not seeing new exported variables
2
3(export ZVAR=1; printenv) | grep ^ZVAR=
4(ZVAR=2 printenv) | grep ^ZVAR=
5
6(export ZVAR=3; env) | grep ^ZVAR=
7(ZVAR=4 env) | grep ^ZVAR=
8
9export ZVAR=5; printenv | grep ^ZVAR=
10ZVAR=6 printenv | grep ^ZVAR=
11
12export ZVAR=7; env | grep ^ZVAR=
13ZVAR=8 env | grep ^ZVAR=
14
15echo Ok:$?
diff --git a/shell/hush_test/hush-standalone/nofork_env.right b/shell/hush_test/hush-standalone/nofork_env.right
new file mode 100644
index 000000000..3f16ff458
--- /dev/null
+++ b/shell/hush_test/hush-standalone/nofork_env.right
@@ -0,0 +1,9 @@
1ZVAR=1
2ZVAR=2
3ZVAR=3
4ZVAR=4
5ZVAR=5
6ZVAR=6
7ZVAR=7
8ZVAR=8
9Ok:0
diff --git a/shell/hush_test/hush-standalone/nofork_env.tests b/shell/hush_test/hush-standalone/nofork_env.tests
new file mode 100755
index 000000000..111e564d2
--- /dev/null
+++ b/shell/hush_test/hush-standalone/nofork_env.tests
@@ -0,0 +1,15 @@
1# ash had a bug where NOFORKed applet (env/printenv) was not seeing new exported variables
2
3(export ZVAR=1; printenv) | grep ^ZVAR=
4(ZVAR=2 printenv) | grep ^ZVAR=
5
6(export ZVAR=3; env) | grep ^ZVAR=
7(ZVAR=4 env) | grep ^ZVAR=
8
9export ZVAR=5; printenv | grep ^ZVAR=
10ZVAR=6 printenv | grep ^ZVAR=
11
12export ZVAR=7; env | grep ^ZVAR=
13ZVAR=8 env | grep ^ZVAR=
14
15echo Ok:$?