mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Fix unsetting aliases in subshells
Aliases can now be correctly unset within subshell environments (such as ( ... ), $(command substitutions), etc), as well as non-subshell "shared" command substitutions (${ ...; }). Before, attempts to unset aliases within these were silently ignored. Prior discussion: https://github.com/att/ast/issues/108 Subshell alias trees are only referenced in a few places in the code, *and* have always been broken, so this commit gets rid of the whole notion of a subshell alias tree. Instead, there is now just one flat alias tree, and subshells fork into a separate process when aliases are set or unset within them. It is not really conceivable that this could be a performance-sensitive operation, or even a common one, so this is a clean fix with no downside. src/cmd/ksh93/include/defs.h: - Remove sh_subaliastree() definition. src/cmd/ksh93/sh/subshell.c: - Remove salias element (pointer to subshell alias tree) from subshell struct. - Remove sh_subaliastree() function. - sh_subshell(): Remove alias subshell tree cleanup. src/cmd/ksh93/bltins/typeset.c: - b_alias(): If in subshell, fork before setting alias. - b_unalias(): If in subshell, fork before unsetting alias. - unall(): Remove sh_subaliastree() call. src/cmd/ksh93/sh/name.c: - nv_open(): Remove sh_subaliastree() call. src/cmd/ksh93/tests/subshell.sh: - Add regression tests for unsetting or redefining aliases within subshells. (cherry picked from commit 12a15605b9521a2564a6e657905705a060e89095)
This commit is contained in:
parent
047cb3303c
commit
ec888867fd
6 changed files with 36 additions and 32 deletions
3
NEWS
3
NEWS
|
@ -18,6 +18,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
||||||
This now correctly lists your directory and then prints "ls executed",
|
This now correctly lists your directory and then prints "ls executed",
|
||||||
instead of printing "ls executed" twice.
|
instead of printing "ls executed" twice.
|
||||||
|
|
||||||
|
- Fix a similar bug with aliases. These can now be correctly unset
|
||||||
|
in subshell environments.
|
||||||
|
|
||||||
2020-05-21:
|
2020-05-21:
|
||||||
|
|
||||||
- Fix truncating of files with the combined redirections '<>;file' and
|
- Fix truncating of files with the combined redirections '<>;file' and
|
||||||
|
|
|
@ -197,6 +197,8 @@ int b_alias(int argc,register char *argv[],Shbltin_t *context)
|
||||||
troot = tdata.sh->track_tree;
|
troot = tdata.sh->track_tree;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(context->shp->subshell && !context->shp->subshare)
|
||||||
|
sh_subfork();
|
||||||
return(setall(argv,flag,troot,&tdata));
|
return(setall(argv,flag,troot,&tdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,6 +1144,8 @@ int b_set(int argc,register char *argv[],Shbltin_t *context)
|
||||||
int b_unalias(int argc,register char *argv[],Shbltin_t *context)
|
int b_unalias(int argc,register char *argv[],Shbltin_t *context)
|
||||||
{
|
{
|
||||||
Shell_t *shp = context->shp;
|
Shell_t *shp = context->shp;
|
||||||
|
if(shp->subshell && !shp->subshare)
|
||||||
|
sh_subfork();
|
||||||
return(unall(argc,argv,shp->alias_tree,shp));
|
return(unall(argc,argv,shp->alias_tree,shp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1161,11 +1165,7 @@ static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
|
||||||
struct checkpt buff;
|
struct checkpt buff;
|
||||||
NOT_USED(argc);
|
NOT_USED(argc);
|
||||||
if(troot==shp->alias_tree)
|
if(troot==shp->alias_tree)
|
||||||
{
|
|
||||||
name = sh_optunalias;
|
name = sh_optunalias;
|
||||||
if(shp->subshell)
|
|
||||||
troot = sh_subaliastree(0);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
name = sh_optunset;
|
name = sh_optunset;
|
||||||
while(r = optget(argv,name)) switch(r)
|
while(r = optget(argv,name)) switch(r)
|
||||||
|
|
|
@ -423,7 +423,6 @@ extern void sh_printopts(Shopt_t,int,Shopt_t*);
|
||||||
extern int sh_readline(Shell_t*,char**,volatile int,int,ssize_t,long);
|
extern int sh_readline(Shell_t*,char**,volatile int,int,ssize_t,long);
|
||||||
extern Sfio_t *sh_sfeval(char*[]);
|
extern Sfio_t *sh_sfeval(char*[]);
|
||||||
extern void sh_setmatch(Shell_t*,const char*,int,int,int[],int);
|
extern void sh_setmatch(Shell_t*,const char*,int,int,int[],int);
|
||||||
extern Dt_t *sh_subaliastree(int);
|
|
||||||
extern void sh_scope(Shell_t*, struct argnod*, int);
|
extern void sh_scope(Shell_t*, struct argnod*, int);
|
||||||
extern Namval_t *sh_scoped(Shell_t*, Namval_t*);
|
extern Namval_t *sh_scoped(Shell_t*, Namval_t*);
|
||||||
extern Dt_t *sh_subfuntree(int);
|
extern Dt_t *sh_subfuntree(int);
|
||||||
|
|
|
@ -1390,8 +1390,6 @@ Namval_t *nv_open(const char *name, Dt_t *root, int flags)
|
||||||
msg = e_aliname;
|
msg = e_aliname;
|
||||||
while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
|
while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
|
||||||
(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
|
(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
|
||||||
if(shp->subshell && c=='=')
|
|
||||||
root = sh_subaliastree(1);
|
|
||||||
if(c= *--cp)
|
if(c= *--cp)
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
|
np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
|
||||||
|
|
|
@ -71,7 +71,6 @@ static struct subshell
|
||||||
Dt_t *var; /* variable table at time of subshell */
|
Dt_t *var; /* variable table at time of subshell */
|
||||||
struct Link *svar; /* save shell variable table */
|
struct Link *svar; /* save shell variable table */
|
||||||
Dt_t *sfun; /* function scope for subshell */
|
Dt_t *sfun; /* function scope for subshell */
|
||||||
Dt_t *salias;/* alias scope for subshell */
|
|
||||||
Pathcomp_t *pathlist; /* for PATH variable */
|
Pathcomp_t *pathlist; /* for PATH variable */
|
||||||
#if (ERROR_VERSION >= 20030214L)
|
#if (ERROR_VERSION >= 20030214L)
|
||||||
struct Error_context_s *errcontext;
|
struct Error_context_s *errcontext;
|
||||||
|
@ -375,24 +374,6 @@ static void nv_restore(struct subshell *sp)
|
||||||
sp->shpwd=save;
|
sp->shpwd=save;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* return pointer to alias tree
|
|
||||||
* create new one if in a subshell and one doesn't exist and create is non-zero
|
|
||||||
*/
|
|
||||||
Dt_t *sh_subaliastree(int create)
|
|
||||||
{
|
|
||||||
register struct subshell *sp = subshell_data;
|
|
||||||
if(!sp || sp->shp->curenv==0)
|
|
||||||
return(sh.alias_tree);
|
|
||||||
if(!sp->salias && create)
|
|
||||||
{
|
|
||||||
sp->salias = dtopen(&_Nvdisc,Dtoset);
|
|
||||||
dtview(sp->salias,sp->shp->alias_tree);
|
|
||||||
sp->shp->alias_tree = sp->salias;
|
|
||||||
}
|
|
||||||
return(sp->salias);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return pointer to function tree
|
* return pointer to function tree
|
||||||
* create new one if in a subshell and one doesn't exist and create is non-zero
|
* create new one if in a subshell and one doesn't exist and create is non-zero
|
||||||
|
@ -710,12 +691,6 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
shp->options = sp->options;
|
shp->options = sp->options;
|
||||||
if(sp->salias)
|
|
||||||
{
|
|
||||||
shp->alias_tree = dtview(sp->salias,0);
|
|
||||||
table_unset(sp->salias,0);
|
|
||||||
dtclose(sp->salias);
|
|
||||||
}
|
|
||||||
if(sp->sfun)
|
if(sp->sfun)
|
||||||
{
|
{
|
||||||
shp->fun_tree = dtview(sp->sfun,0);
|
shp->fun_tree = dtview(sp->sfun,0);
|
||||||
|
|
|
@ -652,5 +652,34 @@ v=$("$SHELL" -c "$(cat "$a")") && [[ $v == ok ]] || err_exit 'fail: more fun 2'
|
||||||
v=$("$SHELL" -c 'eval "$(cat "$1")"' x "$a") && [[ $v == ok ]] || err_exit "fail: more fun 3"
|
v=$("$SHELL" -c 'eval "$(cat "$1")"' x "$a") && [[ $v == ok ]] || err_exit "fail: more fun 3"
|
||||||
v=$("$SHELL" -c '. "$1"' x "$a") && [[ $v == ok ]] || err_exit "fail: more fun 4"
|
v=$("$SHELL" -c '. "$1"' x "$a") && [[ $v == ok ]] || err_exit "fail: more fun 4"
|
||||||
|
|
||||||
|
# ======
|
||||||
|
# Unsetting or redefining aliases within subshells
|
||||||
|
|
||||||
|
# ...alias can be unset in subshell
|
||||||
|
|
||||||
|
alias al="echo 'mainalias'"
|
||||||
|
|
||||||
|
(unalias al; alias al >/dev/null) && err_exit 'alias fails to be unset in subshell'
|
||||||
|
|
||||||
|
v=$(unalias al; alias al >/dev/null) && err_exit 'alias fails to be unset in comsub'
|
||||||
|
|
||||||
|
[[ $(eval 'al') == 'mainalias' ]] || err_exit 'main alias fails to survive unset in subshell(s)'
|
||||||
|
|
||||||
|
v=${ eval 'al'; unalias al 2>&1; } && [[ $v == 'mainalias' ]] && ! alias al >/dev/null \
|
||||||
|
|| err_exit 'main shell alias wrongly survives unset within ${ ...; }'
|
||||||
|
|
||||||
|
# ...alias can be redefined in subshell
|
||||||
|
|
||||||
|
alias al="echo 'mainalias'"
|
||||||
|
|
||||||
|
(alias al='echo sub'; [[ $(eval 'al') == sub ]]) || err_exit 'alias fails to be redefined in subshell'
|
||||||
|
|
||||||
|
v=$(alias al='echo sub'; eval 'al') && [[ $v == sub ]] || err_exit 'alias fails to be redefined in comsub'
|
||||||
|
|
||||||
|
[[ $(eval 'al') == 'mainalias' ]] || err_exit 'main alias fails to survive redefinition in subshell(s)'
|
||||||
|
|
||||||
|
v=${ eval 'al'; alias al='echo subshare'; } && [[ $v == 'mainalias' && $(eval 'al') == subshare ]] \
|
||||||
|
|| err_exit 'alias redefinition fails to survive ${ ...; }'
|
||||||
|
|
||||||
# ======
|
# ======
|
||||||
exit $((Errors<125?Errors:125))
|
exit $((Errors<125?Errors:125))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue