sh: Recognize "--" in . and exec.

Although "--" historically has not been required to be recognized for
certain special builtins that do not take options in POSIX, some other
implementations recognize options for them, requiring scripts to use "--" or
avoid operands starting with "-".

Operands starting with "-" can be avoided with eval by prepending a space,
and cannot occur with break, continue, exit, return and shift as they only
take numbers, nor with times as it does not take operands. With . and exec,
avoiding "-" is not so easy as it may require reimplementing the PATH
search; therefore the current proposal for POSIX is to require recognition
of "--" for them.

We continue to accept other strings starting with "-" as operands to . and
exec, and also "--" if it is alone to . (which would otherwise be invalid
anyway).
This commit is contained in:
Jilles Tjoelker 2010-05-28 22:40:24 +00:00
parent bc4c1a0670
commit c1564db05d
4 changed files with 60 additions and 2 deletions

View File

@ -1170,6 +1170,12 @@ truecmd(int argc __unused, char **argv __unused)
int
execcmd(int argc, char **argv)
{
/*
* Because we have historically not supported any options,
* only treat "--" specially.
*/
if (argc > 1 && strcmp(argv[1], "--") == 0)
argc--, argv++;
if (argc > 1) {
struct strlist *sp;

View File

@ -314,14 +314,20 @@ find_dot_file(char *basename)
int
dotcmd(int argc, char **argv)
{
char *fullname;
char *filename, *fullname;
if (argc < 2)
error("missing filename");
exitstatus = 0;
fullname = find_dot_file(argv[1]);
/*
* Because we have historically not supported any options,
* only treat "--" specially.
*/
filename = argc > 2 && strcmp(argv[1], "--") == 0 ? argv[2] : argv[1];
fullname = find_dot_file(filename);
setinputfile(fullname, 1);
commandname = fullname;
cmdloop(0);

View File

@ -0,0 +1,21 @@
# $FreeBSD$
failures=
failure() {
echo "Error at line $1" >&2
failures=x$failures
}
T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX) || exit
trap 'rm -rf $T' 0
cd $T || exit 3
unset x
echo 'x=2' >testscript
. -- ./testscript
[ "$x" = 2 ] || failure $LINENO
cd / || exit 3
x=1
PATH=$T:$PATH . -- testscript
[ "$x" = 2 ] || failure $LINENO
test -z "$failures"

View File

@ -0,0 +1,25 @@
# $FreeBSD$
failures=
failure() {
echo "Error at line $1" >&2
failures=x$failures
}
(
exec -- >/dev/null
echo bad
)
[ $? = 0 ] || failure $LINENO
(
exec -- sh -c 'exit 42'
echo bad
)
[ $? = 42 ] || failure $LINENO
(
exec -- /var/empty/nosuch
echo bad
) 2>/dev/null
[ $? = 127 ] || failure $LINENO
test -z "$failures"