ash: [VAR] Move unsetvar functionality into setvareq

Upstream commit:

    Date: Tue, 25 May 2010 20:55:05 +0800
    [VAR] Move unsetvar functionality into setvareq

    This patch moves the unsetvar code into setvareq so that we can
    no have a pathological case of an unset variable hanging around
    unless it has a bit pinning it like VEXPORT.

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

function                                             old     new   delta
setvareq                                             227     303     +76
expmeta                                              517     521      +4
localcmd                                             364     366      +2
unsetcmd                                              96      76     -20
unsetvar                                             129       7    -122
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/2 up/down: 82/-142)           Total: -60 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-07-25 16:29:36 +02:00
parent be669fa1fd
commit b28d4c3462
6 changed files with 81 additions and 46 deletions

View File

@ -2269,11 +2269,22 @@ setvareq(char *s, int flags)
if (!(vp->flags & (VTEXTFIXED|VSTACK))) if (!(vp->flags & (VTEXTFIXED|VSTACK)))
free((char*)vp->var_text); 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); flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
} else { } else {
/* variable s is not found */ /* variable s is not found */
if (flags & VNOSET) if (flags & VNOSET)
return; return;
if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
goto out_free;
vp = ckzalloc(sizeof(*vp)); vp = ckzalloc(sizeof(*vp));
vp->next = *vpp; vp->next = *vpp;
/*vp->func = NULL; - ckzalloc did it */ /*vp->func = NULL; - ckzalloc did it */
@ -2331,43 +2342,10 @@ setvar0(const char *name, const char *val)
/* /*
* Unset the specified variable. * Unset the specified variable.
*/ */
static int static void
unsetvar(const char *s) 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); setvar0(s, NULL);
vp->flags &= ~VEXPORT;
}
ok:
retval = 0;
}
out:
return retval;
} }
/* /*
@ -13218,7 +13196,6 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
char **ap; char **ap;
int i; int i;
int flag = 0; int flag = 0;
int ret = 0;
while ((i = nextopt("vf")) != 0) { while ((i = nextopt("vf")) != 0) {
flag = i; flag = i;
@ -13226,15 +13203,13 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
for (ap = argptr; *ap; ap++) { for (ap = argptr; *ap; ap++) {
if (flag != 'f') { if (flag != 'f') {
i = unsetvar(*ap); unsetvar(*ap);
ret |= i;
if (!(i & 2))
continue; continue;
} }
if (flag != 'v') if (flag != 'v')
unsetfunc(*ap); unsetfunc(*ap);
} }
return ret & 1; return 0;
} }
static const unsigned char timescmd_str[] ALIGN1 = { static const unsigned char timescmd_str[] ALIGN1 = {

View File

@ -10,4 +10,4 @@ Fail:2
./readonly0.tests: export: line 27: a: is read only ./readonly0.tests: export: line 27: a: is read only
Fail:2 Fail:2
Fail:1 ./readonly0.tests: unset: line 44: a: is read only

View File

@ -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

View File

@ -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

View File

@ -12,7 +12,7 @@ ___
0 f g 0 f g
0 0
___ ___
hush: HUSH_VERSION: readonly variable hush: VAR_RO: readonly variable
1 f g 1 f g
hush: HUSH_VERSION: readonly variable hush: VAR_RO: readonly variable
1 1

View File

@ -1,4 +1,5 @@
# check invalid options are rejected # check invalid options are rejected
# bash: in posix mode, aborts if non-interactive
unset - unset -
echo $? echo $?
unset -m a b c unset -m a b c
@ -30,7 +31,9 @@ echo $? $f $g
# check read only vars # check read only vars
echo ___ echo ___
f=f g=g f=f g=g
unset HUSH_VERSION VAR_RO=1
readonly VAR_RO
unset VAR_RO
echo $? $f $g echo $? $f $g
unset f HUSH_VERSION g unset f VAR_RO g
echo $? $f $g echo $? $f $g