aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-20 22:04:21 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-20 22:04:21 +0000
commitad4bd0548a5a9b630606ca95794cee8b31671c9a (patch)
tree41e681d086425d31f7ae0e0e36e94dff7bda40e0
parentd40fa397e45b35b62d1967a88036e06b4c061abe (diff)
downloadbusybox-w32-ad4bd0548a5a9b630606ca95794cee8b31671c9a.tar.gz
busybox-w32-ad4bd0548a5a9b630606ca95794cee8b31671c9a.tar.bz2
busybox-w32-ad4bd0548a5a9b630606ca95794cee8b31671c9a.zip
hush: export -n support
function old new delta builtin_export 206 256 +50 set_local_var 248 265 +17 expand_variables 2204 2203 -1
-rw-r--r--shell/Config.in7
-rw-r--r--shell/hush.c53
-rw-r--r--shell/hush_test/hush-misc/export-n.right10
-rwxr-xr-xshell/hush_test/hush-misc/export-n.tests37
4 files changed, 95 insertions, 12 deletions
diff --git a/shell/Config.in b/shell/Config.in
index 6cc11ce80..57969f02c 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -232,6 +232,13 @@ config HUSH_FUNCTIONS
232 help 232 help
233 Enable support for shell functions in hush. +800 bytes. 233 Enable support for shell functions in hush. +800 bytes.
234 234
235config HUSH_EXPORT_N
236 bool "Support export '-n' option"
237 default n
238 depends on HUSH
239 help
240 Enable support for export '-n' option in hush. It is a bash extension.
241
235config LASH 242config LASH
236 bool "lash (deprecated: aliased to hush)" 243 bool "lash (deprecated: aliased to hush)"
237 default n 244 default n
diff --git a/shell/hush.c b/shell/hush.c
index d08652656..d59a5de82 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1253,10 +1253,10 @@ static const char *get_local_var_value(const char *src)
1253/* str holds "NAME=VAL" and is expected to be malloced. 1253/* str holds "NAME=VAL" and is expected to be malloced.
1254 * We take ownership of it. 1254 * We take ownership of it.
1255 * flg_export: 1255 * flg_export:
1256 * 0: do not export 1256 * 0: do not change export flag
1257 * 1: export 1257 * (if creating new variable, flag will be 0)
1258 * -1: if NAME is set, leave export status alone 1258 * 1: set export flag and putenv the variable
1259 * if NAME is not set, do not export 1259 * -1: clear export flag and unsetenv the variable
1260 * flg_read_only is set only when we handle -R var=val 1260 * flg_read_only is set only when we handle -R var=val
1261 */ 1261 */
1262#if BB_MMU 1262#if BB_MMU
@@ -1297,6 +1297,7 @@ static int set_local_var(char *str, int flg_export, int flg_read_only)
1297 free(str); 1297 free(str);
1298 return -1; 1298 return -1;
1299 } 1299 }
1300//TODO: optimize out redundant unsetenv/putenv's?
1300 debug_printf_env("%s: unsetenv '%s'\n", __func__, str); 1301 debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
1301 unsetenv(str); /* just in case */ 1302 unsetenv(str); /* just in case */
1302 *value = '='; 1303 *value = '=';
@@ -1331,8 +1332,13 @@ static int set_local_var(char *str, int flg_export, int flg_read_only)
1331 if (flg_export == 1) 1332 if (flg_export == 1)
1332 cur->flg_export = 1; 1333 cur->flg_export = 1;
1333 if (cur->flg_export) { 1334 if (cur->flg_export) {
1334 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr); 1335 if (flg_export == -1) {
1335 return putenv(cur->varstr); 1336 cur->flg_export = 0;
1337 /* unsetenv was already done */
1338 } else {
1339 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
1340 return putenv(cur->varstr);
1341 }
1336 } 1342 }
1337 return 0; 1343 return 0;
1338} 1344}
@@ -2214,7 +2220,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2214 val = NULL; 2220 val = NULL;
2215 } else { 2221 } else {
2216 char *new_var = xasprintf("%s=%s", var, val); 2222 char *new_var = xasprintf("%s=%s", var, val);
2217 set_local_var(new_var, -1, 0); 2223 set_local_var(new_var, 0, 0);
2218 } 2224 }
2219 } 2225 }
2220 } 2226 }
@@ -6400,7 +6406,9 @@ static void print_escaped(const char *s)
6400 6406
6401static int builtin_export(char **argv) 6407static int builtin_export(char **argv)
6402{ 6408{
6403 if (*++argv == NULL) { 6409 unsigned opt_unexport;
6410
6411 if (argv[1] == NULL) {
6404 char **e = environ; 6412 char **e = environ;
6405 if (e) { 6413 if (e) {
6406 while (*e) { 6414 while (*e) {
@@ -6426,15 +6434,33 @@ static int builtin_export(char **argv)
6426 return EXIT_SUCCESS; 6434 return EXIT_SUCCESS;
6427 } 6435 }
6428 6436
6437#if ENABLE_HUSH_EXPORT_N
6438 opt_unexport = getopt32(argv, "+n"); /* "+": stop at 1st non-option */
6439 argv += optind;
6440#else
6441 opt_unexport = 0;
6442 argv++;
6443#endif
6444
6429 do { 6445 do {
6430 char *name = *argv; 6446 char *name = *argv;
6431 6447
6432 /* So far we do not check that name is valid */ 6448 /* So far we do not check that name is valid (TODO?) */
6449
6433 if (strchr(name, '=') == NULL) { 6450 if (strchr(name, '=') == NULL) {
6434 /* Exporting a name without a =VALUE */
6435 struct variable *var; 6451 struct variable *var;
6436 6452
6437 var = get_local_var(name); 6453 var = get_local_var(name);
6454 if (opt_unexport) {
6455 /* export -n NAME (without =VALUE) */
6456 if (var) {
6457 var->flg_export = 0;
6458 debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
6459 unsetenv(name);
6460 } /* else: export -n NOT_EXISTING_VAR: no-op */
6461 continue;
6462 }
6463 /* export NAME (without =VALUE) */
6438 if (var) { 6464 if (var) {
6439 var->flg_export = 1; 6465 var->flg_export = 1;
6440 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr); 6466 debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
@@ -6448,10 +6474,13 @@ static int builtin_export(char **argv)
6448 * We just set it to "" and export. */ 6474 * We just set it to "" and export. */
6449 name = xasprintf("%s=", name); 6475 name = xasprintf("%s=", name);
6450 } else { 6476 } else {
6451 /* Exporting VAR=VALUE */ 6477 /* (Un)exporting NAME=VALUE */
6452 name = xstrdup(name); 6478 name = xstrdup(name);
6453 } 6479 }
6454 set_local_var(name, 1, 0); 6480 set_local_var(name,
6481 /*export:*/ (opt_unexport ? -1 : 1),
6482 /*readonly:*/ 0
6483 );
6455 } while (*++argv); 6484 } while (*++argv);
6456 6485
6457 return EXIT_SUCCESS; 6486 return EXIT_SUCCESS;
diff --git a/shell/hush_test/hush-misc/export-n.right b/shell/hush_test/hush-misc/export-n.right
new file mode 100644
index 000000000..3d55bf752
--- /dev/null
+++ b/shell/hush_test/hush-misc/export-n.right
@@ -0,0 +1,10 @@
1export aaa1="'''"
2export aaa2=''
3export aaa3="'''"'abc'
4export aaa8='8'
5aaa9=9
6aaa10=10
7Nothing:
8Nothing:
9Nothing:
10Done
diff --git a/shell/hush_test/hush-misc/export-n.tests b/shell/hush_test/hush-misc/export-n.tests
new file mode 100755
index 000000000..5252a1e14
--- /dev/null
+++ b/shell/hush_test/hush-misc/export-n.tests
@@ -0,0 +1,37 @@
1export aaa1="'''"
2export aaa2=""
3export aaa3="'''abc"
4export | grep aaa.=
5
6export -n aaa1
7unset aaa2; export -n aaa2="ghi"
8export -n aaa3="klm"
9export | grep aaa.=
10
11export aaa4=4 aaa5=5
12export -n aaa4=4n
13export -n aaa5
14export | grep aaa.=
15
16export aaa5=5 aaa6=6 aaa7=7 aaa8=8
17export -n aaa5 aaa6=6n aaa7
18export | grep aaa.=
19
20aaa9=9
21export -n aaa9
22set | grep ^aaa9=
23
24export aaa10=10
25export -n aaa10
26set | grep ^aaa10=
27
28
29export EXPORTED=qwe
30export -nnnnnn nnnnnn; echo "Nothing:"; env | grep nnnnnn
31
32export -n EXPORTED=123; echo "Nothing:"; env | grep ^EXPORTED
33
34export EXPORTED=qwe
35export -n EXPORTED; EXPORTED=123; echo "Nothing:"; env | grep ^EXPORTED
36
37echo Done