bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

alias does not match POSIX


From: Eric Blake
Subject: alias does not match POSIX
Date: Tue, 13 Apr 2004 06:22:25 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624

Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: cygwin
Compiler: i686-pc-cygwin-gcc
Compilation CFLAGS: -DPROGRAM='bash.exe' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='cygwin' -DCONF_MACHTYPE='i686-pc-cygwin' -DCONF_VENDOR='pc' -DSHELL -DHAVE_CONFIG_H -DRECYCLES_PIDS -I. -I/home/RLandheer/cygwin-contrib/bash/2.05b-16/bash-2.05b -I/home/RLandheer/cygwin-contrib/bash/2.05b-16/bash-2.05b/include -I/home/RLandheer/cygwin-contrib/bash/2.05b-16/bash-2.05b/lib -O2 uname output: CYGWIN_NT-5.0 eblake 1.5.7(0.109/3/2) 2004-01-30 19:32 i686 unknown unknown Cygwin
Machine Type: i686-pc-cygwin

Bash Version: 2.05b
Patch Level: 0
Release Status: release

Description:
I have the aliases xargs='xargs ' and grep='grep --color'.  I wanted
to alias -0 so that I could do ``find . -print0 | xargs -0 grep foo''
and have the output colorized, when I ran into some counterintuitive
behavior.  With further research, I have determined that the
processing of the shell builtin ``alias'' violates POSIX 2003. Refer
to http://www.opengroup.org/onlinepubs/007904975/utilities/alias.html.

First is the formatting of the output. Under STDOUT, POSIX requires
that "The format for displaying aliases (when no operands or only name
operands are specified) shall be:

"%s=%s\n", name, value

The value string shall be written with appropriate quoting so that it
is suitable for reinput to the shell."

I am not sure whether bash is in error for using the format "alias
%s=%s\n", or whether POSIX has a bug for copying the output of the
``set'' command too strictly. If bash is in error for outputting too
much, then the rest of this bug report is still valid, but using
``eval alias `alias`'' rather than ``eval `alias`''.  However, I do
think POSIX is in error for not requiring the output of ``alias'' to
be sorted in the collation order of the current locale (the way it is
specified for ``set'').

Next, there are bash documentation issues.  Bash does not document
what characters are legal as extensions in an alias name.  POSIX
defines alias names:

"In the shell command language, a word consisting solely of
underscores, digits, and alphabetics from the portable character set
and any of the following characters: '!' , '%' , ',' , '@' .

"Implementations may allow other characters within alias names as an
extension."

And in the rationale section:

"The definition of "alias name" precludes an alias name containing a
slash character."

While a POSIX conformant application must not do ``alias \'/\\=a'',
bash currently allows it.  This seems to go against the intent of
POSIX - the alias will never be expanded - so it would make more sense
for bash to give non-zero exit status when some characters (probably
\, /, ', ", and $ at a minimum) appear in the alias-name to the alias
command.  In particular, the wording of the rationale section makes it
seem that a command word with a slash should never be subject to alias
expansion, even though the example below shows that bash allowed
it.  However, there are some characters which are reasonable
extensions, even when POSIXLY_CORRECT is set (probably - and + at a
minimum).  Of course, this means my desire to ``alias -- -0="-0 "'' is
non-POSIX, so I am already treading on thin ice when it comes to
compliance.

The next documentation issue is the lack of mention that ``--'' can be
used on the alias builtin (and in fact, must be used to alias a non-POSIX
aliasname such as -0).

Which leads to another issue - I interpret the POSIX requirement on
the output of ``alias'' to mean that the command ``eval `alias`''
should always be successful.  But with bash's extension to the set of
legal alias names, it is not properly quoting alias names, so that the
example below causes a usage error rather than reassigning the alias.
Bash could fix this particular bug by using ("\\alias -- %s=%s;\n",
quoted-name, quoted-value) instead of ("alias %s=%s\n" name,
quoted-value) (the leading \ prevents problems if 'alias' is aliased,
the -- allows for aliases starting with -, the trailing ; allows for
multiple aliases).

Another thing to worry about is the interaction between aliases and
history.  Alias expansion is required by POSIX, history is not.  And
alias names are required by POSIX to support !.  Therefore, in the
second half of my example below, with POSIXLY_CORRECT, I would expect
the alias !a to be expanded, and output ``hi'', rather than history
expansion to occur.  Note that escaping the history expansion also
escapes the alias expansion, so there is no way for me to expand this
POSIX-mandated alias name. (When POSIXLY_CORRECT is not specified, I
would be happy with history expansion taking priority; particularly
since, as you note in the documentation, aliases can almost always be
replaced by more powerful functions).

One last thing - the POSIX specification for unalias states that
arguments are mandatory, but bash returns 0 on ``unalias'', without
changing the current set of aliases.  You should document this valid
extension, and consider making unalias report an error if it is not
given arguments.

Fortunately, I think your documented weakness that ``alias a=b; a''
invokes the command a rather than performing alias expansion and
invoking b is valid under POSIX, since POSIX states that aliases are
expanded after tokens are delimited but before applying the
grammatical rules for that input line; at the time the parser
tokenizes a, there is no alias available for a (the grammatical rules
must be applied before the alias command can be executed).  And I have
no idea why POSIX only notes that alias "is generally provided as a
shell regular built-in", rather than requiring it to be a builtin - as
I see no way to write a program /bin/alias that could have the same
functionality as the builtin.


Repeat-By:
$ bash --posix
$ unalias -a
$ alias -0='-0 '
bash: alias: -0: invalid option
alias: usage: alias [-p] [name[=value] ... ]

$ alias -- -0='-0 '
$ alias
alias -0='-0 '

$ eval `alias`
bash: alias: -0: invalid option
alias: usage: alias [-p] [name[=value] ... ]

$ unalias -a
$ alias \!a='echo hi'
$ alias
alias !a='echo hi'
$ !a
alias
alias !a='echo hi'

$ \!a
bash: !a: command not found

Fix:
        [Description of how to fix the problem.  If you don't know a
        fix for the problem, don't include this section.]

--
Someday, I might put a cute statement here.

Eric Blake             ebb9@byu.net





reply via email to

[Prev in Thread] Current Thread [Next in Thread]