aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c57
-rw-r--r--shell/ash_test/ash-vars/readonly0.right2
-rw-r--r--shell/ash_test/ash-vars/unset.right17
-rwxr-xr-xshell/ash_test/ash-vars/unset.tests40
-rw-r--r--shell/hush_test/hush-vars/unset.right4
-rwxr-xr-xshell/hush_test/hush-vars/unset.tests7
6 files changed, 81 insertions, 46 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 0ae086e98..72ceba782 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2269,11 +2269,22 @@ setvareq(char *s, int flags)
if (!(vp->flags & (VTEXTFIXED|VSTACK)))
free((char*)vp->var_text);
+ if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
+ *vpp = vp->next;
+ free(vp);
+ out_free:
+ if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
+ free(s);
+ return;
+ }
+
flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
} else {
/* variable s is not found */
if (flags & VNOSET)
return;
+ if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
+ goto out_free;
vp = ckzalloc(sizeof(*vp));
vp->next = *vpp;
/*vp->func = NULL; - ckzalloc did it */
@@ -2331,43 +2342,10 @@ setvar0(const char *name, const char *val)
/*
* Unset the specified variable.
*/
-static int
+static void
unsetvar(const char *s)
{
- struct var **vpp;
- struct var *vp;
- int retval;
-
- vpp = findvar(hashvar(s), s);
- vp = *vpp;
- retval = 2;
- if (vp) {
- int flags = vp->flags;
-
- retval = 1;
- if (flags & VREADONLY)
- goto out;
-#if ENABLE_ASH_RANDOM_SUPPORT
- vp->flags &= ~VDYNAMIC;
-#endif
- if (flags & VUNSET)
- goto ok;
- if ((flags & VSTRFIXED) == 0) {
- INT_OFF;
- if ((flags & (VTEXTFIXED|VSTACK)) == 0)
- free((char*)vp->var_text);
- *vpp = vp->next;
- free(vp);
- INT_ON;
- } else {
- setvar0(s, NULL);
- vp->flags &= ~VEXPORT;
- }
- ok:
- retval = 0;
- }
- out:
- return retval;
+ setvar0(s, NULL);
}
/*
@@ -13218,7 +13196,6 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
char **ap;
int i;
int flag = 0;
- int ret = 0;
while ((i = nextopt("vf")) != 0) {
flag = i;
@@ -13226,15 +13203,13 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
for (ap = argptr; *ap; ap++) {
if (flag != 'f') {
- i = unsetvar(*ap);
- ret |= i;
- if (!(i & 2))
- continue;
+ unsetvar(*ap);
+ continue;
}
if (flag != 'v')
unsetfunc(*ap);
}
- return ret & 1;
+ return 0;
}
static const unsigned char timescmd_str[] ALIGN1 = {
diff --git a/shell/ash_test/ash-vars/readonly0.right b/shell/ash_test/ash-vars/readonly0.right
index f3a6bde9e..ecc4054f8 100644
--- a/shell/ash_test/ash-vars/readonly0.right
+++ b/shell/ash_test/ash-vars/readonly0.right
@@ -10,4 +10,4 @@ Fail:2
./readonly0.tests: export: line 27: a: is read only
Fail:2
-Fail:1
+./readonly0.tests: unset: line 44: a: is read only
diff --git a/shell/ash_test/ash-vars/unset.right b/shell/ash_test/ash-vars/unset.right
new file mode 100644
index 000000000..77d5abe9e
--- /dev/null
+++ b/shell/ash_test/ash-vars/unset.right
@@ -0,0 +1,17 @@
+./unset.tests: unset: line 3: -: bad variable name
+2
+./unset.tests: unset: line 5: illegal option -m
+2
+0
+___
+0 f g
+0 g
+0
+___
+0 f g
+0
+0 f g
+0
+___
+./unset.tests: unset: line 36: VAR_RO: is read only
+2 f g
diff --git a/shell/ash_test/ash-vars/unset.tests b/shell/ash_test/ash-vars/unset.tests
new file mode 100755
index 000000000..11b392744
--- /dev/null
+++ b/shell/ash_test/ash-vars/unset.tests
@@ -0,0 +1,40 @@
+# check invalid options are rejected
+# bash: in posix mode, aborts if non-interactive; using subshell to avoid that
+(unset -)
+echo $?
+(unset -m a b c)
+echo $?
+
+# check funky usage
+unset
+echo $?
+
+# check normal usage
+echo ___
+f=f g=g
+echo $? $f $g
+unset f
+echo $? $f $g
+unset g
+echo $? $f $g
+
+echo ___
+f=f g=g
+echo $? $f $g
+unset f g
+echo $? $f $g
+f=f g=g
+echo $? $f $g
+unset -v f g
+echo $? $f $g
+
+# check read only vars
+echo ___
+f=f g=g
+VAR_RO=1
+readonly VAR_RO
+(unset VAR_RO)
+echo $? $f $g
+# not testing "do variables survive error halfway through unset" since unset aborts
+# unset f VAR_RO g
+#echo $? $f $g
diff --git a/shell/hush_test/hush-vars/unset.right b/shell/hush_test/hush-vars/unset.right
index 1fbe76a73..097274201 100644
--- a/shell/hush_test/hush-vars/unset.right
+++ b/shell/hush_test/hush-vars/unset.right
@@ -12,7 +12,7 @@ ___
0 f g
0
___
-hush: HUSH_VERSION: readonly variable
+hush: VAR_RO: readonly variable
1 f g
-hush: HUSH_VERSION: readonly variable
+hush: VAR_RO: readonly variable
1
diff --git a/shell/hush_test/hush-vars/unset.tests b/shell/hush_test/hush-vars/unset.tests
index f59ce5923..81243fbf9 100755
--- a/shell/hush_test/hush-vars/unset.tests
+++ b/shell/hush_test/hush-vars/unset.tests
@@ -1,4 +1,5 @@
# check invalid options are rejected
+# bash: in posix mode, aborts if non-interactive
unset -
echo $?
unset -m a b c
@@ -30,7 +31,9 @@ echo $? $f $g
# check read only vars
echo ___
f=f g=g
-unset HUSH_VERSION
+VAR_RO=1
+readonly VAR_RO
+unset VAR_RO
echo $? $f $g
-unset f HUSH_VERSION g
+unset f VAR_RO g
echo $? $f $g