/* str holds "NAME=VAL" and is expected to be malloced.
* We take ownership of it.
- * flg_export:
- * 0: do not change export flag
- * (if creating new variable, flag will be 0)
- * 1: set export flag and putenv the variable
- * -1: clear export flag and unsetenv the variable
- * flg_read_only is set only when we handle -R var=val
*/
-static int set_local_var(char *str,
- int flg_export UNUSED_PARAM,
- int local_lvl UNUSED_PARAM,
- int flg_read_only UNUSED_PARAM)
+#define SETFLAG_EXPORT (1 << 0)
+#define SETFLAG_UNEXPORT (1 << 1)
+#define SETFLAG_MAKE_RO (1 << 2)
+#define SETFLAG_LOCAL_SHIFT 3
+static int set_local_var(char *str, unsigned flags)
{
struct variable **var_pp;
struct variable *cur;
char *free_me = NULL;
char *eq_sign;
int name_len;
+ IF_HUSH_LOCAL(unsigned local_lvl = (flags >> SETFLAG_LOCAL_SHIFT);)
- //bb_error_msg("set_local_var('%s',%d,%d,%d)", str, flg_export, local_lvl, flg_read_only);
eq_sign = strchr(str, '=');
if (!eq_sign) { /* not expected to ever happen? */
free(str);
free(str);
return -1;
}
- if (flg_export == -1) { // "&& cur->flg_export" ?
+ if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
*eq_sign = '\0';
unsetenv(str);
* z=z
*/
if (cur->flg_export)
- flg_export = 1;
+ flags |= SETFLAG_EXPORT;
break;
}
#endif
/* Not found - create new variable struct */
cur = xzalloc(sizeof(*cur));
-#if ENABLE_HUSH_LOCAL
- cur->func_nest_level = local_lvl;
-#endif
+ IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
cur->next = *var_pp;
*var_pp = cur;
cur->varstr = str;
exp:
#if !BB_MMU || ENABLE_HUSH_READONLY
- if (flg_read_only != 0) {
- cur->flg_read_only = flg_read_only;
+ if (flags & SETFLAG_MAKE_RO) {
+ cur->flg_read_only = 1;
}
#endif
- if (flg_export == 1)
+ if (flags & SETFLAG_EXPORT)
cur->flg_export = 1;
if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
cmdedit_update_prompt();
if (cur->flg_export) {
- if (flg_export == -1) {
+ if (flags & SETFLAG_UNEXPORT) {
cur->flg_export = 0;
/* unsetenv was already done */
} else {
}
/* Used at startup and after each cd */
-static void set_pwd_var(int exp)
+static void set_pwd_var(unsigned flag)
{
- set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)),
- /*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
}
static int unset_local_var_len(const char *name, int name_len)
static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
{
char *var = xasprintf("%s=%s", name, val);
- set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(var, /*flag:*/ 0);
}
#endif
var_p->next = old;
old = var_p;
}
- set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(*s, SETFLAG_EXPORT);
}
s++;
}
val = NULL;
} else {
char *new_var = xasprintf("%s=%s", var, val);
- set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(new_var, /*flag:*/ 0);
}
}
}
if (new_env) {
argv = new_env;
while (*argv) {
- set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(*argv, /*flag:*/ 0);
/* Do we need to flag set_local_var() errors?
* "assignment to readonly var" and "putenv error"
*/
fprintf(stderr, " %s", p);
debug_printf_exec("set shell var:'%s'->'%s'\n",
*argv, p);
- set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(p, /*flag:*/ 0);
/* Do we need to flag set_local_var() errors?
* "assignment to readonly var" and "putenv error"
*/
}
/* Insert next value from for_lcur */
/* note: *for_lcur already has quotes removed, $var expanded, etc */
- set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
+ set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
continue;
}
if (rword == RES_IN) {
putenv(shell_ver->varstr);
/* Export PWD */
- set_pwd_var(/*exp:*/ 1);
+ set_pwd_var(SETFLAG_EXPORT);
#if BASH_HOSTNAME_VAR
/* Set (but not export) HOSTNAME unless already set */
}
case 'R':
case 'V':
- set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R');
+ set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
break;
# if ENABLE_HUSH_FUNCTIONS
case 'F': {
* Note: do not enforce exporting. If PWD was unset or unexported,
* set it again, but do not export. bash does the same.
*/
- set_pwd_var(/*exp:*/ 0);
+ set_pwd_var(/*flag:*/ 0);
return EXIT_SUCCESS;
}
#endif
#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
-static int helper_export_local(char **argv,
- int exp UNUSED_PARAM,
- int ro UNUSED_PARAM,
- int lvl UNUSED_PARAM)
+static int helper_export_local(char **argv, unsigned flags)
{
do {
char *name = *argv;
vpp = get_ptr_to_local_var(name, name_end - name);
var = vpp ? *vpp : NULL;
- if (exp == -1) { /* unexporting? */
+ if (flags & SETFLAG_UNEXPORT) {
/* export -n NAME (without =VALUE) */
if (var) {
var->flg_export = 0;
} /* else: export -n NOT_EXISTING_VAR: no-op */
continue;
}
- if (exp == 1) { /* exporting? */
+ if (flags & SETFLAG_EXPORT) {
/* export NAME (without =VALUE) */
if (var) {
var->flg_export = 1;
}
# if ENABLE_HUSH_LOCAL
/* Is this "local" bltin? */
- if (exp == 0
- IF_HUSH_READONLY(&& ro == 0) /* in !READONLY config, always true */
- ) {
+ if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
+ unsigned lvl = flags >> SETFLAG_LOCAL_SHIFT;
if (var && var->func_nest_level == lvl) {
/* "local x=abc; ...; local x" - ignore second local decl */
continue;
/* (Un)exporting/making local NAME=VALUE */
name = xstrdup(name);
}
- set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ ro);
+ set_local_var(name, flags);
} while (*++argv);
return EXIT_SUCCESS;
}
return EXIT_SUCCESS;
}
- return helper_export_local(argv, /*exp:*/ (opt_unexport ? -1 : 1), /*ro:*/ 0, /*lvl:*/ 0);
+ return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
}
#endif
return EXIT_FAILURE; /* bash compat */
}
argv++;
- return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 0, /*lvl:*/ G.func_nest_level);
+ return helper_export_local(argv, G.func_nest_level << SETFLAG_LOCAL_SHIFT);
}
#endif
#if ENABLE_HUSH_READONLY
static int FAST_FUNC builtin_readonly(char **argv)
{
- if (*++argv == NULL) {
+ argv++;
+ if (*argv == NULL) {
/* bash: readonly [-p]: list all readonly VARs
* (-p has no effect in bash)
*/
}
return EXIT_SUCCESS;
}
- return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 1, /*lvl:*/ 0);
+ return helper_export_local(argv, SETFLAG_MAKE_RO);
}
#endif