Skip to content

Commit

Permalink
sh: Write absolute path in command -vV and type
Browse files Browse the repository at this point in the history
POSIX is pretty clear that command -v, command -V and type shall write
absolute pathnames. Therefore, we need to prepend the current directory's
name to relative pathnames.

This can happen either when PATH contains a relative pathname or when the
operand contains a slash but is not an absolute pathname.
  • Loading branch information
jillest committed Sep 1, 2020
1 parent 78ae1e6 commit ccd0a51
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 11 deletions.
33 changes: 22 additions & 11 deletions bin/sh/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,21 @@ isfunc(const char *name)
}


static void
print_absolute_path(const char *name)
{
const char *pwd;

if (*name != '/' && (pwd = lookupvar("PWD")) != NULL && *pwd != '\0') {
out1str(pwd);
if (strcmp(pwd, "/") != 0)
outcslow('/', out1);
}
out1str(name);
outcslow('\n', out1);
}


/*
* Shared code for the following builtin commands:
* type, command -v, command -V
Expand Down Expand Up @@ -745,20 +760,16 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
name = padvance(&path2, &opt2, argv[i]);
stunalloc(name);
} while (--j >= 0);
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", name);
else
out1fmt("%s is%s %s\n", argv[i],
if (cmd != TYPECMD_SMALLV)
out1fmt("%s is%s ", argv[i],
(cmdp && cmd == TYPECMD_TYPE) ?
" a tracked alias for" : "",
name);
" a tracked alias for" : "");
print_absolute_path(name);
} else {
if (eaccess(argv[i], X_OK) == 0) {
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", argv[i]);
else
out1fmt("%s is %s\n", argv[i],
argv[i]);
if (cmd != TYPECMD_SMALLV)
out1fmt("%s is ", argv[i]);
print_absolute_path(argv[i]);
} else {
if (cmd != TYPECMD_SMALLV)
outfmt(out2, "%s: %s\n",
Expand Down
3 changes: 3 additions & 0 deletions bin/sh/tests/builtins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ ${PACKAGE}FILES+= command9.0
${PACKAGE}FILES+= command10.0
${PACKAGE}FILES+= command11.0
${PACKAGE}FILES+= command12.0
${PACKAGE}FILES+= command13.0
${PACKAGE}FILES+= command14.0
${PACKAGE}FILES+= dot1.0
${PACKAGE}FILES+= dot2.0
${PACKAGE}FILES+= dot3.0
Expand Down Expand Up @@ -170,6 +172,7 @@ ${PACKAGE}FILES+= trap9.0
${PACKAGE}FILES+= type1.0 type1.0.stderr
${PACKAGE}FILES+= type2.0
${PACKAGE}FILES+= type3.0
${PACKAGE}FILES+= type4.0
${PACKAGE}FILES+= unalias.0
${PACKAGE}FILES+= var-assign.0
${PACKAGE}FILES+= var-assign2.0
Expand Down
21 changes: 21 additions & 0 deletions bin/sh/tests/builtins/command13.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# $FreeBSD$

failures=0

check() {
if [ "$1" != "$2" ] && { [ "$#" -lt 3 ] || [ "$1" != "$3" ]; } then
echo "Mismatch found"
echo "Expected: $2"
if [ "$#" -ge 3 ]; then
echo "Alternative expected: $3"
fi
echo "Actual: $1"
: $((failures += 1))
fi
}

check "$(cd /bin && PATH=. command -v ls)" /bin/ls /bin/./ls
check "$(cd /bin && PATH=:/var/empty/nosuch command -v ls)" /bin/ls /bin/./ls
check "$(cd / && PATH=bin command -v ls)" /bin/ls
check "$(cd / && command -v bin/ls)" /bin/ls
check "$(cd /bin && command -v ./ls)" /bin/ls /bin/./ls
9 changes: 9 additions & 0 deletions bin/sh/tests/builtins/command14.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# $FreeBSD$

r=`cd /bin && PATH=. command -V ls`
case $r in
*/bin/ls*|*/bin/./ls*) ;;
*)
echo "Unexpected result: $r"
exit 1
esac
9 changes: 9 additions & 0 deletions bin/sh/tests/builtins/type4.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# $FreeBSD$

r=`cd /bin && PATH=. type ls`
case $r in
*/bin/ls*|*/bin/./ls*) ;;
*)
echo "Unexpected result: $r"
exit 1
esac

0 comments on commit ccd0a51

Please sign in to comment.