diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-04 00:14:30 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-04 00:14:30 +0200 |
| commit | cb6ff25afeb2daeebcb435c9766215061d3c75cb (patch) | |
| tree | e185f3ff23622f171d52fb783ad4b23626f26bfc /shell | |
| parent | e19e1935a33b117e2ee6daf9b2d79c00603333c7 (diff) | |
| download | busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.tar.gz busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.tar.bz2 busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.zip | |
hush: fix bug where in "var=val func" var's value is not visible in func
function old new delta
unset_local_var - 168 +168
set_vars_all_and_save_old - 87 +87
get_ptr_to_local_var - 77 +77
free_strings_and_unset - 53 +53
builtin_export 266 274 +8
get_local_var_value 31 33 +2
putenv_all 27 - -27
free_strings_and_unsetenv 53 - -53
get_local_var 68 - -68
run_list 2475 2350 -125
builtin_unset 380 220 -160
------------------------------------------------------------------------------
(add/remove: 4/3 grow/shrink: 2/2 up/down: 395/-433) Total: -38 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 199 | ||||
| -rw-r--r-- | shell/hush_test/hush-misc/env_and_func.right (renamed from shell/hush_test/hush-bugs/env_and_func.right) | 0 | ||||
| -rwxr-xr-x | shell/hush_test/hush-misc/env_and_func.tests (renamed from shell/hush_test/hush-bugs/env_and_func.tests) | 2 |
3 files changed, 109 insertions, 92 deletions
diff --git a/shell/hush.c b/shell/hush.c index c6e940548..0890f0977 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -56,7 +56,7 @@ | |||
| 56 | * | 56 | * |
| 57 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 57 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
| 58 | */ | 58 | */ |
| 59 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 59 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
| 60 | #include <glob.h> | 60 | #include <glob.h> |
| 61 | /* #include <dmalloc.h> */ | 61 | /* #include <dmalloc.h> */ |
| 62 | #if ENABLE_HUSH_CASE | 62 | #if ENABLE_HUSH_CASE |
| @@ -65,7 +65,7 @@ | |||
| 65 | #include "math.h" | 65 | #include "math.h" |
| 66 | #include "match.h" | 66 | #include "match.h" |
| 67 | #ifndef PIPE_BUF | 67 | #ifndef PIPE_BUF |
| 68 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | 68 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ |
| 69 | #endif | 69 | #endif |
| 70 | 70 | ||
| 71 | 71 | ||
| @@ -138,6 +138,8 @@ | |||
| 138 | 138 | ||
| 139 | #define SPECIAL_VAR_SYMBOL 3 | 139 | #define SPECIAL_VAR_SYMBOL 3 |
| 140 | 140 | ||
| 141 | struct variable; | ||
| 142 | |||
| 141 | static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; | 143 | static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; |
| 142 | 144 | ||
| 143 | /* This supports saving pointers malloced in vfork child, | 145 | /* This supports saving pointers malloced in vfork child, |
| @@ -146,7 +148,7 @@ static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; | |||
| 146 | #if !BB_MMU | 148 | #if !BB_MMU |
| 147 | typedef struct nommu_save_t { | 149 | typedef struct nommu_save_t { |
| 148 | char **new_env; | 150 | char **new_env; |
| 149 | char **old_env; | 151 | struct variable *old_vars; |
| 150 | char **argv; | 152 | char **argv; |
| 151 | char **argv_from_re_execing; | 153 | char **argv_from_re_execing; |
| 152 | } nommu_save_t; | 154 | } nommu_save_t; |
| @@ -282,8 +284,8 @@ struct command { | |||
| 282 | #if ENABLE_HUSH_FUNCTIONS | 284 | #if ENABLE_HUSH_FUNCTIONS |
| 283 | # define GRP_FUNCTION 2 | 285 | # define GRP_FUNCTION 2 |
| 284 | #endif | 286 | #endif |
| 285 | struct pipe *group; /* if non-NULL, this "command" is { list }, | 287 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ |
| 286 | * ( list ), or a compound statement */ | 288 | struct pipe *group; |
| 287 | #if !BB_MMU | 289 | #if !BB_MMU |
| 288 | char *group_as_string; | 290 | char *group_as_string; |
| 289 | #endif | 291 | #endif |
| @@ -883,6 +885,7 @@ static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, | |||
| 883 | xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup) | 885 | xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup) |
| 884 | #endif | 886 | #endif |
| 885 | 887 | ||
| 888 | /* Note: takes ownership of "add" ptr (it is not strdup'ed) */ | ||
| 886 | static char **add_string_to_strings(char **strings, char *add) | 889 | static char **add_string_to_strings(char **strings, char *add) |
| 887 | { | 890 | { |
| 888 | char *v[2]; | 891 | char *v[2]; |
| @@ -901,44 +904,9 @@ static char **xx_add_string_to_strings(int lineno, char **strings, char *add) | |||
| 901 | xx_add_string_to_strings(__LINE__, strings, add) | 904 | xx_add_string_to_strings(__LINE__, strings, add) |
| 902 | #endif | 905 | #endif |
| 903 | 906 | ||
| 904 | static void putenv_all(char **strings) | 907 | static int unset_local_var(const char *name); |
| 905 | { | ||
| 906 | if (!strings) | ||
| 907 | return; | ||
| 908 | while (*strings) { | ||
| 909 | debug_printf_env("putenv '%s'\n", *strings); | ||
| 910 | putenv(*strings++); | ||
| 911 | } | ||
| 912 | } | ||
| 913 | |||
| 914 | static char **putenv_all_and_save_old(char **strings) | ||
| 915 | { | ||
| 916 | char **old = NULL; | ||
| 917 | char **s = strings; | ||
| 918 | |||
| 919 | if (!strings) | ||
| 920 | return old; | ||
| 921 | while (*strings) { | ||
| 922 | char *v, *eq; | ||
| 923 | |||
| 924 | eq = strchr(*strings, '='); | ||
| 925 | if (eq) { | ||
| 926 | *eq = '\0'; | ||
| 927 | v = getenv(*strings); | ||
| 928 | *eq = '='; | ||
| 929 | if (v) { | ||
| 930 | /* v points to VAL in VAR=VAL, go back to VAR */ | ||
| 931 | v -= (eq - *strings) + 1; | ||
| 932 | old = add_string_to_strings(old, v); | ||
| 933 | } | ||
| 934 | } | ||
| 935 | strings++; | ||
| 936 | } | ||
| 937 | putenv_all(s); | ||
| 938 | return old; | ||
| 939 | } | ||
| 940 | 908 | ||
| 941 | static void free_strings_and_unsetenv(char **strings, int unset) | 909 | static void free_strings_and_unset(char **strings, int unset) |
| 942 | { | 910 | { |
| 943 | char **v; | 911 | char **v; |
| 944 | 912 | ||
| @@ -948,8 +916,7 @@ static void free_strings_and_unsetenv(char **strings, int unset) | |||
| 948 | v = strings; | 916 | v = strings; |
| 949 | while (*v) { | 917 | while (*v) { |
| 950 | if (unset) { | 918 | if (unset) { |
| 951 | debug_printf_env("unsetenv '%s'\n", *v); | 919 | unset_local_var(*v); |
| 952 | bb_unsetenv(*v); | ||
| 953 | } | 920 | } |
| 954 | free(*v++); | 921 | free(*v++); |
| 955 | } | 922 | } |
| @@ -958,7 +925,7 @@ static void free_strings_and_unsetenv(char **strings, int unset) | |||
| 958 | 925 | ||
| 959 | static void free_strings(char **strings) | 926 | static void free_strings(char **strings) |
| 960 | { | 927 | { |
| 961 | free_strings_and_unsetenv(strings, 0); | 928 | free_strings_and_unset(strings, 0); |
| 962 | } | 929 | } |
| 963 | 930 | ||
| 964 | 931 | ||
| @@ -1242,27 +1209,38 @@ static const char *set_cwd(void) | |||
| 1242 | } | 1209 | } |
| 1243 | 1210 | ||
| 1244 | 1211 | ||
| 1245 | /* Get/check local shell variables */ | 1212 | /* |
| 1246 | static struct variable *get_local_var(const char *name) | 1213 | * Shell and environment variable support |
| 1214 | */ | ||
| 1215 | static struct variable **get_ptr_to_local_var(const char *name) | ||
| 1247 | { | 1216 | { |
| 1217 | struct variable **pp; | ||
| 1248 | struct variable *cur; | 1218 | struct variable *cur; |
| 1249 | int len; | 1219 | int len; |
| 1250 | 1220 | ||
| 1251 | if (!name) | ||
| 1252 | return NULL; | ||
| 1253 | len = strlen(name); | 1221 | len = strlen(name); |
| 1254 | for (cur = G.top_var; cur; cur = cur->next) { | 1222 | pp = &G.top_var; |
| 1223 | while ((cur = *pp) != NULL) { | ||
| 1255 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') | 1224 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') |
| 1256 | return cur; | 1225 | return pp; |
| 1226 | pp = &cur->next; | ||
| 1257 | } | 1227 | } |
| 1258 | return NULL; | 1228 | return NULL; |
| 1259 | } | 1229 | } |
| 1260 | 1230 | ||
| 1261 | static const char *get_local_var_value(const char *src) | 1231 | static struct variable *get_local_var(const char *name) |
| 1262 | { | 1232 | { |
| 1263 | struct variable *var = get_local_var(src); | 1233 | struct variable **pp = get_ptr_to_local_var(name); |
| 1264 | if (var) | 1234 | if (pp) |
| 1265 | return strchr(var->varstr, '=') + 1; | 1235 | return *pp; |
| 1236 | return NULL; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static const char *get_local_var_value(const char *name) | ||
| 1240 | { | ||
| 1241 | struct variable **pp = get_ptr_to_local_var(name); | ||
| 1242 | if (pp) | ||
| 1243 | return strchr((*pp)->varstr, '=') + 1; | ||
| 1266 | return NULL; | 1244 | return NULL; |
| 1267 | } | 1245 | } |
| 1268 | 1246 | ||
| @@ -1423,6 +1401,57 @@ static void arith_set_local_var(const char *name, const char *val, int flags) | |||
| 1423 | 1401 | ||
| 1424 | 1402 | ||
| 1425 | /* | 1403 | /* |
| 1404 | * Helpers for "var1=val1 var2=val2 cmd" feature | ||
| 1405 | */ | ||
| 1406 | static void add_vars(struct variable *var) | ||
| 1407 | { | ||
| 1408 | struct variable *next; | ||
| 1409 | |||
| 1410 | while (var) { | ||
| 1411 | next = var->next; | ||
| 1412 | var->next = G.top_var; | ||
| 1413 | G.top_var = var; | ||
| 1414 | if (var->flg_export) | ||
| 1415 | putenv(var->varstr); | ||
| 1416 | var = next; | ||
| 1417 | } | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | static struct variable *set_vars_all_and_save_old(char **strings) | ||
| 1421 | { | ||
| 1422 | char **s; | ||
| 1423 | struct variable *old = NULL; | ||
| 1424 | |||
| 1425 | if (!strings) | ||
| 1426 | return old; | ||
| 1427 | s = strings; | ||
| 1428 | while (*s) { | ||
| 1429 | struct variable *var_p; | ||
| 1430 | struct variable **var_pp; | ||
| 1431 | char *eq; | ||
| 1432 | |||
| 1433 | eq = strchr(*s, '='); | ||
| 1434 | if (eq) { | ||
| 1435 | *eq = '\0'; | ||
| 1436 | var_pp = get_ptr_to_local_var(*s); | ||
| 1437 | *eq = '='; | ||
| 1438 | if (var_pp) { | ||
| 1439 | /* Remove variable from global linked list */ | ||
| 1440 | var_p = *var_pp; | ||
| 1441 | *var_pp = var_p->next; | ||
| 1442 | /* Add it to returned list */ | ||
| 1443 | var_p->next = old; | ||
| 1444 | old = var_p; | ||
| 1445 | } | ||
| 1446 | set_local_var(*s, 1, 0); | ||
| 1447 | } | ||
| 1448 | s++; | ||
| 1449 | } | ||
| 1450 | return old; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | |||
| 1454 | /* | ||
| 1426 | * in_str support | 1455 | * in_str support |
| 1427 | */ | 1456 | */ |
| 1428 | static int static_get(struct in_str *i) | 1457 | static int static_get(struct in_str *i) |
| @@ -2855,17 +2884,17 @@ static struct function *new_function(char *name) | |||
| 2855 | * body_as_string was not malloced! */ | 2884 | * body_as_string was not malloced! */ |
| 2856 | if (funcp->body) { | 2885 | if (funcp->body) { |
| 2857 | free_pipe_list(funcp->body); | 2886 | free_pipe_list(funcp->body); |
| 2858 | #if !BB_MMU | 2887 | # if !BB_MMU |
| 2859 | free(funcp->body_as_string); | 2888 | free(funcp->body_as_string); |
| 2860 | #endif | 2889 | # endif |
| 2861 | } | 2890 | } |
| 2862 | } else { | 2891 | } else { |
| 2863 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); | 2892 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); |
| 2864 | cmd->argv[0] = funcp->name; | 2893 | cmd->argv[0] = funcp->name; |
| 2865 | cmd->group = funcp->body; | 2894 | cmd->group = funcp->body; |
| 2866 | #if !BB_MMU | 2895 | # if !BB_MMU |
| 2867 | cmd->group_as_string = funcp->body_as_string; | 2896 | cmd->group_as_string = funcp->body_as_string; |
| 2868 | #endif | 2897 | # endif |
| 2869 | } | 2898 | } |
| 2870 | goto skip; | 2899 | goto skip; |
| 2871 | } | 2900 | } |
| @@ -2892,9 +2921,9 @@ static void unset_func(const char *name) | |||
| 2892 | * body_as_string was not malloced! */ | 2921 | * body_as_string was not malloced! */ |
| 2893 | if (funcp->body) { | 2922 | if (funcp->body) { |
| 2894 | free_pipe_list(funcp->body); | 2923 | free_pipe_list(funcp->body); |
| 2895 | #if !BB_MMU | 2924 | # if !BB_MMU |
| 2896 | free(funcp->body_as_string); | 2925 | free(funcp->body_as_string); |
| 2897 | #endif | 2926 | # endif |
| 2898 | } | 2927 | } |
| 2899 | free(funcp); | 2928 | free(funcp); |
| 2900 | break; | 2929 | break; |
| @@ -2903,10 +2932,10 @@ static void unset_func(const char *name) | |||
| 2903 | } | 2932 | } |
| 2904 | } | 2933 | } |
| 2905 | 2934 | ||
| 2906 | #if BB_MMU | 2935 | # if BB_MMU |
| 2907 | #define exec_function(nommu_save, funcp, argv) \ | 2936 | #define exec_function(nommu_save, funcp, argv) \ |
| 2908 | exec_function(funcp, argv) | 2937 | exec_function(funcp, argv) |
| 2909 | #endif | 2938 | # endif |
| 2910 | static void exec_function(nommu_save_t *nommu_save, | 2939 | static void exec_function(nommu_save_t *nommu_save, |
| 2911 | const struct function *funcp, | 2940 | const struct function *funcp, |
| 2912 | char **argv) NORETURN; | 2941 | char **argv) NORETURN; |
| @@ -2938,37 +2967,31 @@ static int run_function(const struct function *funcp, char **argv) | |||
| 2938 | { | 2967 | { |
| 2939 | int rc; | 2968 | int rc; |
| 2940 | save_arg_t sv; | 2969 | save_arg_t sv; |
| 2941 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2942 | smallint sv_flg; | 2970 | smallint sv_flg; |
| 2943 | #endif | ||
| 2944 | 2971 | ||
| 2945 | save_and_replace_G_args(&sv, argv); | 2972 | save_and_replace_G_args(&sv, argv); |
| 2946 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2947 | /* "we are in function, ok to use return" */ | 2973 | /* "we are in function, ok to use return" */ |
| 2948 | sv_flg = G.flag_return_in_progress; | 2974 | sv_flg = G.flag_return_in_progress; |
| 2949 | G.flag_return_in_progress = -1; | 2975 | G.flag_return_in_progress = -1; |
| 2950 | #endif | ||
| 2951 | 2976 | ||
| 2952 | /* On MMU, funcp->body is always non-NULL */ | 2977 | /* On MMU, funcp->body is always non-NULL */ |
| 2953 | #if !BB_MMU | 2978 | # if !BB_MMU |
| 2954 | if (!funcp->body) { | 2979 | if (!funcp->body) { |
| 2955 | /* Function defined by -F */ | 2980 | /* Function defined by -F */ |
| 2956 | parse_and_run_string(funcp->body_as_string); | 2981 | parse_and_run_string(funcp->body_as_string); |
| 2957 | rc = G.last_exitcode; | 2982 | rc = G.last_exitcode; |
| 2958 | } else | 2983 | } else |
| 2959 | #endif | 2984 | # endif |
| 2960 | { | 2985 | { |
| 2961 | rc = run_list(funcp->body); | 2986 | rc = run_list(funcp->body); |
| 2962 | } | 2987 | } |
| 2963 | 2988 | ||
| 2964 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2965 | G.flag_return_in_progress = sv_flg; | 2989 | G.flag_return_in_progress = sv_flg; |
| 2966 | #endif | ||
| 2967 | restore_G_args(&sv, argv); | 2990 | restore_G_args(&sv, argv); |
| 2968 | 2991 | ||
| 2969 | return rc; | 2992 | return rc; |
| 2970 | } | 2993 | } |
| 2971 | #endif | 2994 | #endif /* ENABLE_HUSH_FUNCTIONS */ |
| 2972 | 2995 | ||
| 2973 | 2996 | ||
| 2974 | #if BB_MMU | 2997 | #if BB_MMU |
| @@ -2998,11 +3021,13 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
| 2998 | 3021 | ||
| 2999 | new_env = expand_assignments(argv, assignment_cnt); | 3022 | new_env = expand_assignments(argv, assignment_cnt); |
| 3000 | #if BB_MMU | 3023 | #if BB_MMU |
| 3001 | putenv_all(new_env); | 3024 | set_vars_all_and_save_old(new_env); |
| 3002 | free(new_env); /* optional */ | 3025 | free(new_env); /* optional */ |
| 3026 | /* we can also destroy set_vars_all_and_save_old's return value, | ||
| 3027 | * to save memory */ | ||
| 3003 | #else | 3028 | #else |
| 3004 | nommu_save->new_env = new_env; | 3029 | nommu_save->new_env = new_env; |
| 3005 | nommu_save->old_env = putenv_all_and_save_old(new_env); | 3030 | nommu_save->old_vars = set_vars_all_and_save_old(new_env); |
| 3006 | #endif | 3031 | #endif |
| 3007 | if (argv_expanded) { | 3032 | if (argv_expanded) { |
| 3008 | argv = argv_expanded; | 3033 | argv = argv_expanded; |
| @@ -3443,10 +3468,10 @@ static int run_pipe(struct pipe *pi) | |||
| 3443 | funcp = new_function(command->argv[0]); | 3468 | funcp = new_function(command->argv[0]); |
| 3444 | /* funcp->name is already set to argv[0] */ | 3469 | /* funcp->name is already set to argv[0] */ |
| 3445 | funcp->body = command->group; | 3470 | funcp->body = command->group; |
| 3446 | #if !BB_MMU | 3471 | # if !BB_MMU |
| 3447 | funcp->body_as_string = command->group_as_string; | 3472 | funcp->body_as_string = command->group_as_string; |
| 3448 | command->group_as_string = NULL; | 3473 | command->group_as_string = NULL; |
| 3449 | #endif | 3474 | # endif |
| 3450 | command->group = NULL; | 3475 | command->group = NULL; |
| 3451 | command->argv[0] = NULL; | 3476 | command->argv[0] = NULL; |
| 3452 | debug_printf_exec("cmd %p has child func at %p\n", command, funcp); | 3477 | debug_printf_exec("cmd %p has child func at %p\n", command, funcp); |
| @@ -3481,7 +3506,7 @@ static int run_pipe(struct pipe *pi) | |||
| 3481 | enum { funcp = 0 }; | 3506 | enum { funcp = 0 }; |
| 3482 | #endif | 3507 | #endif |
| 3483 | char **new_env = NULL; | 3508 | char **new_env = NULL; |
| 3484 | char **old_env = NULL; | 3509 | struct variable *old_vars = NULL; |
| 3485 | 3510 | ||
| 3486 | if (argv[command->assignment_cnt] == NULL) { | 3511 | if (argv[command->assignment_cnt] == NULL) { |
| 3487 | /* Assignments, but no command */ | 3512 | /* Assignments, but no command */ |
| @@ -3529,7 +3554,7 @@ static int run_pipe(struct pipe *pi) | |||
| 3529 | rcode = setup_redirects(command, squirrel); | 3554 | rcode = setup_redirects(command, squirrel); |
| 3530 | if (rcode == 0) { | 3555 | if (rcode == 0) { |
| 3531 | new_env = expand_assignments(argv, command->assignment_cnt); | 3556 | new_env = expand_assignments(argv, command->assignment_cnt); |
| 3532 | old_env = putenv_all_and_save_old(new_env); | 3557 | old_vars = set_vars_all_and_save_old(new_env); |
| 3533 | if (!funcp) { | 3558 | if (!funcp) { |
| 3534 | debug_printf_exec(": builtin '%s' '%s'...\n", | 3559 | debug_printf_exec(": builtin '%s' '%s'...\n", |
| 3535 | x->cmd, argv_expanded[1]); | 3560 | x->cmd, argv_expanded[1]); |
| @@ -3548,11 +3573,8 @@ static int run_pipe(struct pipe *pi) | |||
| 3548 | clean_up_and_ret: | 3573 | clean_up_and_ret: |
| 3549 | #endif | 3574 | #endif |
| 3550 | restore_redirects(squirrel); | 3575 | restore_redirects(squirrel); |
| 3551 | free_strings_and_unsetenv(new_env, 1); | 3576 | free_strings_and_unset(new_env, 1); |
| 3552 | putenv_all(old_env); | 3577 | add_vars(old_vars); |
| 3553 | /* Free the pointers, but the strings themselves | ||
| 3554 | * are in environ now, don't use free_strings! */ | ||
| 3555 | free(old_env); | ||
| 3556 | clean_up_and_ret1: | 3578 | clean_up_and_ret1: |
| 3557 | free(argv_expanded); | 3579 | free(argv_expanded); |
| 3558 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) | 3580 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
| @@ -3567,7 +3589,7 @@ static int run_pipe(struct pipe *pi) | |||
| 3567 | rcode = setup_redirects(command, squirrel); | 3589 | rcode = setup_redirects(command, squirrel); |
| 3568 | if (rcode == 0) { | 3590 | if (rcode == 0) { |
| 3569 | new_env = expand_assignments(argv, command->assignment_cnt); | 3591 | new_env = expand_assignments(argv, command->assignment_cnt); |
| 3570 | old_env = putenv_all_and_save_old(new_env); | 3592 | old_vars = set_vars_all_and_save_old(new_env); |
| 3571 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", | 3593 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", |
| 3572 | argv_expanded[0], argv_expanded[1]); | 3594 | argv_expanded[0], argv_expanded[1]); |
| 3573 | rcode = run_nofork_applet(i, argv_expanded); | 3595 | rcode = run_nofork_applet(i, argv_expanded); |
| @@ -3592,7 +3614,7 @@ static int run_pipe(struct pipe *pi) | |||
| 3592 | #if !BB_MMU | 3614 | #if !BB_MMU |
| 3593 | volatile nommu_save_t nommu_save; | 3615 | volatile nommu_save_t nommu_save; |
| 3594 | nommu_save.new_env = NULL; | 3616 | nommu_save.new_env = NULL; |
| 3595 | nommu_save.old_env = NULL; | 3617 | nommu_save.old_vars = NULL; |
| 3596 | nommu_save.argv = NULL; | 3618 | nommu_save.argv = NULL; |
| 3597 | nommu_save.argv_from_re_execing = NULL; | 3619 | nommu_save.argv_from_re_execing = NULL; |
| 3598 | #endif | 3620 | #endif |
| @@ -3665,11 +3687,8 @@ static int run_pipe(struct pipe *pi) | |||
| 3665 | /* Clean up after vforked child */ | 3687 | /* Clean up after vforked child */ |
| 3666 | free(nommu_save.argv); | 3688 | free(nommu_save.argv); |
| 3667 | free(nommu_save.argv_from_re_execing); | 3689 | free(nommu_save.argv_from_re_execing); |
| 3668 | free_strings_and_unsetenv(nommu_save.new_env, 1); | 3690 | free_strings_and_unset(nommu_save.new_env, 1); |
| 3669 | putenv_all(nommu_save.old_env); | 3691 | add_vars(nommu_save.old_vars); |
| 3670 | /* Free the pointers, but the strings themselves | ||
| 3671 | * are in environ now, don't use free_strings! */ | ||
| 3672 | free(nommu_save.old_env); | ||
| 3673 | #endif | 3692 | #endif |
| 3674 | free(argv_expanded); | 3693 | free(argv_expanded); |
| 3675 | argv_expanded = NULL; | 3694 | argv_expanded = NULL; |
diff --git a/shell/hush_test/hush-bugs/env_and_func.right b/shell/hush_test/hush-misc/env_and_func.right index 4a1545058..4a1545058 100644 --- a/shell/hush_test/hush-bugs/env_and_func.right +++ b/shell/hush_test/hush-misc/env_and_func.right | |||
diff --git a/shell/hush_test/hush-bugs/env_and_func.tests b/shell/hush_test/hush-misc/env_and_func.tests index d62c1af40..1d4eaf3a7 100755 --- a/shell/hush_test/hush-bugs/env_and_func.tests +++ b/shell/hush_test/hush-misc/env_and_func.tests | |||
| @@ -1,5 +1,3 @@ | |||
| 1 | # UNFIXED BUG | ||
| 2 | |||
| 3 | var=old | 1 | var=old |
| 4 | f() { echo "var=$var"; } | 2 | f() { echo "var=$var"; } |
| 5 | var=val f | 3 | var=val f |
