sh: Expand aliases after assignments and redirections.
This commit is contained in:
parent
aa27d9ef94
commit
05a447d0b9
@ -714,15 +714,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
oexitstatus = exitstatus;
|
||||
exitstatus = 0;
|
||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||
char *p = argp->narg.text;
|
||||
if (varflag && is_name(*p)) {
|
||||
do {
|
||||
p++;
|
||||
} while (is_in_name(*p));
|
||||
if (*p == '=') {
|
||||
expandarg(argp, &varlist, EXP_VARTILDE);
|
||||
continue;
|
||||
}
|
||||
if (varflag && isassignment(argp->narg.text)) {
|
||||
expandarg(argp, &varlist, EXP_VARTILDE);
|
||||
continue;
|
||||
}
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
varflag = 0;
|
||||
|
@ -619,6 +619,7 @@ simplecmd(union node **rpp, union node *redir)
|
||||
union node **orig_rpp = rpp;
|
||||
union node *n = NULL;
|
||||
int special;
|
||||
int savecheckkwd;
|
||||
|
||||
/* If we don't have any redirections already, then we must reset */
|
||||
/* rpp to be the address of the local redir variable. */
|
||||
@ -634,7 +635,10 @@ simplecmd(union node **rpp, union node *redir)
|
||||
*/
|
||||
orig_rpp = rpp;
|
||||
|
||||
savecheckkwd = CHKALIAS;
|
||||
|
||||
for (;;) {
|
||||
checkkwd = savecheckkwd;
|
||||
if (readtoken() == TWORD) {
|
||||
n = (union node *)stalloc(sizeof (struct narg));
|
||||
n->type = NARG;
|
||||
@ -642,6 +646,8 @@ simplecmd(union node **rpp, union node *redir)
|
||||
n->narg.backquote = backquotelist;
|
||||
*app = n;
|
||||
app = &n->narg.next;
|
||||
if (savecheckkwd != 0 && !isassignment(wordtext))
|
||||
savecheckkwd = 0;
|
||||
} else if (lasttoken == TREDIR) {
|
||||
*rpp = n = redirnode;
|
||||
rpp = &n->nfile.next;
|
||||
@ -1859,6 +1865,22 @@ goodname(const char *name)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isassignment(const char *p)
|
||||
{
|
||||
if (!is_name(*p))
|
||||
return 0;
|
||||
p++;
|
||||
for (;;) {
|
||||
if (*p == '=')
|
||||
return 1;
|
||||
else if (!is_in_name(*p))
|
||||
return 0;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when an unexpected token is read during the parse. The argument
|
||||
* is the token that is expected, or -1 if more than one type of token can
|
||||
|
@ -80,4 +80,5 @@ extern const char *const parsekwd[];
|
||||
union node *parsecmd(int);
|
||||
void fixredir(union node *, const char *, int);
|
||||
int goodname(const char *);
|
||||
int isassignment(const char *);
|
||||
char *getprompt(void *);
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 20, 2011
|
||||
.Dd May 21, 2011
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -506,8 +506,8 @@ The following are keywords:
|
||||
An alias is a name and corresponding value set using the
|
||||
.Ic alias
|
||||
built-in command.
|
||||
Whenever a keyword may occur (see above),
|
||||
and after checking for keywords, the shell
|
||||
Wherever the command word of a simple command may occur,
|
||||
and after checking for keywords if a keyword may occur, the shell
|
||||
checks the word to see if it matches an alias.
|
||||
If it does, it replaces it in the input stream with its value.
|
||||
For example, if there is an alias called
|
||||
|
5
tools/regression/bin/sh/parser/alias4.0
Normal file
5
tools/regression/bin/sh/parser/alias4.0
Normal file
@ -0,0 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
alias alias0=exit
|
||||
eval 'x=1 alias0 0'
|
||||
exit 1
|
5
tools/regression/bin/sh/parser/alias5.0
Normal file
5
tools/regression/bin/sh/parser/alias5.0
Normal file
@ -0,0 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
alias alias0=exit
|
||||
eval '</dev/null alias0 0'
|
||||
exit 1
|
Loading…
x
Reference in New Issue
Block a user