hush: export -n support

function                                             old     new   delta
builtin_export                                       206     256     +50
set_local_var                                        248     265     +17
expand_variables                                    2204    2203      -1
This commit is contained in:
Denis Vlasenko 2009-04-20 22:04:21 +00:00
parent d40fa397e4
commit ad4bd0548a
4 changed files with 95 additions and 12 deletions

View File

@ -232,6 +232,13 @@ config HUSH_FUNCTIONS
help help
Enable support for shell functions in hush. +800 bytes. Enable support for shell functions in hush. +800 bytes.
config HUSH_EXPORT_N
bool "Support export '-n' option"
default n
depends on HUSH
help
Enable support for export '-n' option in hush. It is a bash extension.
config LASH config LASH
bool "lash (deprecated: aliased to hush)" bool "lash (deprecated: aliased to hush)"
default n default n

View File

@ -1253,10 +1253,10 @@ static const char *get_local_var_value(const char *src)
/* str holds "NAME=VAL" and is expected to be malloced. /* str holds "NAME=VAL" and is expected to be malloced.
* We take ownership of it. * We take ownership of it.
* flg_export: * flg_export:
* 0: do not export * 0: do not change export flag
* 1: export * (if creating new variable, flag will be 0)
* -1: if NAME is set, leave export status alone * 1: set export flag and putenv the variable
* if NAME is not set, do not export * -1: clear export flag and unsetenv the variable
* flg_read_only is set only when we handle -R var=val * flg_read_only is set only when we handle -R var=val
*/ */
#if BB_MMU #if BB_MMU
@ -1297,6 +1297,7 @@ static int set_local_var(char *str, int flg_export, int flg_read_only)
free(str); free(str);
return -1; return -1;
} }
//TODO: optimize out redundant unsetenv/putenv's?
debug_printf_env("%s: unsetenv '%s'\n", __func__, str); debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
unsetenv(str); /* just in case */ unsetenv(str); /* just in case */
*value = '='; *value = '=';
@ -1331,8 +1332,13 @@ static int set_local_var(char *str, int flg_export, int flg_read_only)
if (flg_export == 1) if (flg_export == 1)
cur->flg_export = 1; cur->flg_export = 1;
if (cur->flg_export) { if (cur->flg_export) {
debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr); if (flg_export == -1) {
return putenv(cur->varstr); cur->flg_export = 0;
/* unsetenv was already done */
} else {
debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
return putenv(cur->varstr);
}
} }
return 0; return 0;
} }
@ -2214,7 +2220,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
val = NULL; val = NULL;
} else { } else {
char *new_var = xasprintf("%s=%s", var, val); char *new_var = xasprintf("%s=%s", var, val);
set_local_var(new_var, -1, 0); set_local_var(new_var, 0, 0);
} }
} }
} }
@ -6400,7 +6406,9 @@ static void print_escaped(const char *s)
static int builtin_export(char **argv) static int builtin_export(char **argv)
{ {
if (*++argv == NULL) { unsigned opt_unexport;
if (argv[1] == NULL) {
char **e = environ; char **e = environ;
if (e) { if (e) {
while (*e) { while (*e) {
@ -6426,15 +6434,33 @@ static int builtin_export(char **argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#if ENABLE_HUSH_EXPORT_N
opt_unexport = getopt32(argv, "+n"); /* "+": stop at 1st non-option */
argv += optind;
#else
opt_unexport = 0;
argv++;
#endif
do { do {
char *name = *argv; char *name = *argv;
/* So far we do not check that name is valid */ /* So far we do not check that name is valid (TODO?) */
if (strchr(name, '=') == NULL) { if (strchr(name, '=') == NULL) {
/* Exporting a name without a =VALUE */
struct variable *var; struct variable *var;
var = get_local_var(name); var = get_local_var(name);
if (opt_unexport) {
/* export -n NAME (without =VALUE) */
if (var) {
var->flg_export = 0;
debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
unsetenv(name);
} /* else: export -n NOT_EXISTING_VAR: no-op */
continue;
}
/* export NAME (without =VALUE) */
if (var) { if (var) {
var->flg_export = 1; var->flg_export = 1;
debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr); debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
@ -6448,10 +6474,13 @@ static int builtin_export(char **argv)
* We just set it to "" and export. */ * We just set it to "" and export. */
name = xasprintf("%s=", name); name = xasprintf("%s=", name);
} else { } else {
/* Exporting VAR=VALUE */ /* (Un)exporting NAME=VALUE */
name = xstrdup(name); name = xstrdup(name);
} }
set_local_var(name, 1, 0); set_local_var(name,
/*export:*/ (opt_unexport ? -1 : 1),
/*readonly:*/ 0
);
} while (*++argv); } while (*++argv);
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -0,0 +1,10 @@
export aaa1="'''"
export aaa2=''
export aaa3="'''"'abc'
export aaa8='8'
aaa9=9
aaa10=10
Nothing:
Nothing:
Nothing:
Done

View File

@ -0,0 +1,37 @@
export aaa1="'''"
export aaa2=""
export aaa3="'''abc"
export | grep aaa.=
export -n aaa1
unset aaa2; export -n aaa2="ghi"
export -n aaa3="klm"
export | grep aaa.=
export aaa4=4 aaa5=5
export -n aaa4=4n
export -n aaa5
export | grep aaa.=
export aaa5=5 aaa6=6 aaa7=7 aaa8=8
export -n aaa5 aaa6=6n aaa7
export | grep aaa.=
aaa9=9
export -n aaa9
set | grep ^aaa9=
export aaa10=10
export -n aaa10
set | grep ^aaa10=
export EXPORTED=qwe
export -nnnnnn nnnnnn; echo "Nothing:"; env | grep nnnnnn
export -n EXPORTED=123; echo "Nothing:"; env | grep ^EXPORTED
export EXPORTED=qwe
export -n EXPORTED; EXPORTED=123; echo "Nothing:"; env | grep ^EXPORTED
echo Done