Update ^/vendor/NetBSD/tests/dist to a more recent snapshot

Pulled on "Thu Aug 11 18:01:19 PDT 2016"
This commit is contained in:
Enji Cooper 2016-08-12 01:05:07 +00:00
parent 478290db20
commit 014db25b98
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/NetBSD/tests/dist/; revision=303980
389 changed files with 33890 additions and 18037 deletions

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.44 2013/02/25 00:33:19 jmmv Exp $
# $NetBSD: Makefile,v 1.45 2015/06/22 00:05:23 matt Exp $
.include <bsd.own.mk>
@ -9,7 +9,7 @@ TESTSDIR= ${TESTSBASE}
TESTS_SUBDIRS= bin dev games include kernel lib libexec net
TESTS_SUBDIRS+= sbin sys usr.bin usr.sbin
. if (${MKRUMP} != "no")
. if (${MKRUMP} != "no") && !defined(BSD_MK_COMPAT_FILE)
TESTS_SUBDIRS+= fs rump
. if ${MKKMOD} != "no"

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.1 2012/03/27 08:16:33 jruoho Exp $
# $NetBSD: Makefile,v 1.2 2016/06/16 01:04:58 sevan Exp $
.include <bsd.own.mk>
@ -8,5 +8,7 @@ TESTS_SH= t_cat
FILESDIR= ${TESTSDIR}
FILES+= d_align.in
FILES+= d_align.out
FILES+= d_se_output.in
FILES+= d_se_output.out
.include <bsd.test.mk>

View file

@ -1,3 +1,5 @@
a b c
1 2 3
x y z

View file

@ -1,3 +1,5 @@
1 a b c$
$
2 1 2 3$
$
3 x y z$

3
bin/cat/d_se_output.in Normal file
View file

@ -0,0 +1,3 @@
Of course it runs NetBSD

3
bin/cat/d_se_output.out Normal file
View file

@ -0,0 +1,3 @@
$
Of course it runs NetBSD$
$

View file

@ -1,4 +1,4 @@
# $NetBSD: t_cat.sh,v 1.2 2012/03/27 17:57:02 jruoho Exp $
# $NetBSD: t_cat.sh,v 1.3 2016/06/16 01:04:58 sevan Exp $
#
# Copyright (c) 2012 The NetBSD Foundation, Inc.
# All rights reserved.
@ -52,8 +52,20 @@ nonexistent_body() {
-x "cat /some/name/that/does/not/exist"
}
atf_test_case se_output
se_output_head() {
atf_set "descr" "Test that cat(1) prints a $ sign " \
"on blank lines with options '-se' (PR bin/51250)"
}
se_output_body() {
atf_check -s ignore -o file:$(atf_get_srcdir)/d_se_output.out \
-x "cat -se $(atf_get_srcdir)/d_se_output.in"
}
atf_init_test_cases()
{
atf_add_test_case align
atf_add_test_case nonexistent
atf_add_test_case se_output
}

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.4 2014/09/11 18:25:30 dholland Exp $
# $NetBSD: Makefile,v 1.11 2016/03/20 22:57:04 christos Exp $
#
.include <bsd.own.mk>
@ -7,15 +7,21 @@ TESTSDIR = ${TESTSBASE}/bin/sh
TESTS_SUBDIRS += dotcmd
TESTS_SH= t_compexit
TESTS_SH+= t_arith
TESTS_SH+= t_cmdsub
TESTS_SH+= t_evaltested
TESTS_SH+= t_exit
TESTS_SH+= t_expand
TESTS_SH+= t_evaltested
TESTS_SH+= t_fsplit
TESTS_SH+= t_here
TESTS_SH+= t_option
TESTS_SH+= t_redir
TESTS_SH+= t_redircloexec
TESTS_SH+= t_set_e
TESTS_SH+= t_shift
TESTS_SH+= t_ulimit
TESTS_SH+= t_varquote
TESTS_SH+= t_varval
TESTS_SH+= t_wait
.include <bsd.test.mk>

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.2 2014/07/27 14:24:17 apb Exp $
# $NetBSD: Makefile,v 1.3 2016/03/27 14:57:50 christos Exp $
#
.include <bsd.own.mk>
@ -7,6 +7,10 @@ TESTSDIR = ${TESTSBASE}/bin/sh/dotcmd
TESTS_SH = t_dotcmd
.if !defined(TEST_SH)
TEST_SH = ${HOST_SH}
.endif
FILESDIR = ${TESTSDIR}/out
# Testing scripts: dotcmd in various scopes includes a file with
@ -19,7 +23,7 @@ FILESDIR_${cmd}_${cmd_scope} = ${TESTSDIR}
FILESBUILD_${cmd}_${cmd_scope} = yes
${cmd}_${cmd_scope}: scoped_command
${HOST_SH} ${.CURDIR}/scoped_command '${cmd_scope}' '${cmd}' '${cmd}' \
${TEST_SH} ${.CURDIR}/scoped_command '${cmd_scope}' '${cmd}' '${cmd}' \
>'${.TARGET}'
. for dot_scope in case compound file for func subshell until while
@ -31,7 +35,7 @@ FILESBUILD_${dot_scope}_${cmd}_${cmd_scope} = yes
FILESMODE_${dot_scope}_${cmd}_${cmd_scope} = ${BINMODE}
${dot_scope}_${cmd}_${cmd_scope}: scoped_command
${HOST_SH} ${.CURDIR}/scoped_command '${dot_scope}' \
${TEST_SH} ${.CURDIR}/scoped_command '${dot_scope}' \
'. "${cmd}_${cmd_scope}"' 'dotcmd' 'dotcmd' >'${.TARGET}'
. endfor
. endfor

View file

@ -1,6 +1,6 @@
#!/bin/sh
#
# $NetBSD: scoped_command,v 1.1 2014/05/31 14:29:06 christos Exp $
# $NetBSD: scoped_command,v 1.2 2016/03/27 14:57:50 christos Exp $
#
# Copyright (c) 2014 The NetBSD Foundation, Inc.
# All rights reserved.
@ -30,6 +30,27 @@
# POSSIBILITY OF SUCH DAMAGE.
#
: ${TEST_SH:=/bin/sh}
sane_sh()
{
set -- ${TEST_SH}
case "$#" in
(0) set /bin/sh;;
(1|2) ;;
(*) set "$1";; # Just ignore options if we cannot make them work
esac
case "$1" in
/*) TEST_SH="$1${2+ }$2";;
./*) TEST_SH="${PWD}${1#.}${2+ }$2";;
*/*) TEST_SH="${PWD}/$1${2+ }$2";;
*) TEST_SH="$( command -v "$1" )${2+ }$2";;
esac
}
sane_sh
set -e
# USAGE:
@ -52,7 +73,7 @@ cmd="echo 'before ${3}'
${2}
echo 'after ${3}, return value:' ${?}"
echo "#!/bin/sh"
echo "#!${TEST_SH}"
[ 'func' = "${1}" ] && cat <<EOF
func()

View file

@ -1,4 +1,4 @@
# $NetBSD: t_dotcmd.sh,v 1.1 2014/05/31 14:29:06 christos Exp $
# $NetBSD: t_dotcmd.sh,v 1.2 2016/03/27 14:57:50 christos Exp $
#
# Copyright (c) 2014 The NetBSD Foundation, Inc.
# All rights reserved.
@ -33,6 +33,10 @@
# in C/C++ so, for example, if the dotcmd is in a loop's body, a break in
# the sourced file can be used to break out of that loop.
# Note that the standard does not require this, and allows lexically
# scoped interpretation of break/continue (and permits dynamic scope
# as an optional extension.)
cmds='return break continue'
scopes='case compound file for func subshell until while'

1035
bin/sh/t_arith.sh Executable file

File diff suppressed because it is too large Load diff

783
bin/sh/t_cmdsub.sh Executable file
View file

@ -0,0 +1,783 @@
# $NetBSD: t_cmdsub.sh,v 1.4 2016/04/04 12:40:13 christos Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
#
# This file tests command substitutions ( `...` and $( ... ) )
#
# CAUTION:
# Be careful attempting running these tests outside the ATF environment
# Some of the tests run "rm *" in the current directory to clean up
# An ATF test directory should be empty already, outside ATF, anything
atf_test_case a_basic_cmdsub
a_basic_cmdsub_head() {
atf_set "descr" 'Test operation of simple $( ) substitutions'
}
a_basic_cmdsub_body() {
atf_check -s exit:0 -o match:'Result is true today' -e empty \
${TEST_SH} -c \
'echo Result is $( true && echo true || echo false ) today'
atf_check -s exit:0 -o match:'Result is false today' -e empty \
${TEST_SH} -c \
'echo Result is $( false && echo true || echo false ) today'
atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
${TEST_SH} -c 'echo aaa$( echo bbb )ccc'
atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
${TEST_SH} -c 'echo aaa$( echo bbb ccc )ddd'
atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
${TEST_SH} -c 'echo aaa$( echo bbb; echo ccc )ddd'
atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
${TEST_SH} -c 'echo "aaa$( echo bbb; echo ccc )ddd"'
atf_check -s exit:0 -o inline:'some string\n' -e empty \
${TEST_SH} -c 'X=$( echo some string ); echo "$X"'
atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
${TEST_SH} -c 'X=$( echo "weird; string *" ); echo "$X"'
rm -f * 2>/dev/null || :
for f in file-1 file-2
do
cp /dev/null "$f"
done
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found $( echo * )'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found "$( echo * )"'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found $('" echo '*' )"
atf_check -s exit:0 -o match:'Found \*' -e empty \
${TEST_SH} -c 'echo Found "$('" echo '*' "')"'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found $('" echo \\* )"
atf_check -s exit:0 -o match:'Found \*' -e empty \
${TEST_SH} -c 'echo Found "$('" echo \\* )"\"
}
atf_test_case b_basic_backticks
b_basic_backticks_head() {
atf_set "descr" 'Test operation of old style ` ` substitutions'
}
b_basic_backticks_body() {
atf_check -s exit:0 -o match:'Result is true today' -e empty \
${TEST_SH} -c \
'echo Result is `true && echo true || echo false` today'
atf_check -s exit:0 -o match:'Result is false today' -e empty \
${TEST_SH} -c \
'echo Result is `false && echo true || echo false` today'
atf_check -s exit:0 -o match:'aaabbbccc' -e empty \
${TEST_SH} -c 'echo aaa` echo bbb `ccc'
atf_check -s exit:0 -o match:'aaabbb cccddd' -e empty \
${TEST_SH} -c 'echo aaa` echo bbb ccc `ddd'
atf_check -s exit:0 -o inline:'aaabbb cccddd\n' -e empty \
${TEST_SH} -c 'echo aaa` echo bbb; echo ccc `ddd'
atf_check -s exit:0 -o inline:'aaabbb\ncccddd\n' -e empty \
${TEST_SH} -c 'echo "aaa` echo bbb; echo ccc `ddd"'
atf_check -s exit:0 -o inline:'some string\n' -e empty \
${TEST_SH} -c 'X=` echo some string `; echo "$X"'
atf_check -s exit:0 -o inline:'weird; string *\n' -e empty \
${TEST_SH} -c 'X=` echo "weird; string *" `; echo "$X"'
rm -f * 2>/dev/null || :
for f in file-1 file-2
do
cp /dev/null "$f"
done
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found ` echo * `'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found "` echo * `"'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found `'" echo '*' "'`'
atf_check -s exit:0 -o match:'Found \*' -e empty \
${TEST_SH} -c 'echo Found "`'" echo '*' "'`"'
atf_check -s exit:0 -o match:'Found file-1 file-2' -e empty \
${TEST_SH} -c 'echo Found `'" echo \\* "'`'
atf_check -s exit:0 -o match:'Found \*' -e empty \
${TEST_SH} -c 'echo Found "`'" echo \\* "'`"'
}
atf_test_case c_nested_cmdsub
c_nested_cmdsub_head() {
atf_set "descr" "Test that cmd substitutions can be nested"
}
c_nested_cmdsub_body() {
atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
${TEST_SH} -c 'echo __$( echo foo$(echo bar)bletch )__'
atf_check -s exit:0 -o match:'_abcde_' -e empty \
${TEST_SH} -c 'echo _$(echo a$(echo $(echo b)c$(echo d))e )_'
atf_check -s exit:0 -o match:'123454321' -e empty \
${TEST_SH} -c 'echo 1$(echo 2$(echo 3$(echo 4$(echo 5)4)3)2)1'
}
atf_test_case d_nested_backticks
d_nested_backticks_head() {
atf_set "descr" "Tests that old style backtick cmd subs can be nested"
}
d_nested_backticks_body() {
atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
${TEST_SH} -c 'echo __` echo foo\`echo bar\`bletch `__'
atf_check -s exit:0 -o match:'_abcde_' -e empty \
${TEST_SH} -c \
'echo _`echo a\`echo \\\`echo b\\\`c\\\`echo d\\\`\`e `_'
atf_check -s exit:0 -o match:'123454321' -e empty \
${TEST_SH} -c \
'echo 1`echo 2\`echo 3\\\`echo 4\\\\\\\`echo 5\\\\\\\`4\\\`3\`2`1'
}
atf_test_case e_perverse_mixing
e_perverse_mixing_head() {
atf_set "descr" \
"Checks various mixed new and old style cmd substitutions"
}
e_perverse_mixing_body() {
atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
${TEST_SH} -c 'echo __$( echo foo`echo bar`bletch )__'
atf_check -s exit:0 -o match:'__foobarbletch__' -e empty \
${TEST_SH} -c 'echo __` echo foo$(echo bar)bletch `__'
atf_check -s exit:0 -o match:'_abcde_' -e empty \
${TEST_SH} -c 'echo _$(echo a`echo $(echo b)c$(echo d)`e )_'
atf_check -s exit:0 -o match:'_abcde_' -e empty \
${TEST_SH} -c 'echo _`echo a$(echo \`echo b\`c\`echo d\`)e `_'
atf_check -s exit:0 -o match:'12345654321' -e empty \
${TEST_SH} -c \
'echo 1`echo 2$(echo 3\`echo 4\\\`echo 5$(echo 6)5\\\`4\`3)2`1'
}
atf_test_case f_redirect_in_cmdsub
f_redirect_in_cmdsub_head() {
atf_set "descr" "Checks that redirects work in command substitutions"
}
f_redirect_in_cmdsub_body() {
atf_require_prog cat
atf_require_prog rm
rm -f file 2>/dev/null || :
atf_check -s exit:0 -o match:'_aa_' -e empty \
${TEST_SH} -c 'echo _$( echo a$( echo b > file )a)_'
atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
atf_check -s exit:0 -o match:'_aba_' -e empty \
${TEST_SH} -c 'echo _$( echo a$( cat < file )a)_'
atf_check -s exit:0 -o match:'_aa_' -e empty \
${TEST_SH} -c 'echo _$( echo a$( echo d >> file )a)_'
atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
${TEST_SH} -c 'echo _$( echo a$( echo not error >&2 )a)_'
}
atf_test_case g_redirect_in_backticks
g_redirect_in_backticks_head() {
atf_set "descr" "Checks that redirects work in old style cmd sub"
}
g_redirect_in_backticks_body() {
atf_require_prog cat
atf_require_prog rm
rm -f file 2>/dev/null || :
atf_check -s exit:0 -o match:'_aa_' -e empty \
${TEST_SH} -c 'echo _` echo a\` echo b > file \`a`_'
atf_check -s exit:0 -o match:b -e empty ${TEST_SH} -c 'cat file'
atf_check -s exit:0 -o match:'_aba_' -e empty \
${TEST_SH} -c 'echo _` echo a\` cat < file \`a`_'
atf_check -s exit:0 -o match:'_aa_' -e empty \
${TEST_SH} -c 'echo _` echo a\` echo d >> file \`a`_'
atf_check -s exit:0 -o inline:'b\nd\n' -e empty ${TEST_SH} -c 'cat file'
atf_check -s exit:0 -o match:'_aa_' -e match:'not error' \
${TEST_SH} -c 'echo _` echo a\` echo not error >&2 \`a`_'
}
atf_test_case h_vars_in_cmdsub
h_vars_in_cmdsub_head() {
atf_set "descr" "Check that variables work in command substitutions"
}
h_vars_in_cmdsub_body() {
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo __$( echo ${X} )__'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo __$( echo "${X}" )__'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo "__$( echo ${X} )__"'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo "__$( echo "${X}" )__"'
atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
atf_check -s exit:0 -o match:'__acd__' -e empty \
${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
atf_check -s exit:0 -o match:'__abcd__' -e empty \
${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
atf_check -s exit:0 -o match:'__XYX__' -e empty \
${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
atf_check -s exit:0 -o match:'__def__' -e empty \
${TEST_SH} -c 'X=abc; echo "__$(X=def; echo "${X}" )__"'
atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
${TEST_SH} -c 'X=abc; echo "$X$(X=def; echo ${X} )"; echo $X'
}
atf_test_case i_vars_in_backticks
i_vars_in_backticks_head() {
atf_set "descr" "Checks that variables work in old style cmd sub"
}
i_vars_in_backticks_body() {
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo __` echo ${X} `__'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo __` echo "${X}" `__'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo "__` echo ${X} `__"'
atf_check -s exit:0 -o match:'__abc__' -e empty \
${TEST_SH} -c 'X=abc; echo "__` echo \"${X}\" `__"'
atf_check -s exit:0 -o inline:'a\n\nb\n\nc\n' -e empty \
${TEST_SH} -c "for X in a '' b '' c"'; do echo $( echo "$X" ); done'
atf_check -s exit:0 -o match:'__acd__' -e empty \
${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X-b}${Y-c}d)__"'
atf_check -s exit:0 -o match:'__abcd__' -e empty \
${TEST_SH} -c 'X=; unset Y; echo "__$( echo a${X:-b}${Y:-c}d)__"'
atf_check -s exit:0 -o match:'__XYX__' -e empty \
${TEST_SH} -c 'X=X; echo "__${X}$( X=Y; echo ${X} )${X}__"'
atf_check -s exit:0 -o inline:'abcdef\nabc\n' -e empty \
${TEST_SH} -c 'X=abc; echo "$X`X=def; echo \"${X}\" `";echo $X'
# The following is nonsense, so is not included ...
# atf_check -s exit:0 -o match:'__abc__' -e empty \
# oV cV oV cV
# ${TEST_SH} -c 'X=abc; echo "__`X=def echo "${X}" `__"'
# `start in " ^ " ends, ` not yet
}
atf_test_case j_cmdsub_in_varexpand
j_cmdsub_in_varexpand_head() {
atf_set "descr" "Checks that command sub can be used in var expansion"
}
j_cmdsub_in_varexpand_body() {
atf_check -s exit:0 -o match:'foo' -e empty \
${TEST_SH} -c 'X=set; echo ${X+$(echo foo)}'
atf_check -s exit:0 -o match:'set' -e empty \
${TEST_SH} -c 'X=set; echo ${X-$(echo foo)}'
rm -f bar 2>/dev/null || :
atf_check -s exit:0 -o match:'set' -e empty \
${TEST_SH} -c 'X=set; echo ${X-$(echo foo > bar)}'
test -f bar && atf_fail "bar should not exist, but does"
atf_check -s exit:0 -o inline:'\n' -e empty \
${TEST_SH} -c 'X=set; echo ${X+$(echo foo > bar)}'
test -f bar || atf_fail "bar should exist, but does not"
}
atf_test_case k_backticks_in_varexpand
k_backticks_in_varexpand_head() {
atf_set "descr" "Checks that old style cmd sub works in var expansion"
}
k_backticks_in_varexpand_body() {
atf_check -s exit:0 -o match:'foo' -e empty \
${TEST_SH} -c 'X=set; echo ${X+`echo foo`}'
atf_check -s exit:0 -o match:'set' -e empty \
${TEST_SH} -c 'X=set; echo ${X-`echo foo`}'
rm -f bar 2>/dev/null || :
atf_check -s exit:0 -o match:'set' -e empty \
${TEST_SH} -c 'X=set; echo ${X-`echo foo > bar`}'
test -f bar && atf_fail "bar should not exist, but does"
atf_check -s exit:0 -o inline:'\n' -e empty \
${TEST_SH} -c 'X=set; echo ${X+`echo foo > bar`}'
test -f bar || atf_fail "bar should exist, but does not"
}
atf_test_case l_arithmetic_in_cmdsub
l_arithmetic_in_cmdsub_head() {
atf_set "descr" "Checks that arithmetic works in cmd substitutions"
}
l_arithmetic_in_cmdsub_body() {
atf_check -s exit:0 -o inline:'1 + 1 = 2\n' -e empty \
${TEST_SH} -c 'echo 1 + 1 = $( echo $(( 1 + 1 )) )'
atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
${TEST_SH} -c 'X=2; Y=3; echo X \* Y = $( echo $(( X * Y )) )'
atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
${TEST_SH} -c 'X=2; Y=3; echo Y % X = $( echo $(( $Y % $X )) )'
}
atf_test_case m_arithmetic_in_backticks
m_arithmetic_in_backticks_head() {
atf_set "descr" "Checks that arithmetic works in old style cmd sub"
}
m_arithmetic_in_backticks_body() {
atf_check -s exit:0 -o inline:'2 + 3 = 5\n' -e empty \
${TEST_SH} -c 'echo 2 + 3 = ` echo $(( 2 + 3 )) `'
atf_check -s exit:0 -o inline:'X * Y = 6\n' -e empty \
${TEST_SH} -c 'X=2; Y=3; echo X \* Y = ` echo $(( X * Y )) `'
atf_check -s exit:0 -o inline:'Y % X = 1\n' -e empty \
${TEST_SH} -c 'X=2; Y=3; echo Y % X = ` echo $(( $Y % $X )) `'
}
atf_test_case n_cmdsub_in_arithmetic
n_cmdsub_in_arithmetic_head() {
atf_set "descr" "Tests uses of command substitutions in arithmetic"
}
n_cmdsub_in_arithmetic_body() {
atf_check -s exit:0 -o inline:'7\n' -e empty \
${TEST_SH} -c 'echo $(( $( echo 3 ) $( echo + ) $( echo 4 ) ))'
atf_check -s exit:0 -o inline:'11\n7\n18\n4\n1\n' -e empty \
${TEST_SH} -c \
'for op in + - \* / %
do
echo $(( $( echo 9 ) $( echo "${op}" ) $( echo 2 ) ))
done'
}
atf_test_case o_backticks_in_arithmetic
o_backticks_in_arithmetic_head() {
atf_set "descr" "Tests old style cmd sub used in arithmetic"
}
o_backticks_in_arithmetic_body() {
atf_check -s exit:0 -o inline:'33\n' -e empty \
${TEST_SH} -c 'echo $(( `echo 77` `echo -` `echo 44`))'
atf_check -s exit:0 -o inline:'14\n8\n33\n3\n2\n' -e empty \
${TEST_SH} -c \
'for op in + - \* / %
do
echo $((`echo 11``echo "${op}"``echo 3`))
done'
}
atf_test_case p_cmdsub_in_heredoc
p_cmdsub_in_heredoc_head() {
atf_set "descr" "Checks that cmdsubs work inside a here document"
}
p_cmdsub_in_heredoc_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'line 1+1\nline 2\nline 3\n' -e empty \
${TEST_SH} -c \
'cat <<- EOF
$( echo line 1 )$( echo +1 )
$( echo line 2;echo line 3 )
EOF'
}
atf_test_case q_backticks_in_heredoc
q_backticks_in_heredoc_head() {
atf_set "descr" "Checks that old style cmdsubs work in here docs"
}
q_backticks_in_heredoc_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
${TEST_SH} -c \
'cat <<- EOF
`echo Mary ` `echo had a `
` echo little; echo lamb `
EOF'
}
atf_test_case r_heredoc_in_cmdsub
r_heredoc_in_cmdsub_head() {
atf_set "descr" "Checks that here docs work inside cmd subs"
}
r_heredoc_in_cmdsub_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
${TEST_SH} -c 'echo "$( cat <<- \EOF
Mary had a
little
lamb
EOF
)"'
atf_check -s exit:0 -e empty \
-o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF
Mary had ${N}
little
lamb$( [ $N -gt 1 ] && echo s )
EOF
)"; done'
atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
${TEST_SH} -c 'echo "$( cat <<- EOF
A Calculation:
2 * 7 = $(( 2 * 7 ))
EOF
)"'
}
atf_test_case s_heredoc_in_backticks
s_heredoc_in_backticks_head() {
atf_set "descr" "Checks that here docs work inside old style cmd subs"
}
s_heredoc_in_backticks_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
${TEST_SH} -c 'echo ` cat <<- \EOF
Mary had a
little
lamb
EOF
`'
atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
${TEST_SH} -c 'echo "` cat <<- EOF
A Calculation:
17 / 3 = $(( 17 / 3 ))
EOF
`"'
}
atf_test_case t_nested_cmdsubs_in_heredoc
t_nested_cmdsubs_in_heredoc_head() {
atf_set "descr" "Checks nested command substitutions in here docs"
}
t_nested_cmdsubs_in_heredoc_body() {
atf_require_prog cat
atf_require_prog rm
rm -f * 2>/dev/null || :
echo "Hello" > File
atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
$(cat File) U
$( V=$(cat File); echo "${V%lo}p" ) me!
EOF'
rm -f * 2>/dev/null || :
echo V>V ; echo A>A; echo R>R
echo Value>VAR
atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
$(Value='\''$2.50'\'';eval echo $(eval $(cat V)$(cat A)$(cat R)=\'\''\$$(cat $(cat V)$(cat A)$(cat R))\'\''; eval echo \$$(set -- *;echo ${3}${1}${2})))
EOF'
}
atf_test_case u_nested_backticks_in_heredoc
u_nested_backticks_in_heredoc_head() {
atf_set "descr" "Checks nested old style cmd subs in here docs"
}
u_nested_backticks_in_heredoc_body() {
atf_require_prog cat
atf_require_prog rm
rm -f * 2>/dev/null || :
echo "Hello" > File
atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
`cat File` U
`V=\`cat File\`; echo "${V%lo}p" ` me!
EOF'
rm -f * 2>/dev/null || :
echo V>V ; echo A>A; echo R>R
echo Value>VAR
atf_check -s exit:0 -o inline:'$5.20\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
`Value='\''$5.20'\'';eval echo \`eval \\\`cat V\\\`\\\`cat A\\\`\\\`cat R\\\`=\\\'\''\\\$\\\`cat \\\\\\\`cat V\\\\\\\`\\\\\\\`cat A\\\\\\\`\\\\\\\`cat R\\\\\\\`\\\`\\\'\''; eval echo \\\$\\\`set -- *;echo \\\\\${3}\\\\\${1}\\\\\${2}\\\`\``
EOF'
}
atf_test_case v_cmdsub_paren_tests
v_cmdsub__paren_tests_head() {
atf_set "descr" "tests with cmdsubs containing embedded ')'"
}
v_cmdsub_paren_tests_body() {
# Tests from:
# http://www.in-ulm.de/~mascheck/various/cmd-subst/
# (slightly modified.)
atf_check -s exit:0 -o inline:'A.1\n' -e empty ${TEST_SH} -c \
'echo $(
case x in x) echo A.1;; esac
)'
atf_check -s exit:0 -o inline:'A.2\n' -e empty ${TEST_SH} -c \
'echo $(
case x in x) echo A.2;; esac # comment
)'
atf_check -s exit:0 -o inline:'A.3\n' -e empty ${TEST_SH} -c \
'echo $(
case x in (x) echo A.3;; esac
)'
atf_check -s exit:0 -o inline:'A.4\n' -e empty ${TEST_SH} -c \
'echo $(
case x in (x) echo A.4;; esac # comment
)'
atf_check -s exit:0 -o inline:'A.5\n' -e empty ${TEST_SH} -c \
'echo $(
case x in (x) echo A.5
esac
)'
atf_check -s exit:0 -o inline:'B: quoted )\n' -e empty ${TEST_SH} -c \
'echo $(
echo '\''B: quoted )'\''
)'
atf_check -s exit:0 -o inline:'C: comment then closing paren\n' \
-e empty ${TEST_SH} -c \
'echo $(
echo C: comment then closing paren # )
)'
atf_check -s exit:0 -o inline:'D.1: here-doc with )\n' \
-e empty ${TEST_SH} -c \
'echo $(
cat <<-\eof
D.1: here-doc with )
eof
)'
# D.2 is a bogus test.
atf_check -s exit:0 -o inline:'D.3: here-doc with \()\n' \
-e empty ${TEST_SH} -c \
'echo $(
cat <<-\eof
D.3: here-doc with \()
eof
)'
atf_check -s exit:0 -e empty \
-o inline:'E: here-doc terminated with a parenthesis ("academic")\n' \
${TEST_SH} -c \
'echo $(
cat <<-\)
E: here-doc terminated with a parenthesis ("academic")
)
)'
atf_check -s exit:0 -e empty \
-o inline:'F.1: here-doc embed with unbal single, back- or doublequote '\''\n' \
${TEST_SH} -c \
'echo $(
cat <<-"eof"
F.1: here-doc embed with unbal single, back- or doublequote '\''
eof
)'
atf_check -s exit:0 -e empty \
-o inline:'F.2: here-doc embed with unbal single, back- or doublequote "\n' \
${TEST_SH} -c \
'echo $(
cat <<-"eof"
F.2: here-doc embed with unbal single, back- or doublequote "
eof
)'
atf_check -s exit:0 -e empty \
-o inline:'F.3: here-doc embed with unbal single, back- or doublequote `\n' \
${TEST_SH} -c \
'echo $(
cat <<-"eof"
F.3: here-doc embed with unbal single, back- or doublequote `
eof
)'
atf_check -s exit:0 -e empty -o inline:'G: backslash at end of line\n' \
${TEST_SH} -c \
'echo $(
echo G: backslash at end of line # \
)'
atf_check -s exit:0 -e empty \
-o inline:'H: empty command-substitution\n' \
${TEST_SH} -c 'echo H: empty command-substitution $( )'
}
atf_test_case w_heredoc_outside_cmdsub
w_heredoc_outside_cmdsub_head() {
atf_set "descr" "Checks that here docs work inside cmd subs"
}
w_heredoc_outside_cmdsub_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'Mary had a\nlittle\nlamb\n' -e empty \
${TEST_SH} -c 'echo "$( cat <<- \EOF )"
Mary had a
little
lamb
EOF
'
atf_check -s exit:0 -e empty \
-o inline:'Mary had 1\nlittle\nlamb\nMary had 4\nlittle\nlambs\n' \
${TEST_SH} -c 'for N in 1 4; do echo "$( cat <<- EOF )"
Mary had ${N}
little
lamb$( [ $N -gt 1 ] && echo s )
EOF
done'
atf_check -s exit:0 -o inline:'A Calculation:\n2 * 7 = 14\n' -e empty \
${TEST_SH} -c 'echo "$( cat <<- EOF)"
A Calculation:
2 * 7 = $(( 2 * 7 ))
EOF
'
}
atf_test_case x_heredoc_outside_backticks
x_heredoc_outside_backticks_head() {
atf_set "descr" "Checks that here docs work inside old style cmd subs"
}
x_heredoc_outside_backticks_body() {
atf_require_prog cat
atf_check -s exit:0 -o inline:'Mary had a little lamb\n' -e empty \
${TEST_SH} -c 'echo ` cat <<- \EOF `
Mary had a
little
lamb
EOF
'
atf_check -s exit:0 -o inline:'A Calculation:\n17 / 3 = 5\n' -e empty \
${TEST_SH} -c 'echo "` cat <<- EOF `"
A Calculation:
17 / 3 = $(( 17 / 3 ))
EOF
'
}
atf_test_case t_nested_cmdsubs_in_heredoc
t_nested_cmdsubs_in_heredoc_head() {
atf_set "descr" "Checks nested command substitutions in here docs"
}
t_nested_cmdsubs_in_heredoc_body() {
atf_require_prog cat
atf_require_prog rm
rm -f * 2>/dev/null || :
echo "Hello" > File
atf_check -s exit:0 -o inline:'Hello U\nHelp me!\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
$(cat File) U
$( V=$(cat File); echo "${V%lo}p" ) me!
EOF'
rm -f * 2>/dev/null || :
echo V>V ; echo A>A; echo R>R
echo Value>VAR
atf_check -s exit:0 -o inline:'$2.50\n' -e empty \
${TEST_SH} -c 'cat <<- EOF
$(Value='\''$2.50'\'';eval echo $(eval $(cat V)$(cat A)$(cat R)=\'\''\$$(cat $(cat V)$(cat A)$(cat R))\'\''; eval echo \$$(set -- *;echo ${3}${1}${2})))
EOF'
}
atf_test_case z_absurd_heredoc_cmdsub_combos
z_absurd_heredoc_cmdsub_combos_head() {
atf_set "descr" "perverse and unusual cmd substitutions & more"
}
z_absurd_heredoc_cmdsub_combos_body() {
echo "Help!" > help
# This version works in NetBSD (& FreeBSD)'s sh (and most others)
atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
cat <<- EOF
$(
cat <<- STOP
$(
cat `echo help`
)
STOP
)
$(
cat <<- END 4<<-TRASH
Me $(( 1 + 1 ))
END
This is unused noise!
TRASH
)
EOF
'
# atf_expect_fail "PR bin/50993 - heredoc parsing done incorrectly"
atf_check -s exit:0 -o inline:'Help!\nMe 2\n' -e empty ${TEST_SH} -c '
cat <<- EOF
$(
cat << STOP
$(
cat `echo help`
)
STOP
)
$(
cat <<- END 4<<TRASH
Me $(( 1 + 1 ))
END
This is unused noise!
TRASH
)
EOF
'
}
atf_init_test_cases() {
atf_add_test_case a_basic_cmdsub
atf_add_test_case b_basic_backticks
atf_add_test_case c_nested_cmdsub
atf_add_test_case d_nested_backticks
atf_add_test_case e_perverse_mixing
atf_add_test_case f_redirect_in_cmdsub
atf_add_test_case g_redirect_in_backticks
atf_add_test_case h_vars_in_cmdsub
atf_add_test_case i_vars_in_backticks
atf_add_test_case j_cmdsub_in_varexpand
atf_add_test_case k_backticks_in_varexpand
atf_add_test_case l_arithmetic_in_cmdsub
atf_add_test_case m_arithmetic_in_backticks
atf_add_test_case n_cmdsub_in_arithmetic
atf_add_test_case o_backticks_in_arithmetic
atf_add_test_case p_cmdsub_in_heredoc
atf_add_test_case q_backticks_in_heredoc
atf_add_test_case r_heredoc_in_cmdsub
atf_add_test_case s_heredoc_in_backticks
atf_add_test_case t_nested_cmdsubs_in_heredoc
atf_add_test_case u_nested_backticks_in_heredoc
atf_add_test_case v_cmdsub_paren_tests
atf_add_test_case w_heredoc_outside_cmdsub
atf_add_test_case x_heredoc_outside_backticks
atf_add_test_case z_absurd_heredoc_cmdsub_combos
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_evaltested.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $
# $NetBSD: t_evaltested.sh,v 1.2 2016/03/27 14:50:01 christos Exp $
#
# Copyright (c) 2011 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,6 +24,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
atf_test_case evaltested
@ -43,7 +45,7 @@ fi
echo "passed"
exit 0
EOF
output="$(/bin/sh helper.sh)"
output="$($TEST_SH helper.sh)"
[ $? = 0 ] && return
if [ -n "$output" ]

View file

@ -1,4 +1,4 @@
# $NetBSD: t_exit.sh,v 1.3 2012/04/13 06:12:32 jruoho Exp $
# $NetBSD: t_exit.sh,v 1.6 2016/05/07 23:51:30 kre Exp $
#
# Copyright (c) 2007 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,74 +24,124 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
crud() {
test yes = no
cat <<EOF
$?
EOF
}
atf_test_case background
background_head() {
atf_set "descr" "Tests that sh(1) sets '$?' properly when running " \
"a command in the background (PR bin/46327)"
"a command in the background (PR bin/46327)"
}
background_body() {
atf_check -s exit:0 -o ignore -e ignore -x "true; true & echo $?"
atf_check -s exit:0 -o ignore -e ignore -x "false; true & echo $?"
atf_check -o match:0 -e empty ${TEST_SH} -c 'true; true & echo $?'
# atf_expect_fail "PR bin/46327" (now fixed?)
atf_check -o match:0 -e empty ${TEST_SH} -c 'false; true & echo $?'
}
atf_test_case function
function_head() {
atf_set "descr" "Tests that \$? is correctly updated inside" \
"a function"
atf_set "descr" "Tests that \$? is correctly updated inside " \
"a function"
}
function_body() {
foo=`crud`
atf_check_equal 'x$foo' 'x1'
atf_check -s exit:0 -o match:STATUS=1-0 -e empty \
${TEST_SH} -c '
crud() {
test yes = no
cat <<-EOF
STATUS=$?
EOF
}
foo=$(crud)
echo "${foo}-$?"
'
}
atf_test_case readout
readout_head() {
atf_set "descr" "Tests that \$? is correctly updated in a" \
"compound expression"
atf_set "descr" "Tests that \$? is correctly updated in a " \
"compound expression"
}
readout_body() {
atf_check_equal '$( true && ! true | false; echo $? )' '0'
atf_check -s exit:0 -o match:0 -e empty \
${TEST_SH} -c 'true && ! true | false; echo $?'
}
atf_test_case trap_subshell
trap_subshell_head() {
atf_set "descr" "Tests that the trap statement in a subshell" \
"works when the subshell exits"
atf_set "descr" "Tests that the trap statement in a subshell " \
"works when the subshell exits"
}
trap_subshell_body() {
atf_check -s eq:0 -o inline:'exiting\n' -x \
'( trap "echo exiting" EXIT; /usr/bin/true )'
atf_check -s exit:0 -o inline:'exiting\n' -e empty \
${TEST_SH} -c '( trap "echo exiting" EXIT; /usr/bin/true )'
}
atf_test_case trap_zero__implicit_exit
trap_zero__implicit_exit_head() {
atf_set "descr" "Tests that the trap statement in a subshell in a " \
"script works when the subshell simply runs out of commands"
}
trap_zero__implicit_exit_body() {
# PR bin/6764: sh works but ksh does not"
# PR bin/6764: sh works but ksh does not
echo '( trap "echo exiting" 0 )' >helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/sh helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/ksh helper.sh
atf_check -s exit:0 -o match:exiting -e empty ${TEST_SH} helper.sh
# test ksh by setting TEST_SH to /bin/ksh and run the entire set...
# atf_check -s exit:0 -o match:exiting -e empty /bin/ksh helper.sh
}
atf_test_case trap_zero__explicit_exit
trap_zero__explicit_exit_head() {
atf_set "descr" "Tests that the trap statement in a subshell in a " \
"script works when the subshell executes an explicit exit"
}
trap_zero__explicit_exit_body() {
echo '( trap "echo exiting" 0; exit )' >helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/sh helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/ksh helper.sh
echo '( trap "echo exiting" 0; exit; echo NO_NO_NO )' >helper.sh
atf_check -s exit:0 -o match:exiting -o not-match:NO_NO -e empty \
${TEST_SH} helper.sh
# test ksh by setting TEST_SH to /bin/ksh and run the entire set...
# atf_check -s exit:0 -o match:exiting -e empty /bin/ksh helper.sh
}
atf_test_case trap_zero__explicit_return
trap_zero__explicit_return_body() {
echo '( trap "echo exiting" 0; return )' >helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/sh helper.sh
atf_check -s eq:0 -o match:exiting -e empty /bin/ksh helper.sh
atf_test_case simple_exit
simple_exit_head() {
atf_set "descr" "Tests that various values for exit status work"
}
# Note: ATF will not allow tests of exit values > 255, even if they would work
simple_exit_body() {
for N in 0 1 2 3 4 5 6 42 99 101 125 126 127 128 129 200 254 255
do
atf_check -s exit:$N -o empty -e empty \
${TEST_SH} -c "exit $N; echo FOO; echo BAR >&2"
done
}
atf_test_case subshell_exit
subshell_exit_head() {
atf_set "descr" "Tests that subshell exit status works and \$? gets it"
}
# Note: ATF will not allow tests of exit values > 255, even if they would work
subshell_exit_body() {
for N in 0 1 2 3 4 5 6 42 99 101 125 126 127 128 129 200 254 255
do
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c "(exit $N); test \$? -eq $N"
done
}
atf_test_case subshell_background
subshell_background_head() {
atf_set "descr" "Tests that sh(1) sets '$?' properly when running " \
"a subshell in the background"
}
subshell_background_body() {
atf_check -o match:0 -e empty \
${TEST_SH} -c 'true; (false || true) & echo $?'
# atf_expect_fail "PR bin/46327" (now fixed?)
atf_check -o match:0 -e empty \
${TEST_SH} -c 'false; (false || true) & echo $?'
}
atf_init_test_cases() {
@ -101,5 +151,7 @@ atf_init_test_cases() {
atf_add_test_case trap_subshell
atf_add_test_case trap_zero__implicit_exit
atf_add_test_case trap_zero__explicit_exit
atf_add_test_case trap_zero__explicit_return
atf_add_test_case simple_exit
atf_add_test_case subshell_exit
atf_add_test_case subshell_background
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_expand.sh,v 1.2 2013/10/06 21:05:50 ast Exp $
# $NetBSD: t_expand.sh,v 1.8 2016/04/29 18:29:17 christos Exp $
#
# Copyright (c) 2007, 2009 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,6 +24,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
#
# This file tests the functions in expand.c.
@ -50,19 +52,15 @@ dollar_at_head() {
}
dollar_at_body() {
# This one should work everywhere.
got=`echo "" "" | sed 's,$,EOL,'`
atf_check_equal ' EOL' '$got'
atf_check -s exit:0 -o inline:' EOL\n' -e empty \
${TEST_SH} -c 'echo "" "" | '" sed 's,\$,EOL,'"
# This code triggered the bug.
set -- "" ""
got=`echo "$@" | sed 's,$,EOL,'`
atf_check_equal ' EOL' '$got'
atf_check -s exit:0 -o inline:' EOL\n' -e empty \
${TEST_SH} -c 'set -- "" ""; echo "$@" | '" sed 's,\$,EOL,'"
set -- -
shift
n_arg() { echo $#; }
n_args=`n_arg "$@"`
atf_check_equal '0' '$n_args'
atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
'set -- -; shift; n_arg() { echo $#; }; n_arg "$@"'
}
atf_test_case dollar_at_with_text
@ -71,15 +69,61 @@ dollar_at_with_text_head() {
"within the quotes. PR bin/33956."
}
dollar_at_with_text_body() {
set --
atf_check_equal '' "$(delim_argv "$@")"
atf_check_equal '>foobar<' "$(delim_argv "foo$@bar")"
atf_check_equal '>foo bar<' "$(delim_argv "foo $@ bar")"
set -- a b c
atf_check_equal '>a< >b< >c<' "$(delim_argv "$@")"
atf_check_equal '>fooa< >b< >cbar<' "$(delim_argv "foo$@bar")"
atf_check_equal '>foo a< >b< >c bar<' "$(delim_argv "foo $@ bar")"
cat <<'EOF' > h-f1
delim_argv() {
str=
while [ $# -gt 0 ]; do
if [ -z "${str}" ]; then
str=">$1<"
else
str="${str} >$1<"
fi
shift
done
echo "${str}"
}
EOF
cat <<'EOF' > h-f2
delim_argv() {
str=
while [ $# -gt 0 ]; do
str="${str}${str:+ }>$1<"
shift
done
echo "${str}"
}
EOF
chmod +x h-f1 h-f2
for f in 1 2
do
atf_check -s exit:0 -o inline:'\n' -e empty ${TEST_SH} -c \
". ./h-f${f}; "'set -- ; delim_argv "$@"'
atf_check -s exit:0 -o inline:'>foobar<\n' -e empty \
${TEST_SH} -c \
". ./h-f${f}; "'set -- ; delim_argv "foo$@bar"'
atf_check -s exit:0 -o inline:'>foo bar<\n' -e empty \
${TEST_SH} -c \
". ./h-f${f}; "'set -- ; delim_argv "foo $@ bar"'
atf_check -s exit:0 -o inline:'>a< >b< >c<\n' -e empty \
${TEST_SH} -c \
". ./h-f${f}; "'set -- a b c; delim_argv "$@"'
atf_check -s exit:0 -o inline:'>fooa< >b< >cbar<\n' -e empty \
${TEST_SH} -c \
". ./h-f${f}; "'set -- a b c; delim_argv "foo$@bar"'
atf_check -s exit:0 -o inline:'>foo a< >b< >c bar<\n' -e empty \
${TEST_SH} -c \
". ./h-f${f}; "'set -- a b c; delim_argv "foo $@ bar"'
done
}
atf_test_case strip
@ -91,8 +135,25 @@ strip_head() {
strip_body() {
line='#define bindir "/usr/bin" /* comment */'
stripped='#define bindir "/usr/bin" '
atf_expect_fail "PR bin/43469"
atf_check_equal '$stripped' '${line%%/\**}'
# atf_expect_fail "PR bin/43469" -- now fixed
for exp in \
'${line%%/\**}' \
'${line%%"/*"*}' \
'${line%%'"'"'/*'"'"'*}' \
'"${line%%/\**}"' \
'"${line%%"/*"*}"' \
'"${line%%'"'"'/*'"'"'*}"' \
'${line%/\**}' \
'${line%"/*"*}' \
'${line%'"'"'/*'"'"'*}' \
'"${line%/\**}"' \
'"${line%"/*"*}"' \
'"${line%'"'"'/*'"'"'*}"'
do
atf_check -o inline:":$stripped:\n" -e empty ${TEST_SH} -c \
"line='${line}'; echo :${exp}:"
done
}
atf_test_case varpattern_backslashes
@ -103,7 +164,8 @@ varpattern_backslashes_head() {
varpattern_backslashes_body() {
line='/foo/bar/*/baz'
stripped='/foo/bar/'
atf_check_equal $stripped ${line%%\**}
atf_check -o inline:'/foo/bar/\n' -e empty ${TEST_SH} -c \
'line="/foo/bar/*/baz"; echo ${line%%\**}'
}
atf_test_case arithmetic
@ -114,9 +176,13 @@ arithmetic_head() {
"this is true."
}
arithmetic_body() {
atf_check_equal '3' '$((1 + 2))'
atf_check_equal '2147483647' '$((0x7fffffff))'
atf_check_equal '9223372036854775807' '$(((1 << 63) - 1))'
atf_check -o inline:'3' -e empty ${TEST_SH} -c \
'printf %s $((1 + 2))'
atf_check -o inline:'2147483647' -e empty ${TEST_SH} -c \
'printf %s $((0x7fffffff))'
atf_check -o inline:'9223372036854775807' -e empty ${TEST_SH} -c \
'printf %s $(((1 << 63) - 1))'
}
atf_test_case iteration_on_null_parameter
@ -126,10 +192,178 @@ iteration_on_null_parameter_head() {
"PR bin/48202."
}
iteration_on_null_parameter_body() {
s1=`/bin/sh -uc 'N=; set -- ${N}; for X; do echo "[$X]"; done' 2>&1`
s2=`/bin/sh -uc 'N=; set -- ${N:-}; for X; do echo "[$X]"; done' 2>&1`
atf_check_equal '' '$s1'
atf_check_equal '[]' '$s2'
atf_check -o empty -e empty ${TEST_SH} -c \
'N=; set -- ${N}; for X; do echo "[$X]"; done'
}
atf_test_case iteration_on_quoted_null_parameter
iteration_on_quoted_null_parameter_head() {
atf_set "descr" \
'Check iteration of "$@" in for loop when set to null;'
}
iteration_on_quoted_null_parameter_body() {
atf_check -o inline:'[]\n' -e empty ${TEST_SH} -c \
'N=; set -- "${N}"; for X; do echo "[$X]"; done'
}
atf_test_case iteration_on_null_or_null_parameter
iteration_on_null_or_null_parameter_head() {
atf_set "descr" \
'Check expansion of null parameter as default for another null'
}
iteration_on_null_or_null_parameter_body() {
atf_check -o empty -e empty ${TEST_SH} -c \
'N=; E=; set -- ${N:-${E}}; for X; do echo "[$X]"; done'
}
atf_test_case iteration_on_null_or_missing_parameter
iteration_on_null_or_missing_parameter_head() {
atf_set "descr" \
'Check expansion of missing parameter as default for another null'
}
iteration_on_null_or_missing_parameter_body() {
# atf_expect_fail 'PR bin/50834'
atf_check -o empty -e empty ${TEST_SH} -c \
'N=; set -- ${N:-}; for X; do echo "[$X]"; done'
}
nl='
'
reset()
{
TEST_NUM=0
TEST_FAILURES=''
TEST_FAIL_COUNT=0
TEST_ID="$1"
}
check()
{
fail=false
TEMP_FILE=$( mktemp OUT.XXXXXX )
TEST_NUM=$(( $TEST_NUM + 1 ))
MSG=
# our local shell (ATF_SHELL) better do quoting correctly...
# some of the tests expect us to expand $nl internally...
CMD="$1"
result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
STATUS=$?
if [ "${STATUS}" -ne "$3" ]; then
MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
MSG="${MSG} expected exit code $3, got ${STATUS}"
# don't actually fail just because of wrong exit code
# unless we either expected, or received "good"
case "$3/${STATUS}" in
(*/0|0/*) fail=true;;
esac
fi
if [ "$3" -eq 0 ]; then
if [ -s "${TEMP_FILE}" ]; then
MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
MSG="${MSG} Messages produced on stderr unexpected..."
MSG="${MSG}${nl}$( cat "${TEMP_FILE}" )"
fail=true
fi
else
if ! [ -s "${TEMP_FILE}" ]; then
MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
MSG="${MSG} Expected messages on stderr,"
MSG="${MSG} nothing produced"
fail=true
fi
fi
rm -f "${TEMP_FILE}"
# Remove newlines (use local shell for this)
oifs="$IFS"
IFS="$nl"
result="$(echo $result)"
IFS="$oifs"
if [ "$2" != "$result" ]
then
MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
MSG="${MSG} Expected output '$2', received '$result'"
fail=true
fi
if $fail
then
MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
MSG="${MSG} Full command: <<${CMD}>>"
fi
$fail && test -n "$TEST_ID" && {
TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+${nl}}"
TEST_FAILURES="${TEST_FAILURES}${TEST_ID}[$TEST_NUM]:"
TEST_FAILURES="${TEST_FAILURES} Test of '$1' failed.";
TEST_FAILURES="${TEST_FAILURES}${nl}${MSG}"
TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
return 0
}
$fail && atf_fail "Test[$TEST_NUM] of '$1' failed${nl}${MSG}"
return 0
}
results()
{
test -z "${TEST_ID}" && return 0
test -z "${TEST_FAILURES}" && return 0
echo >&2 "=========================================="
echo >&2 "While testing '${TEST_ID}'"
echo >&2 " - - - - - - - - - - - - - - - - -"
echo >&2 "${TEST_FAILURES}"
atf_fail \
"Test ${TEST_ID}: $TEST_FAIL_COUNT subtests (of $TEST_NUM) failed - see stderr"
}
atf_test_case shell_params
shell_params_head() {
atf_set "descr" "Test correct operation of the numeric parameters"
}
shell_params_body() {
atf_require_prog mktemp
reset shell_params
check 'set -- a b c; echo "$#: $1 $2 $3"' '3: a b c' 0
check 'set -- a b c d e f g h i j k l m; echo "$#: ${1}0 ${10} $10"' \
'13: a0 j a0' 0
check 'x="$0"; set -- a b; y="$0";
[ "x${x}y" = "x${y}y" ] && echo OK || echo x="$x" y="$y"' \
'OK' 0
check "${TEST_SH} -c 'echo 0=\$0 1=\$1 2=\$2' a b c" '0=a 1=b 2=c' 0
echo 'echo 0="$0" 1="$1" 2="$2"' > helper.sh
check "${TEST_SH} helper.sh a b c" '0=helper.sh 1=a 2=b' 0
check 'set -- a bb ccc dddd eeeee ffffff ggggggg hhhhhhhh \
iiiiiiiii jjjjjjjjjj kkkkkkkkkkk
echo "${#}: ${#1} ${#2} ${#3} ${#4} ... ${#9} ${#10} ${#11}"' \
'11: 1 2 3 4 ... 9 10 11' 0
check 'set -- a b c; echo "$#: ${1-A} ${2-B} ${3-C} ${4-D} ${5-E}"' \
'3: a b c D E' 0
check 'set -- a "" c "" e
echo "$#: ${1:-A} ${2:-B} ${3:-C} ${4:-D} ${5:-E}"' \
'5: a B c D e' 0
check 'set -- a "" c "" e
echo "$#: ${1:+A} ${2:+B} ${3:+C} ${4:+D} ${5:+E}"' \
'5: A C E' 0
check 'set -- "abab*cbb"
echo "${1} ${1#a} ${1%b} ${1##ab} ${1%%b} ${1#*\*} ${1%\**}"' \
'abab*cbb bab*cbb abab*cb ab*cbb abab*cb cbb abab' 0
check 'set -- "abab?cbb"
echo "${1}:${1#*a}+${1%b*}-${1##*a}_${1%%b*}%${1#[ab]}=${1%?*}/${1%\?*}"' \
'abab?cbb:bab?cbb+abab?cb-b?cbb_a%bab?cbb=abab?cb/abab' 0
check 'set -- a "" c "" e; echo "${2:=b}"' '' 1
results
}
atf_init_test_cases() {
@ -139,4 +373,8 @@ atf_init_test_cases() {
atf_add_test_case varpattern_backslashes
atf_add_test_case arithmetic
atf_add_test_case iteration_on_null_parameter
atf_add_test_case iteration_on_quoted_null_parameter
atf_add_test_case iteration_on_null_or_null_parameter
atf_add_test_case iteration_on_null_or_missing_parameter
atf_add_test_case shell_params
}

View file

@ -1,6 +1,6 @@
# $NetBSD: t_fsplit.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $
# $NetBSD: t_fsplit.sh,v 1.4 2016/03/27 14:50:01 christos Exp $
#
# Copyright (c) 2007 The NetBSD Foundation, Inc.
# Copyright (c) 2007-2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -33,22 +33,51 @@
# the "${x-" and "}" were absent from the input line.
#
# So: sh -c 'set ${x-a b c}; echo $#' should give 3.
# and: sh -c 'set -- ${x-}' echo $#' shold give 0
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
nl='
'
check()
{
result="$(eval $1)"
TEST=$((${TEST} + 1))
case "$#" in
(2) ;;
(*) atf_fail "Internal test error, $# args to check test ${TEST}";;
esac
result=$( ${TEST_SH} -c "unset x; $1" )
STATUS="$?"
# Remove newlines
oifs="$IFS"
IFS="$nl"
result="$(echo $result)"
IFS="$oifs"
# trim the test text in case we use it in a message below
case "$1" in
????????????????*)
set -- "$(expr "$1" : '\(............\).*')..." "$2" ;;
esac
if [ "$2" != "$result" ]
then
atf_fail "expected [$2], found [$result]"
if [ "${STATUS}" = "0" ]
then
atf_fail "Test ${TEST} '$1': expected [$2], found [$result]"
else
atf_fail \
"TEST ${TEST} '$1' failed ($STATUS): expected [$2], found [$result]"
fi
elif [ "${STATUS}" != 0 ]
then
atf_fail "TEST ${TEST} '$1' failed ($STATUS)"
fi
}
@ -59,6 +88,7 @@ for_head() {
for_body() {
unset x
TEST=0
# Since I managed to break this, leave the test in
check 'for f in $x; do echo x${f}y; done' ''
}
@ -68,17 +98,121 @@ default_val_head() {
atf_set "descr" "Checks field splitting in variable default values"
}
default_val_body() {
unset x
TEST=0
# Check that IFS is applied to text from ${x-...} unless it is inside
# any set of "..."
check 'set ${x-a b c}; echo $#' 3
check 'for i in ${x-a b c}; do echo "z${i}z"; done' 'zaz zbz zcz'
check 'for i in ${x-"a b" c}; do echo "z${i}z"; done' 'za bz zcz'
check 'for i in ${x-"a ${x-b c}" d}; do echo "z${i}z"; done' 'za b cz zdz'
check 'for i in ${x-"a ${x-"b c"}" d}; do echo "z${i}z"; done' 'za b cz zdz'
check 'for i in ${x-a ${x-"b c"} d}; do echo "z${i}z"; done' 'zaz zb cz zdz'
check 'for i in ${x-a ${x-b c} d}; do echo "z${i}z"; done' 'zaz zbz zcz zdz'
check 'set -- ${x-a b c}; echo $#' 3
check 'set -- ${x-"a b" c}; echo $#' 2
check 'set -- ${x-a "b c"}; echo $#' 2
check 'set -- ${x-"a b c"}; echo $#' 1
check "set -- \${x-'a b' c}; echo \$#" 2
check "set -- \${x-a 'b c'}; echo \$#" 2
check "set -- \${x-'a b c'}; echo \$#" 1
check 'set -- ${x-a\ b c}; echo $#' 2
check 'set -- ${x-a b\ c}; echo $#' 2
check 'set -- ${x-a\ b\ c}; echo $#' 1
check 'set -- ${x}; echo $#' 0
check 'set -- ${x-}; echo $#' 0
check 'set -- ${x-""}; echo $#' 1
check 'set -- ""${x}; echo $#' 1
check 'set -- ""${x-}; echo $#' 1
check 'set -- ""${x-""}; echo $#' 1
check 'set -- ${x}""; echo $#' 1
check 'set -- ${x-}""; echo $#' 1
check 'set -- ${x-""}""; echo $#' 1
check 'set -- ""${x}""; echo $#' 1
check 'set -- ""${x-}""; echo $#' 1
check 'set -- ""${x-""}""; echo $#' 1
check 'for i in ${x-a b c}; do echo "z${i}z"; done' \
'zaz zbz zcz'
check 'for i in ${x-"a b" c}; do echo "z${i}z"; done' \
'za bz zcz'
check 'for i in ${x-"a ${x-b c}" d}; do echo "z${i}z"; done' \
'za b cz zdz'
check 'for i in ${x-a ${x-b c} d}; do echo "z${i}z"; done' \
'zaz zbz zcz zdz'
# I am not sure these two are correct, the rules on quoting word
# in ${var-word} are peculiar, and hard to fathom...
# They are what the NetBSD shell does, and bash, not the freebsd shell
# (as of Mar 1, 2016)
check 'for i in ${x-"a ${x-"b c"}" d}; do echo "z${i}z"; done' \
'za b cz zdz'
check 'for i in ${x-a ${x-"b c"} d}; do echo "z${i}z"; done' \
'zaz zb cz zdz'
}
atf_test_case replacement_val
replacement_val_head() {
atf_set "descr" "Checks field splitting in variable replacement values"
}
replacement_val_body() {
TEST=0
# Check that IFS is applied to text from ${x+...} unless it is inside
# any set of "...", or whole expansion is quoted, or both...
check 'x=BOGUS; set -- ${x+a b c}; echo $#' 3
check 'x=BOGUS; set -- ${x+"a b" c}; echo $#' 2
check 'x=BOGUS; set -- ${x+a "b c"}; echo $#' 2
check 'x=BOGUS; set -- ${x+"a b c"}; echo $#' 1
check "x=BOGUS; set -- \${x+'a b' c}; echo \$#" 2
check "x=BOGUS; set -- \${x+a 'b c'}; echo \$#" 2
check "x=BOGUS; set -- \${x+'a b c'}; echo \$#" 1
check 'x=BOGUS; set -- ${x+a\ b c}; echo $#' 2
check 'x=BOGUS; set -- ${x+a b\ c}; echo $#' 2
check 'x=BOGUS; set -- ${x+a\ b\ c}; echo $#' 1
check 'x=BOGUS; set -- ${x+}; echo $#' 0
check 'x=BOGUS; set -- ${x+""}; echo $#' 1
check 'x=BOGUS; set -- ""${x+}; echo $#' 1
check 'x=BOGUS; set -- ""${x+""}; echo $#' 1
check 'x=BOGUS; set -- ${x+}""; echo $#' 1
check 'x=BOGUS; set -- ${x+""}""; echo $#' 1
check 'x=BOGUS; set -- ""${x+}""; echo $#' 1
check 'x=BOGUS; set -- ""${x+""}""; echo $#' 1
# verify that the value of $x does not affecty the value of ${x+...}
check 'x=BOGUS; set -- ${x+}; echo X$1' X
check 'x=BOGUS; set -- ${x+""}; echo X$1' X
check 'x=BOGUS; set -- ""${x+}; echo X$1' X
check 'x=BOGUS; set -- ""${x+""}; echo X$1' X
check 'x=BOGUS; set -- ${x+}""; echo X$1' X
check 'x=BOGUS; set -- ${x+""}""; echo X$1' X
check 'x=BOGUS; set -- ""${x+}""; echo X$1' X
check 'x=BOGUS; set -- ""${x+""}""; echo X$1' X
check 'x=BOGUS; set -- ${x+}; echo X${1-:}X' X:X
check 'x=BOGUS; set -- ${x+""}; echo X${1-:}X' XX
check 'x=BOGUS; set -- ""${x+}; echo X${1-:}X' XX
check 'x=BOGUS; set -- ""${x+""}; echo X${1-:}X' XX
check 'x=BOGUS; set -- ${x+}""; echo X${1-:}X' XX
check 'x=BOGUS; set -- ${x+""}""; echo X${1-:}X' XX
check 'x=BOGUS; set -- ""${x+}""; echo X${1-:}X' XX
check 'x=BOGUS; set -- ""${x+""}""; echo X${1-:}X' XX
# and validate that the replacement can be used as expected
check 'x=BOGUS; for i in ${x+a b c}; do echo "z${i}z"; done'\
'zaz zbz zcz'
check 'x=BOGUS; for i in ${x+"a b" c}; do echo "z${i}z"; done'\
'za bz zcz'
check 'x=BOGUS; for i in ${x+"a ${x+b c}" d}; do echo "z${i}z"; done'\
'za b cz zdz'
check 'x=BOGUS; for i in ${x+"a ${x+"b c"}" d}; do echo "z${i}z"; done'\
'za b cz zdz'
check 'x=BOGUS; for i in ${x+a ${x+"b c"} d}; do echo "z${i}z"; done'\
'zaz zb cz zdz'
check 'x=BOGUS; for i in ${x+a ${x+b c} d}; do echo "z${i}z"; done'\
'zaz zbz zcz zdz'
}
atf_test_case ifs_alpha
@ -89,13 +223,19 @@ ifs_alpha_head() {
ifs_alpha_body() {
unset x
TEST=0
# repeat with an alphabetic in IFS
check 'IFS=q; set ${x-aqbqc}; echo $#' 3
check 'IFS=q; for i in ${x-aqbqc}; do echo "z${i}z"; done' 'zaz zbz zcz'
check 'IFS=q; for i in ${x-"aqb"qc}; do echo "z${i}z"; done' 'zaqbz zcz'
check 'IFS=q; for i in ${x-"aq${x-bqc}"qd}; do echo "z${i}z"; done' 'zaqbqcz zdz'
check 'IFS=q; for i in ${x-"aq${x-"bqc"}"qd}; do echo "z${i}z"; done' 'zaqbqcz zdz'
check 'IFS=q; for i in ${x-aq${x-"bqc"}qd}; do echo "z${i}z"; done' 'zaz zbqcz zdz'
check 'IFS=q; for i in ${x-aqbqc}; do echo "z${i}z"; done' \
'zaz zbz zcz'
check 'IFS=q; for i in ${x-"aqb"qc}; do echo "z${i}z"; done' \
'zaqbz zcz'
check 'IFS=q; for i in ${x-"aq${x-bqc}"qd}; do echo "z${i}z"; done' \
'zaqbqcz zdz'
check 'IFS=q; for i in ${x-"aq${x-"bqc"}"qd}; do echo "z${i}z"; done' \
'zaqbqcz zdz'
check 'IFS=q; for i in ${x-aq${x-"bqc"}qd}; do echo "z${i}z"; done' \
'zaz zbqcz zdz'
}
atf_test_case quote
@ -106,6 +246,7 @@ quote_head() {
quote_body() {
unset x
TEST=0
# Some quote propagation checks
check 'set "${x-a b c}"; echo $#' 1
check 'set "${x-"a b" c}"; echo $1' 'a b c'
@ -120,19 +261,44 @@ dollar_at_head() {
dollar_at_body() {
unset x
TEST=0
# Check we get "$@" right
check 'set ""; for i; do echo "z${i}z"; done' 'zz'
check 'set ""; for i in "$@"; do echo "z${i}z"; done' 'zz'
check 'set "" ""; for i; do echo "z${i}z"; done' 'zz zz'
check 'set "" ""; for i in "$@"; do echo "z${i}z"; done' 'zz zz'
check 'set "" ""; for i in $@; do echo "z${i}z"; done' ''
check 'set "a b" c; for i; do echo "z${i}z"; done' 'za bz zcz'
check 'set "a b" c; for i in "$@"; do echo "z${i}z"; done' 'za bz zcz'
check 'set "a b" c; for i in $@; do echo "z${i}z"; done' 'zaz zbz zcz'
check 'set " a b " c; for i in "$@"; do echo "z${i}z"; done' 'z a b z zcz'
check 'set --; for i in x"$@"x; do echo "z${i}z"; done' 'zxxz'
check 'set a; for i in x"$@"x; do echo "z${i}z"; done' 'zxaxz'
check 'set a b; for i in x"$@"x; do echo "z${i}z"; done' 'zxaz zbxz'
check 'set --; for i in x"$@"x; do echo "z${i}z"; done' 'zxxz'
check 'set a; for i in x"$@"x; do echo "z${i}z"; done' 'zxaxz'
check 'set a b; for i in x"$@"x; do echo "z${i}z"; done' 'zxaz zbxz'
check 'set --; for i; do echo "z${i}z"; done' ''
check 'set --; for i in $@; do echo "z${i}z"; done' ''
check 'set --; for i in "$@"; do echo "z${i}z"; done' ''
# atf_expect_fail "PR bin/50834"
check 'set --; for i in ""$@; do echo "z${i}z"; done' 'zz'
# atf_expect_pass
check 'set --; for i in $@""; do echo "z${i}z"; done' 'zz'
check 'set --; for i in ""$@""; do echo "z${i}z"; done' 'zz'
check 'set --; for i in """$@"; do echo "z${i}z"; done' 'zz'
check 'set --; for i in "$@"""; do echo "z${i}z"; done' 'zz'
check 'set --; for i in """$@""";do echo "z${i}z"; done' 'zz'
check 'set ""; for i; do echo "z${i}z"; done' 'zz'
check 'set ""; for i in "$@"; do echo "z${i}z"; done' 'zz'
check 'set "" ""; for i; do echo "z${i}z"; done' 'zz zz'
check 'set "" ""; for i in "$@"; do echo "z${i}z"; done' 'zz zz'
check 'set "" ""; for i in $@; do echo "z${i}z"; done' ''
check 'set "a b" c; for i; do echo "z${i}z"; done' \
'za bz zcz'
check 'set "a b" c; for i in "$@"; do echo "z${i}z"; done' \
'za bz zcz'
check 'set "a b" c; for i in $@; do echo "z${i}z"; done' \
'zaz zbz zcz'
check 'set " a b " c; for i in "$@"; do echo "z${i}z"; done' \
'z a b z zcz'
check 'set a b c; for i in "$@$@"; do echo "z${i}z"; done' \
'zaz zbz zcaz zbz zcz'
check 'set a b c; for i in "$@""$@";do echo "z${i}z"; done' \
'zaz zbz zcaz zbz zcz'
}
atf_test_case ifs
@ -143,6 +309,7 @@ ifs_head() {
ifs_body() {
unset x
TEST=0
# Some IFS tests
check 't="-- "; IFS=" "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '0'
check 't=" x"; IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1'
@ -165,19 +332,26 @@ var_length_head() {
"a variable's length"
}
var_length_body() {
unset x
TEST=0
# Check that we apply IFS to ${#var}
long=12345678123456781234567812345678
long=$long$long$long$long
check 'echo ${#long}; IFS=2; echo ${#long}; set 1 ${#long};echo $#' '128 1 8 3'
check 'IFS=2; set ${x-${#long}}; IFS=" "; echo $* $#' '1 8 2'
check 'IFS=2; set ${x-"${#long}"}; IFS=" "; echo $* $#' '128 1'
export long
# first test that the test method works...
check 'set -u; : ${long}; echo ${#long}' '128'
# Check that we apply IFS to ${#var}
check 'echo ${#long}; IFS=2; echo ${#long}; set 1 ${#long};echo $#' \
'128 1 8 3'
check 'IFS=2; set ${x-${#long}}; IFS=" "; echo $* $#' '1 8 2'
check 'IFS=2; set ${x-"${#long}"}; IFS=" "; echo $* $#' '128 1'
}
atf_init_test_cases() {
atf_add_test_case for
atf_add_test_case default_val
atf_add_test_case replacement_val
atf_add_test_case ifs_alpha
atf_add_test_case quote
atf_add_test_case dollar_at

View file

@ -1,4 +1,4 @@
# $NetBSD: t_here.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $
# $NetBSD: t_here.sh,v 1.6 2016/03/31 16:21:52 christos Exp $
#
# Copyright (c) 2007 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,50 +24,542 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
nl='
'
reset()
{
TEST_NUM=0
TEST_FAILURES=''
TEST_FAIL_COUNT=0
TEST_ID="$1"
}
check()
{
SVIFS="$IFS"
result="$(eval $1)"
# Remove newlines
fail=false
TEMP_FILE=$( mktemp OUT.XXXXXX )
TEST_NUM=$(( $TEST_NUM + 1 ))
# our local shell (ATF_SHELL) better do quoting correctly...
# some of the tests expect us to expand $nl internally...
CMD="nl='${nl}'; $1"
result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
STATUS=$?
if [ "${STATUS}" -ne "$3" ]; then
echo >&2 "[$TEST_NUM] expected exit code $3, got ${STATUS}"
# don't actually fail just because of wrong exit code
# unless we either expected, or received "good"
case "$3/${STATUS}" in
(*/0|0/*) fail=true;;
esac
fi
if [ "$3" -eq 0 ]; then
if [ -s "${TEMP_FILE}" ]; then
echo >&2 \
"[$TEST_NUM] Messages produced on stderr unexpected..."
cat "${TEMP_FILE}" >&2
fail=true
fi
else
if ! [ -s "${TEMP_FILE}" ]; then
echo >&2 \
"[$TEST_NUM] Expected messages on stderr, nothing produced"
fail=true
fi
fi
rm -f "${TEMP_FILE}"
# Remove newlines (use local shell for this)
oifs="$IFS"
IFS="$nl"
result="$(echo $result)"
IFS="$oifs"
if [ "$2" != "$result" ]
then
atf_fail "expected [$2], found [$result]"
echo >&2 "[$TEST_NUM] Expected output '$2', received '$result'"
fail=true
fi
IFS="$SVIFS"
if $fail
then
echo >&2 "[$TEST_NUM] Full command: <<${CMD}>>"
fi
$fail && test -n "$TEST_ID" && {
TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+
}${TEST_ID}[$TEST_NUM]: test of '$1' failed";
TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
return 0
}
$fail && atf_fail "Test[$TEST_NUM] of '$1' failed"
return 0
}
atf_test_case all
all_head() {
results()
{
test -z "${TEST_ID}" && return 0
test -z "${TEST_FAILURES}" && return 0
echo >&2 "=========================================="
echo >&2 "While testing '${TEST_ID}'"
echo >&2 " - - - - - - - - - - - - - - - - -"
echo >&2 "${TEST_FAILURES}"
atf_fail \
"Test ${TEST_ID}: $TEST_FAIL_COUNT subtests (of $TEST_NUM) failed - see stderr"
}
atf_test_case do_simple
do_simple_head() {
atf_set "descr" "Basic tests for here documents"
}
all_body() {
do_simple_body() {
y=x
IFS=
check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text'
check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text'
reset 'simple'
IFS=' '
check 'x=`cat <<EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
check 'x=`cat <<\EOF'$nl'text'${nl}EOF$nl'`; echo $x' 'text' 0
check 'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' 'text'
check 'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' 'te${y}t'
check 'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x' 'te${y}t'
check 'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x' 'te${y}t'
check "y=${y};"'x=`cat <<EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
'text' 0
check "y=${y};"'x=`cat <<\EOF'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
'te${y}t' 0
check "y=${y};"'x=`cat <<"EOF"'$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
'te${y}t' 0
check "y=${y};"'x=`cat <<'"'EOF'"$nl'te${y}t'${nl}EOF$nl'`; echo $x' \
'te${y}t' 0
check 'x=`cat <<EOF'$nl'te'"'"'xt'${nl}EOF$nl'`; echo $x' 'te'"'"'xt'
check 'x=`cat <<\EOF'$nl'te'"'"'xt'${nl}EOF$nl'`; echo $x' 'te'"'"'xt'
check 'x=`cat <<"EOF"'$nl'te'"'"'xt'${nl}EOF$nl'`; echo $x' 'te'"'"'xt'
# check that quotes in the here doc survive and cause no problems
check "cat <<EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
check "cat <<\EOF${nl}te'xt${nl}EOF$nl" "te'xt" 0
check "cat <<'EOF'${nl}te'xt${nl}EOF$nl" "te'xt" 0
check "cat <<EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
check "cat <<\EOF${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
check "cat <<'EOF'${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
check "cat <<'EO'F${nl}te\"xt${nl}EOF$nl" 'te"xt' 0
check 'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' 'te'"'"'xt'
check 'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' 'te'"''"'xt'
check "y=${y};"'x=`cat <<EOF'$nl'te'"'"'${y}t'${nl}EOF$nl'`; echo $x' \
'te'"'"'xt' 0
check "y=${y};"'x=`cat <<EOF'$nl'te'"''"'${y}t'${nl}EOF$nl'`; echo $x' \
'te'"''"'xt' 0
# note that the blocks of empty space in the following must
# be entirely tab characters, no spaces.
check 'x=`cat <<EOF'"$nl text${nl}EOF$nl"'`; echo "$x"' \
' text' 0
check 'x=`cat <<-EOF'"$nl text${nl}EOF$nl"'`; echo $x' \
'text' 0
check 'x=`cat <<-EOF'"${nl}text${nl} EOF$nl"'`; echo $x' \
'text' 0
check 'x=`cat <<-\EOF'"$nl text${nl} EOF$nl"'`; echo $x' \
'text' 0
check 'x=`cat <<- "EOF"'"$nl text${nl}EOF$nl"'`; echo $x' \
'text' 0
check 'x=`cat <<- '"'EOF'${nl}text${nl} EOF$nl"'`; echo $x' \
'text' 0
results
}
atf_test_case end_markers
end_markers_head() {
atf_set "descr" "Tests for various end markers of here documents"
}
end_markers_body() {
reset 'end_markers'
for end in EOF 1 \! '$$$' "string " a\\\ a\\\ \ '&' '' ' ' ' ' \
--STRING-- . '~~~' ')' '(' '#' '()' '(\)' '(\/)' '--' '\' '{' '}' \
VERYVERYVERYVERYLONGLONGLONGin_fact_absurdly_LONG_LONG_HERE_DOCUMENT_TERMINATING_MARKER_THAT_goes_On_forever_and_ever_and_ever...
do
# check unquoted end markers
case "${end}" in
('' | *[' ()\$&#*~']* ) ;; # skip unquoted endmark test for these
(*) check \
'x=$(cat << '"${end}${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
;;
esac
# and quoted end markers
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end}${nl}"'); printf %s "$x"' 'text' 0
# and see what happens if we encounter "almost" an end marker
case "${#end}" in
(0|1) ;; # too short to try truncation tests
(*) check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end%?}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end#?}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end#?}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end%?}+${nl}${end}${nl}"');printf %s "$x"' \
"text ${end%?}+" 0
;;
esac
# or something that is a little longer
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end}x${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}x" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}!${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text !${end}" 0
# or which does not begin at start of line
check \
'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl} ${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}" 0
# or end at end of line
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end} ${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end} " 0
# or something that is correct much of the way, but then...
case "${#end}" in
(0) ;; # cannot test this one
(1) check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end}${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}${end}" 0
;;
(2-7) pfx="${end%?}"
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end}${pfx}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}${pfx}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${pfx}${end}" 0
;;
(*) pfx=${end%??????}; sfx=${end#??????}
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${end}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${end}${sfx}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${end}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${pfx}${end}" 0
check \
'x=$(cat <<'"'${end}'${nl}text${nl}${pfx}${sfx}${nl}${end}${nl}"'); printf %s "$x"' \
"text ${pfx}${sfx}" 0
;;
esac
done
# Add striptabs tests (in similar way) here one day...
results
}
atf_test_case incomplete
incomplete_head() {
atf_set "descr" "Basic tests for incomplete here documents"
}
incomplete_body() {
reset incomplete
check 'cat <<EOF' '' 2
check 'cat <<- EOF' '' 2
check 'cat <<\EOF' '' 2
check 'cat <<- \EOF' '' 2
check 'cat <<EOF'"${nl}" '' 2
check 'cat <<- EOF'"${nl}" '' 2
check 'cat <<'"'EOF'${nl}" '' 2
check 'cat <<- "EOF"'"${nl}" '' 2
check 'cat << EOF'"${nl}${nl}" '' 2
check 'cat <<-EOF'"${nl}${nl}" '' 2
check 'cat << '"'EOF'${nl}${nl}" '' 2
check 'cat <<-"EOF"'"${nl}${nl}" '' 2
check 'cat << EOF'"${nl}"'line 1'"${nl}" '' 2
check 'cat <<-EOF'"${nl}"' line 1'"${nl}" '' 2
check 'cat << EOF'"${nl}"'line 1'"${nl}"' line 2'"${nl}" '' 2
check 'cat <<-EOF'"${nl}"' line 1'"${nl}"'line 2'"${nl}" '' 2
check 'cat << EOF'"${nl}line 1${nl}${nl}line3${nl}${nl}5!${nl}" '' 2
results
}
atf_test_case lineends
lineends_head() {
atf_set "descr" "Tests for line endings in here documents"
}
lineends_body() {
reset lineends
# note that "check" removes newlines from stdout before comparing.
# (they become blanks, provided there is something before & after)
check 'cat << \echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" '\' 0
check 'cat << echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" 'echo' 0
check 'cat << echo'"${nl}"'\\'"${nl}echo${nl}echo${nl}" '\' 0
check 'X=3; cat << ec\ho'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
'$X\' 0
check 'X=3; cat << echo'"${nl}"'$X'"${nl}echo${nl}echo${nl}" \
'3' 0
check 'X=3; cat << echo'"${nl}"'$X\'"${nl}echo${nl}echo${nl}" \
'' 0
check 'X=3; cat << echo'"${nl}"'${X}\'"${nl}echo${nl}echo${nl}" \
'3echo' 0
check 'X=3; cat << echo'"${nl}"'\$X\'"${nl}echo${nl}echo${nl}" \
'$Xecho' 0
check 'X=3; cat << echo'"${nl}"'\\$X \'"${nl}echo${nl}echo${nl}" \
'\3 echo' 0
check \
'cat << "echo"'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
'line1\ line2\' 0
check \
'cat << echo'"${nl}"'line1\'"${nl}"'line2\'"${nl}echo${nl}echo${nl}" \
'line1line2echo' 0
results
}
atf_test_case multiple
multiple_head() {
atf_set "descr" "Tests for multiple here documents on one cmd line"
}
multiple_body() {
reset multiple
check \
"(cat ; cat <&3) <<EOF0 3<<EOF3${nl}STDIN${nl}EOF0${nl}-3-${nl}EOF3${nl}" \
'STDIN -3-' 0
check "(read line; echo \"\$line\"; cat <<EOF1; echo \"\$line\") <<EOF2
The File
EOF1
The Line
EOF2
" 'The Line The File The Line' 0
check "(read line; echo \"\$line\"; cat <<EOF; echo \"\$line\") <<EOF
The File
EOF
The Line
EOF
" 'The Line The File The Line' 0
check "V=1; W=2; cat <<-1; cat <<2; cat <<- 3; cat <<'4';"' cat <<\5
$V
$W
3
4
5
1
2
5
4*$W+\$V
3
$W
1
2
3
4
7+$V
$W+6
5
' '1 2 3 4 5 5 4*2+$V $W 1 2 3 7+$V $W+6' 0
results
}
atf_test_case nested
nested_head() {
atf_set "descr" "Tests for nested here documents for one cmd"
}
nested_body() {
reset nested
check \
'cat << EOF1'"${nl}"'$(cat << EOF2'"${nl}LINE${nl}EOF2${nl}"')'"${nl}EOF1${nl}"\
'LINE' 0
# This next one fails ... and correctly, so we will omit it (bad test)
# Reasoning is that the correct data "$(cat << EOF2)\nLINE\nEOF2\n" is
# collected for the outer (EOF1) heredoc, when that is parsed, it looks
# like
# $(cat <<EOF2)
# LINE
# EOF2
# which looks like a good command - except it is being parsed in "heredoc"
# syntax, which means it is enclosed in double quotes, which means that
# the newline after the ')' in the first line is not a newline token, but
# just a character. The EOF2 heredoc cannot start until after the next
# newline token, of which there are none here... LINE and EOF2 are just
# more data in the outer EOF1 heredoc for its "cat" command to read & write.
#
# The previous sub-test works because there the \n comes inside the
# $( ), and in there, the outside quoting rules are suspended, and it
# all starts again - so that \n is a newline token, and the EOF2 heredoc
# is processed.
#
# check \
# 'cat << EOF1'"${nl}"'$(cat << EOF2 )'"${nl}LINE${nl}EOF2${nl}EOF1${nl}" \
# 'LINE' 0
L='cat << EOF1'"${nl}"'LINE1$(cat << EOF2'"${nl}"
L="${L}"'LINE2$(cat << EOF3'"${nl}"
L="${L}"'LINE3$(cat << EOF4'"${nl}"
L="${L}"'LINE4$(cat << EOF5'"${nl}"
L="${L}LINE5${nl}EOF5${nl})4${nl}EOF4${nl})3${nl}"
L="${L}EOF3${nl})2${nl}EOF2${nl})1${nl}EOF1${nl}"
# That mess is ...
#
# cat <<EOF1
# LINE1$(cat << EOF2
# LINE2$(cat << EOF3
# LINE3$(cat << EOF4
# LINE4$(cat << EOF5
# LINE5
# EOF5
# )4
# EOF4
# )3
# EOF3
# )2
# EOF2
# )1
# EOF1
check "${L}" 'LINE1LINE2LINE3LINE4LINE54321' 0
results
}
atf_test_case quoting
quoting_head() {
atf_set "descr" "Tests for use of quotes inside here documents"
}
quoting_body() {
reset quoting
check 'X=!; cat <<- E\0F
<'\''"'\'' \\$X\$X "'\''" \\>
E0F
' '<'\''"'\'' \\$X\$X "'\''" \\>' 0
check 'X=!; cat <<- E0F
<'\''"'\'' \\$X\$X "'\''" \\>
E0F
' '<'\''"'\'' \!$X "'\''" \>' 0
check 'cat <<- END
$( echo "'\''" ) $( echo '\''"'\'' ) $( echo \\ )
END
' "' \" \\" 0
check 'X=12345; Y="string1 line1?-line2"; Z=; unset W; cat <<-EOF
${#X}${Z:-${Y}}${W+junk}${Y%%l*}${Y#*\?}
"$Z"'\''$W'\'' ${Y%" "*} $(( X + 54321 ))
EOF
' '5string1 line1?-line2string1 -line2 ""'\'\'' string1 66666' 0
results
}
atf_test_case side_effects
side_effects_head() {
atf_set "descr" "Tests how side effects in here documents are handled"
}
side_effects_body() {
atf_check -s exit:0 -o inline:'2\n1\n' -e empty ${TEST_SH} -c '
unset X
cat <<-EOF
${X=2}
EOF
echo "${X-1}"
'
}
atf_test_case vicious
vicious_head() {
atf_set "descr" "Tests for obscure and obnoxious uses of here docs"
}
vicious_body() {
reset
cat <<- \END_SCRIPT > script
cat <<ONE && cat \
<<TWO
a
ONE
b
TWO
END_SCRIPT
atf_check -s exit:0 -o inline:'a\nb\n' -e empty ${TEST_SH} script
# This next one is causing discussion currently (late Feb 2016)
# amongst stds writers & implementors. Consequently we
# will not check what it produces. The eventual result
# seems unlikely to be what we currently output, which
# is:
# A:echo line 1
# B:echo line 2)" && prefix DASH_CODE <<DASH_CODE
# B:echo line 3
# line 4
# line 5
#
# The likely intended output is ...
#
# A:echo line 3
# B:echo line 1
# line 2
# DASH_CODE:echo line 4)"
# DASH_CODE:echo line 5
#
# The difference is explained by differing opinions on just
# when processing of a here doc should start
cat <<- \END_SCRIPT > script
prefix() { sed -e "s/^/$1:/"; }
DASH_CODE() { :; }
prefix A <<XXX && echo "$(prefix B <<XXX
echo line 1
XXX
echo line 2)" && prefix DASH_CODE <<DASH_CODE
echo line 3
XXX
echo line 4)"
echo line 5
DASH_CODE
END_SCRIPT
# we will just verify that the shell can parse the
# script somehow, and doesn't fall over completely...
atf_check -s exit:0 -o ignore -e empty ${TEST_SH} script
}
atf_init_test_cases() {
atf_add_test_case all
atf_add_test_case do_simple # not worthy of a comment
atf_add_test_case end_markers # the mundane, the weird, the bizarre
atf_add_test_case incomplete # where the end marker isn't...
atf_add_test_case lineends # test weird line endings in heredocs
atf_add_test_case multiple # multiple << operators on one cmd
atf_add_test_case nested # here docs inside here docs
atf_add_test_case quoting # stuff quoted inside
atf_add_test_case side_effects # here docs that modify environment
atf_add_test_case vicious # evil test from the austin-l list...
}

674
bin/sh/t_option.sh Executable file
View file

@ -0,0 +1,674 @@
# $NetBSD: t_option.sh,v 1.3 2016/03/08 14:19:28 christos Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
# The standard
# http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
# says:
# ...[lots]
test_option_on_off()
{
atf_require_prog tr
for opt
do
# t is needed, as inside $()` $- appears to lose
# the 'e' option if it happened to already be
# set. Must check if that is what should
# happen, but that is a different issue.
test -z "${opt}" && continue
# if we are playing with more that one option at a
# time, the code below requires that we start with no
# options set, or it will mis-diagnose the situation
CLEAR=''
test "${#opt}" -gt 1 &&
CLEAR='xx="$-" && xx=$(echo "$xx" | tr -d cs) && test -n "$xx" && set +"$xx";'
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
"opt=${opt}"'
x() {
echo "ERROR: Unable to $1 option $2" >&2
exit 1
}
s() {
set -"$1"
t="$-"
x=$(echo "$t" | tr -d "$1")
test "$t" = "$x" && x set "$1"
return 0
}
c() {
set +"$1"
t="$-"
x=$(echo "$t" | tr -d "$1")
test "$t" != "$x" && x clear "$1"
return 0
}
'"${CLEAR}"'
# if we do not do this, -x tracing splatters stderr
# for some shells, -v does as well (is that correct?)
case "${opt}" in
(*[xv]*) exec 2>/dev/null;;
esac
o="$-"
x=$(echo "$o" | tr -d "$opt")
if [ "$o" = "$x" ]; then # option was off
s "${opt}"
c "${opt}"
else
c "${opt}"
s "${opt}"
fi
'
done
}
test_optional_on_off()
{
RET=0
OPTS=
for opt
do
test "${opt}" = n && continue
${TEST_SH} -c "set -${opt}" 2>/dev/null &&
OPTS="${OPTS} ${opt}" || RET=1
done
test -n "${OPTS}" && test_option_on_off ${OPTS}
return "${RET}"
}
atf_test_case set_a
set_a_head() {
atf_set "descr" "Tests that 'set -a' turns on all var export " \
"and that it behaves as defined by the standard"
}
set_a_body() {
atf_require_prog env
atf_require_prog grep
test_option_on_off a
# without -a, new variables should not be exported (so grep "fails")
atf_check -s exit:1 -o empty -e empty ${TEST_SH} -ce \
'unset VAR; set +a; VAR=value; env | grep "^VAR="'
# with -a, they should be
atf_check -s exit:0 -o match:VAR=value -e empty ${TEST_SH} -ce \
'unset VAR; set -a; VAR=value; env | grep "^VAR="'
}
atf_test_case set_C
set_C_head() {
atf_set "descr" "Tests that 'set -C' turns on no clobber mode " \
"and that it behaves as defined by the standard"
}
set_C_body() {
atf_require_prog ls
test_option_on_off C
# Check that the environment to use for the tests is sane ...
# we assume current dir is a new tempory directory & is empty
test -z "$(ls)" || atf_skip "Test execution directory not clean"
test -c "/dev/null" || atf_skip "Problem with /dev/null"
echo Dummy_Content > Junk_File
echo Precious_Content > Important_File
# Check that we can redirect onto file when -C is not set
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'
D=$(ls -l Junk_File) || exit 1
set +C
echo "Overwrite it now" > Junk_File
A=$(ls -l Junk_File) || exit 1
test "${A}" != "${D}"
'
# Check that we cannot redirect onto file when -C is set
atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} -c \
'
D=$(ls -l Important_File) || exit 1
set -C
echo "Fail to Overwrite it now" > Important_File
A=$(ls -l Important_File) || exit 1
test "${A}" = "${D}"
'
# Check that we can append to file, even when -C is set
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'
D=$(ls -l Junk_File) || exit 1
set -C
echo "Append to it now" >> Junk_File
A=$(ls -l Junk_File) || exit 1
test "${A}" != "${D}"
'
# Check that we abort on attempt to redirect onto file when -Ce is set
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'
set -Ce
echo "Fail to Overwrite it now" > Important_File
echo "Should not reach this point"
'
# Last check that we can override -C for when we really need to
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'
D=$(ls -l Junk_File) || exit 1
set -C
echo "Change the poor bugger again" >| Junk_File
A=$(ls -l Junk_File) || exit 1
test "${A}" != "${D}"
'
}
atf_test_case set_e
set_e_head() {
atf_set "descr" "Tests that 'set -e' turns on error detection " \
"and that a simple case behaves as defined by the standard"
}
set_e_body() {
test_option_on_off e
# Check that -e does nothing if no commands fail
atf_check -s exit:0 -o match:I_am_OK -e empty \
${TEST_SH} -c \
'false; printf "%s" I_am; set -e; true; printf "%s\n" _OK'
# and that it (silently, but with exit status) aborts if cmd fails
atf_check -s not-exit:0 -o match:I_am -o not-match:Broken -e empty \
${TEST_SH} -c \
'false; printf "%s" I_am; set -e; false; printf "%s\n" _Broken'
# same, except -e this time is on from the beginning
atf_check -s not-exit:0 -o match:I_am -o not-match:Broken -e empty \
${TEST_SH} -ec 'printf "%s" I_am; false; printf "%s\n" _Broken'
# More checking of -e in other places, there is lots to deal with.
}
atf_test_case set_f
set_f_head() {
atf_set "descr" "Tests that 'set -f' turns off pathname expansion " \
"and that it behaves as defined by the standard"
}
set_f_body() {
atf_require_prog ls
test_option_on_off f
# Check that the environment to use for the tests is sane ...
# we assume current dir is a new tempory directory & is empty
test -z "$(ls)" || atf_skip "Test execution directory not clean"
# we will assume that atf will clean up this junk directory
# when we are done. But for testing pathname expansion
# we need files
for f in a b c d e f aa ab ac ad ae aaa aab aac aad aba abc bbb ccc
do
echo "$f" > "$f"
done
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -ec \
'X=$(echo b*); Y=$(echo b*); test "${X}" != "a*";
test "${X}" = "${Y}"'
# now test expansion is different when -f is set
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -ec \
'X=$(echo b*); Y=$(set -f; echo b*); test "${X}" != "${Y}"'
}
atf_test_case set_n
set_n_head() {
atf_set "descr" "Tests that 'set -n' supresses command execution " \
"and that it behaves as defined by the standard"
}
set_n_body() {
# pointless to test this, if it turns on, it stays on...
# test_option_on_off n
# so just allow the tests below to verify it can be turned on
# nothing should be executed, hence no output...
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -enc 'echo ABANDON HOPE; echo ALL YE; echo ...'
# this is true even when the "commands" do not exist
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -enc 'ERR; FAIL; ABANDON HOPE'
# but if there is a syntax error, it should be detected (w or w/o -e)
atf_check -s not-exit:0 -o empty -e not-empty \
${TEST_SH} -enc 'echo JUMP; for frogs swim; echo in puddles'
atf_check -s not-exit:0 -o empty -e not-empty \
${TEST_SH} -nc 'echo ABANDON HOPE; echo "ALL YE; echo ...'
atf_check -s not-exit:0 -o empty -e not-empty \
${TEST_SH} -enc 'echo ABANDON HOPE;; echo ALL YE; echo ...'
atf_check -s not-exit:0 -o empty -e not-empty \
${TEST_SH} -nc 'do YOU ABANDON HOPE; for all eternity?'
# now test enabling -n in the middle of a script
# note that once turned on, it cannot be turned off again.
#
# omit more complex cases, as those can send some shells
# into infinite loops, and believe it or not, that might be OK!
atf_check -s exit:0 -o match:first -o not-match:second -e empty \
${TEST_SH} -c 'echo first; set -n; echo second'
atf_check -s exit:0 -o match:first -o not-match:third -e empty \
${TEST_SH} -c 'echo first; set -n; echo second; set +n; echo third'
atf_check -s exit:0 -o inline:'a\nb\n' -e empty \
${TEST_SH} -c 'for x in a b c d
do
case "$x" in
a);; b);; c) set -n;; d);;
esac
printf "%s\n" "$x"
done'
# This last one is a bit more complex to explain, so I will not try
# First, we need to know what signal number is used for SIGUSR1 on
# the local (testing) system (signal number is $(( $XIT - 128 )) )
# this will take slightly over 1 second elapsed time (the sleep 1)
# The "10" for the first sleep just needs to be something big enough
# that the rest of the commands have time to complete, even on
# very slow testing systems. 10 should be enough. Otherwise irrelevant
# The shell will usually blather to stderr about the sleep 10 being
# killed, but it affects nothing, so just allow it to cry.
(sleep 10 & sleep 1; kill -USR1 $!; wait $!)
XIT="$?"
# The exit value should be an integer > 128 and < 256 (often 158)
# If it is not just skip the test
# If we do run the test, it should take (slightly over) either 1 or 2
# seconds to complete, depending upon the shell being tested.
case "${XIT}" in
( 129 | 1[3-9][0-9] | 2[0-4][0-9] | 25[0-5] )
# The script below should exit with the same code - no output
# Or that is the result that seems best explanable.
# "set -n" in uses like this is not exactly well defined...
# This script comes from a member of the austin group
# (they author changes to the posix shell spec - and more.)
# The author is also an (occasional?) NetBSD user.
atf_check -s exit:${XIT} -o empty -e empty ${TEST_SH} -c '
trap "set -n" USR1
{ sleep 1; kill -USR1 $$; sleep 1; } &
false
wait && echo t || echo f
wait
echo foo
'
;;
esac
}
atf_test_case set_u
set_u_head() {
atf_set "descr" "Tests that 'set -u' turns on unset var detection " \
"and that it behaves as defined by the standard"
}
set_u_body() {
test_option_on_off u
# first make sure it is OK to unset an unset variable
atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
'unset _UNSET_VARIABLE_; echo OK'
# even if -u is set
atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -cue \
'unset _UNSET_VARIABLE_; echo OK'
# and that without -u accessing an unset variable is harmless
atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
'unset X; echo ${X}; echo OK'
# and that the unset variable test expansion works properly
atf_check -s exit:0 -o match:OKOK -e empty ${TEST_SH} -ce \
'unset X; printf "%s" ${X-OK}; echo OK'
# Next test that with -u set, the shell aborts on access to unset var
# do not use -e, want to make sure it is -u that causes abort
atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
'unset X; set -u; echo ${X}; echo ERR'
# quoting should make no difference...
atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
'unset X; set -u; echo "${X}"; echo ERR'
# Now a bunch of accesses to unset vars, with -u, in ways that are OK
atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
'unset X; set -u; echo ${X-GOOD}; echo OK'
atf_check -s exit:0 -o match:OK -e empty ${TEST_SH} -ce \
'unset X; set -u; echo ${X-OK}'
atf_check -s exit:0 -o not-match:ERR -o match:OK -e empty \
${TEST_SH} -ce 'unset X; set -u; echo ${X+ERR}; echo OK'
# and some more ways that are not OK
atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
'unset X; set -u; echo ${X#foo}; echo ERR'
atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
'unset X; set -u; echo ${X%%bar}; echo ERR'
# lastly, just while we are checking unset vars, test aborts w/o -u
atf_check -s not-exit:0 -o not-match:ERR -e not-empty ${TEST_SH} -c \
'unset X; echo ${X?}; echo ERR'
atf_check -s not-exit:0 -o not-match:ERR -e match:X_NOT_SET \
${TEST_SH} -c 'unset X; echo ${X?X_NOT_SET}; echo ERR'
}
atf_test_case set_v
set_v_head() {
atf_set "descr" "Tests that 'set -v' turns on input read echoing " \
"and that it behaves as defined by the standard"
}
set_v_body() {
test_option_on_off v
# check that -v does nothing if no later input line is read
atf_check -s exit:0 \
-o match:OKOK -o not-match:echo -o not-match:printf \
-e empty \
${TEST_SH} -ec 'printf "%s" OK; set -v; echo OK; exit 0'
# but that it does when there are multiple lines
cat <<- 'EOF' |
set -v
printf %s OK
echo OK
exit 0
EOF
atf_check -s exit:0 \
-o match:OKOK -o not-match:echo -o not-match:printf \
-e match:printf -e match:OK -e match:echo \
-e not-match:set ${TEST_SH}
# and that it can be disabled again
cat <<- 'EOF' |
set -v
printf %s OK
set +v
echo OK
exit 0
EOF
atf_check -s exit:0 \
-o match:OKOK -o not-match:echo -o not-match:printf \
-e match:printf -e match:OK -e not-match:echo \
${TEST_SH}
# and lastly, that shell keywords do get output when "read"
cat <<- 'EOF' |
set -v
for i in 111 222 333
do
printf %s $i
done
exit 0
EOF
atf_check -s exit:0 \
-o match:111222333 -o not-match:printf \
-o not-match:for -o not-match:do -o not-match:done \
-e match:printf -e match:111 -e not-match:111222 \
-e match:for -e match:do -e match:done \
${TEST_SH}
}
atf_test_case set_x
set_x_head() {
atf_set "descr" "Tests that 'set -x' turns on command exec logging " \
"and that it behaves as defined by the standard"
}
set_x_body() {
test_option_on_off x
# check that cmd output appears after -x is enabled
atf_check -s exit:0 \
-o match:OKOK -o not-match:echo -o not-match:printf \
-e not-match:printf -e match:OK -e match:echo \
${TEST_SH} -ec 'printf "%s" OK; set -x; echo OK; exit 0'
# and that it stops again afer -x is disabled
atf_check -s exit:0 \
-o match:OKOK -o not-match:echo -o not-match:printf \
-e match:printf -e match:OK -e not-match:echo \
${TEST_SH} -ec 'set -x; printf "%s" OK; set +x; echo OK; exit 0'
# also check that PS4 is output correctly
atf_check -s exit:0 \
-o match:OK -o not-match:echo \
-e match:OK -e match:Run:echo \
${TEST_SH} -ec 'PS4=Run:; set -x; echo OK; exit 0'
return 0
# This one seems controversial... I suspect it is NetBSD's sh
# that is wrong to not output "for" "while" "if" ... etc
# and lastly, that shell keywords do not get output when "executed"
atf_check -s exit:0 \
-o match:111222333 -o not-match:printf \
-o not-match:for \
-e match:printf -e match:111 -e not-match:111222 \
-e not-match:for -e not-match:do -e not-match:done \
${TEST_SH} -ec \
'set -x; for i in 111 222 333; do printf "%s" $i; done; echo; exit 0'
}
opt_test_setup()
{
test -n "$1" || { echo >&2 "Internal error"; exit 1; }
cat > "$1" << 'END_OF_FUNCTIONS'
local_opt_check()
{
local -
}
instr()
{
expr "$2" : "\(.*$1\)" >/dev/null
}
save_opts()
{
local -
set -e
set -u
instr e "$-" && instr u "$-" && return 0
echo ERR
}
fiddle_opts()
{
set -e
set -u
instr e "$-" && instr u "$-" && return 0
echo ERR
}
local_test()
{
set +eu
save_opts
instr '[eu]' "$-" || printf %s "OK"
fiddle_opts
instr e "$-" && instr u "$-" && printf %s "OK"
set +eu
}
END_OF_FUNCTIONS
}
atf_test_case restore_local_opts
restore_local_opts_head() {
atf_set "descr" "Tests that 'local -' saves and restores options. " \
"Note that "local" is a local shell addition"
}
restore_local_opts_body() {
atf_require_prog cat
atf_require_prog expr
FN="test-funcs.$$"
opt_test_setup "${FN}" || atf_skip "Cannot setup test environment"
${TEST_SH} -ec ". './${FN}'; local_opt_check" 2>/dev/null ||
atf_skip "sh extension 'local -' not supported by ${TEST_SH}"
atf_check -s exit:0 -o match:OKOK -o not-match:ERR -e empty \
${TEST_SH} -ec ". './${FN}'; local_test"
}
atf_test_case vi_emacs_VE_toggle
vi_emacs_VE_toggle_head() {
atf_set "descr" "Tests enabling vi disables emacs (and v.v - but why?)"\
" Note that -V and -E are local shell additions"
}
vi_emacs_VE_toggle_body() {
test_optional_on_off V E ||
atf_skip "One or both V & E opts unsupported by ${TEST_SH}"
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '
q() {
eval "case \"$-\" in
(*${2}*) return 1;;
(*${1}*) return 0;;
esac"
return 1
}
x() {
echo >&2 "Option set or toggle failure:" \
" on=$1 off=$2 set=$-"
exit 1
}
set -V; q V E || x V E
set -E; q E V || x E V
set -V; q V E || x V E
set +EV; q "" "[VE]" || x "" VE
exit 0
'
}
atf_test_case xx_bogus
xx_bogus_head() {
atf_set "descr" "Tests that attempting to set a nonsense option fails."
}
xx_bogus_body() {
# Biggest problem here is picking a "nonsense option" that is
# not implemented by any shell, anywhere. Hopefully this will do.
# 'set' is a special builtin, so a conforming shell should exit
# on an arg error, and the ERR should not be printed.
atf_check -s not-exit:0 -o empty -e not-empty \
${TEST_SH} -c 'set -% ; echo ERR'
}
atf_test_case Option_switching
Option_switching_head() {
atf_set "descr" "options can be enabled and disabled"
}
Option_switching_body() {
# Cannot test -m, setting it causes test shell to fail...
# (test shell gets SIGKILL!) Wonder why ... something related to atf
# That is, it works if just run as "sh -c 'echo $-; set -m; echo $-'"
# Don't bother testing toggling -n, once on, it stays on...
# (and because the test fn refuses to allow us to try)
# Cannot test -o or -c here, or the extension -s
# they can only be used, not switched
# these are the posix options, that all shells should implement
test_option_on_off a b C e f h u v x # m
# and these are extensions that might not exist (non-fatal to test)
# -i and -s (and -c) are posix options, but are not required to
# be accessable via the "set" command, just the command line.
# We allow for -i to work with set, as that makes some sense,
# -c and -s do not.
test_optional_on_off E i I p q V || true
# Also test (some) option combinations ...
# only testing posix options here, because it is easier...
test_option_on_off aeu vx Ca aCefux
}
atf_init_test_cases() {
# tests are run in order sort of names produces, so choose names wisely
# this one tests turning on/off all the mandatory. and extra flags
atf_add_test_case Option_switching
# and this tests the NetBSD "local -" functionality in functions.
atf_add_test_case restore_local_opts
# no tests for -m (no idea how to do that one)
# -I (no easy way to generate the EOF it ignores)
# -i (not sure how to test that one at the minute)
# -p (because we aren't going to run tests setuid)
# -V/-E (too much effort, and a real test would be huge)
# -c (because almost all the other tests test it anyway)
# -q (because, for now, I am lazy)
# -s (coming soon, hopefully)
# -o (really +o: again, hopefully soon)
# -o longname (again, just laziness, don't wait...)
# -h/-b (because NetBSD doesn't implement them)
atf_add_test_case set_a
atf_add_test_case set_C
atf_add_test_case set_e
atf_add_test_case set_f
atf_add_test_case set_n
atf_add_test_case set_u
atf_add_test_case set_v
atf_add_test_case set_x
atf_add_test_case vi_emacs_VE_toggle
atf_add_test_case xx_bogus
}

903
bin/sh/t_redir.sh Executable file
View file

@ -0,0 +1,903 @@
# $NetBSD: t_redir.sh,v 1.9 2016/05/14 00:33:02 kre Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
# Any failures in this first test means it is not worth bothering looking
# for causes of failures in any other tests, make this one work first.
# Problems with this test usually mean inadequate ATF_SHELL used for testing.
# (though if all pass but the last, it might be a TEST_SH problem.)
atf_test_case basic_test_method_test
basic_test_method_test_head()
{
atf_set "descr" "Tests that test method works as expected"
}
basic_test_method_test_body()
{
cat <<- 'DONE' |
DONE
atf_check -s exit:0 -o empty -e empty ${TEST_SH}
cat <<- 'DONE' |
DONE
atf_check -s exit:0 -o match:0 -e empty ${TEST_SH} -c 'wc -l'
cat <<- 'DONE' |
echo hello
DONE
atf_check -s exit:0 -o match:hello -e empty ${TEST_SH}
cat <<- 'DONE' |
echo hello
DONE
atf_check -s exit:0 -o match:1 -e empty ${TEST_SH} -c 'wc -l'
cat <<- 'DONE' |
echo hello\
world
DONE
atf_check -s exit:0 -o match:helloworld -e empty ${TEST_SH}
cat <<- 'DONE' |
echo hello\
world
DONE
atf_check -s exit:0 -o match:2 -e empty ${TEST_SH} -c 'wc -l'
printf '%s\n%s\n%s\n' Line1 Line2 Line3 > File
atf_check -s exit:0 -o inline:'Line1\nLine2\nLine3\n' -e empty \
${TEST_SH} -c 'cat File'
cat <<- 'DONE' |
set -- X "" '' Y
echo ARGS="${#}"
echo '' -$1- -$2- -$3- -$4-
cat <<EOF
X=$1
EOF
cat <<\EOF
Y=$4
EOF
DONE
atf_check -s exit:0 -o match:ARGS=4 -o match:'-X- -- -- -Y-' \
-o match:X=X -o match:'Y=\$4' -e empty ${TEST_SH}
}
atf_test_case do_input_redirections
do_input_redirections_head()
{
atf_set "descr" "Tests that simple input redirection works"
}
do_input_redirections_body()
{
printf '%s\n%s\n%s\nEND\n' 'First Line' 'Second Line' 'Line 3' >File
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c 'cat < File'
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c 'cat <File'
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c 'cat< File'
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c 'cat < "File"'
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c '< File cat'
ln File wc
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH} -c '< wc cat'
mv wc cat
atf_check -s exit:0 -e empty -o match:4 \
${TEST_SH} -c '< cat wc'
cat <<- 'EOF' |
for l in 1 2 3; do
read line < File
echo "$line"
done
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nFirst Line\nFirst Line\n' \
${TEST_SH}
cat <<- 'EOF' |
for l in 1 2 3; do
read line
echo "$line"
done <File
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\n' \
${TEST_SH}
cat <<- 'EOF' |
for l in 1 2 3; do
read line < File
echo "$line"
done <File
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nFirst Line\nFirst Line\n' \
${TEST_SH}
cat <<- 'EOF' |
line=
while [ "$line" != END ]; do
read line || exit 1
echo "$line"
done <File
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH}
cat <<- 'EOF' |
while :; do
read line || exit 0
echo "$line"
done <File
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\n' \
${TEST_SH}
cat <<- 'EOF' |
l=''
while read line < File
do
echo "$line"
l="${l}x"
[ ${#l} -ge 3 ] && break
done
echo DONE
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nFirst Line\nFirst Line\nDONE\n' \
${TEST_SH}
cat <<- 'EOF' |
while read line
do
echo "$line"
done <File
echo DONE
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nEND\nDONE\n' \
${TEST_SH}
cat <<- 'EOF' |
l=''
while read line
do
echo "$line"
l="${l}x"
[ ${#l} -ge 3 ] && break
done <File
echo DONE
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line\nSecond Line\nLine 3\nDONE\n' ${TEST_SH}
cat <<- 'EOF' |
l=''
while read line1 <File
do
read line2
echo "$line1":"$line2"
l="${l}x"
[ ${#l} -ge 2 ] && break
done <File
echo DONE
EOF
atf_check -s exit:0 -e empty \
-o inline:'First Line:First Line\nFirst Line:Second Line\nDONE\n' \
${TEST_SH}
}
atf_test_case do_output_redirections
do_output_redirections_head()
{
atf_set "descr" "Test Output redirections"
}
do_output_redirections_body()
{
nl='
'
T=0
i() { T=$(expr "$T" + 1); }
rm -f Output 2>/dev/null || :
test -f Output && atf_fail "Unable to remove Output file"
#1
i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '> Output'
test -f Output || atf_fail "#$T: Did not make Output file"
#2
rm -f Output 2>/dev/null || :
i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>> Output'
test -f Output || atf_fail "#$T: Did not make Output file"
#3
rm -f Output 2>/dev/null || :
i; atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '>| Output'
test -f Output || atf_fail "#$T: Did not make Output file"
#4
rm -f Output 2>/dev/null || :
i
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello >Output'
test -s Output || atf_fail "#$T: Did not make non-empty Output file"
test "$(cat Output)" = "Hello" ||
atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
#5
i
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Hello>!Output'
test -s Output || atf_fail "#$T: Did not make non-empty Output file"
test "$(cat Output)" = "Hello" ||
atf_fail "#$T: Incorrect Output: Should be 'Hello' is '$(cat Output)'"
#6
i
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c 'echo Bye >>Output'
test -s Output || atf_fail "#$T: Removed Output file"
test "$(cat Output)" = "Hello${nl}Bye" || atf_fail \
"#$T: Incorrect Output: Should be 'Hello\\nBye' is '$(cat Output)'"
#7
i; atf_check -s exit:0 -o inline:'line 1\nline 2\n' -e empty \
${TEST_SH} -c \
'echo line 1 > Output; echo line 2 >> Output; cat Output'
test "$(cat Output)" = "line 1${nl}line 2" || atf_fail \
"#$T: Incorrect Output: Should be 'line 1\\nline 2' is '$(cat Output)'"
#8
i; atf_check -s exit:0 -o inline:'line 2\n' -e empty \
${TEST_SH} -c 'echo line 1 > Output; echo line 2'
test "$(cat Output)" = "line 1" || atf_fail \
"#$T: Incorrect Output: Should be 'line 1' is '$(cat Output)'"
#9
i; atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c '(echo line 1; echo line 2 > Out2) > Out1'
test "$(cat Out1)" = "line 1" || atf_fail \
"#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
test "$(cat Out2)" = "line 2" || atf_fail \
"#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
#10
i; atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c '{ echo line 1; echo line 2 > Out2;} > Out1'
test "$(cat Out1)" = "line 1" || atf_fail \
"#$T: Incorrect Out1: Should be 'line 1' is '$(cat Out1)'"
test "$(cat Out2)" = "line 2" || atf_fail \
"#$T: Incorrect Out2: Should be 'line 2' is '$(cat Out2)'"
#11
i; rm -f Out1 Out2 2>/dev/null || :
cat <<- 'EOF' |
for arg in 'line 1' 'line 2' 'line 3'
do
echo "$arg"
echo "$arg" > Out1
done > Out2
EOF
atf_check -s exit:0 -o empty -e empty ${TEST_SH}
test "$(cat Out1)" = "line 3" || atf_fail \
"#$T: Incorrect Out1: Should be 'line 3' is '$(cat Out1)'"
test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
"#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
#12
i; rm -f Out1 Out2 2>/dev/null || :
cat <<- 'EOF' |
for arg in 'line 1' 'line 2' 'line 3'
do
echo "$arg"
echo "$arg" >> Out1
done > Out2
EOF
atf_check -s exit:0 -o empty -e empty ${TEST_SH}
test "$(cat Out1)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
"#$T: Incorrect Out1: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out1)'"
test "$(cat Out2)" = "line 1${nl}line 2${nl}line 3" || atf_fail \
"#$T: Incorrect Out2: Should be 'line 1\\nline 2\\nline 3' is '$(cat Out2)'"
}
atf_test_case fd_redirections
fd_redirections_head()
{
atf_set "descr" "Tests redirections to/from specific descriptors"
}
fd_redirections_body()
{
atf_require_prog /bin/echo
cat <<- 'DONE' > helper.sh
f() {
/bin/echo nothing "$1" >& "$1"
}
for n
do
eval "f $n $n"'> file-$n'
done
DONE
cat <<- 'DONE' > reread.sh
f() {
(read -r var; echo "${var}") <&"$1"
}
for n
do
x=$( eval "f $n $n"'< file-$n' )
test "${x}" = "nothing $n" || echo "$n"
done
DONE
validate()
{
for n
do
test -e "file-$n" || atf_fail "file-$n not created"
C=$(cat file-"$n")
test "$C" = "nothing $n" ||
atf_fail "file-$n contains '$C' not 'nothing $n'"
done
}
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} helper.sh 1 2 3 4 5 6 7 8 9
validate 1 2 3 4 5 6 7 8 9
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} reread.sh 3 4 5 6 7 8 9
L=$(ulimit -n)
if [ "$L" -ge 30 ]
then
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} helper.sh 10 15 19 20 25 29
validate 10 15 19 20 25 29
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} reread.sh 10 15 19 20 25 29
fi
if [ "$L" -ge 100 ]
then
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} helper.sh 32 33 49 50 51 63 64 65 77 88 99
validate 32 33 49 50 51 63 64 65 77 88 99
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} reread.sh 32 33 49 50 51 63 64 65 77 88 99
fi
if [ "$L" -ge 500 ]
then
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} helper.sh 100 101 199 200 222 333 444 499
validate 100 101 199 200 222 333 444 499
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} reread.sh 100 101 199 200 222 333 444 499
fi
if [ "$L" -gt 1005 ]
then
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
validate 1000 1001 1002 1003 1004 1005
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} reread.sh 1000 1001 1002 1003 1004 1005
fi
}
atf_test_case local_redirections
local_redirections_head()
{
atf_set "descr" \
"Tests that exec can reassign file descriptors in the shell itself"
}
local_redirections_body()
{
cat <<- 'DONE' > helper.sh
for f
do
eval "exec $f"'> file-$f'
done
for f
do
printf '%s\n' "Hello $f" >&"$f"
done
for f
do
eval "exec $f"'>&-'
done
for f
do
eval "exec $f"'< file-$f'
done
for f
do
exec <& "$f"
read -r var || echo >&2 "No data in file-$f"
read -r x && echo >&2 "Too much data in file-${f}: $x"
test "${var}" = "Hello $f" ||
echo >&2 "file-$f contains '${var}' not 'Hello $f'"
done
DONE
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} helper.sh 3 4 5 6 7 8 9
L=$(ulimit -n)
if [ "$L" -ge 30 ]
then
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} helper.sh 10 11 13 15 16 19 20 28 29
fi
if [ "$L" -ge 100 ]
then
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} helper.sh 30 31 32 63 64 65 77 88 99
fi
if [ "$L" -ge 500 ]
then
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} helper.sh 100 101 111 199 200 201 222 333 499
fi
if [ "$L" -ge 1005 ]
then
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} helper.sh 1000 1001 1002 1003 1004 1005
fi
}
atf_test_case named_fd_redirections
named_fd_redirections_head()
{
atf_set "descr" "Tests redirections to /dev/stdout (etc)"
}
named_fd_redirections_body()
{
if test -c /dev/stdout
then
atf_check -s exit:0 -o inline:'OK\n' -e empty \
${TEST_SH} -c 'echo OK >/dev/stdout'
atf_check -s exit:0 -o inline:'OK\n' -e empty \
${TEST_SH} -c '/bin/echo OK >/dev/stdout'
fi
if test -c /dev/stdin
then
atf_require_prog cat
echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
${TEST_SH} -c 'read var </dev/stdin; echo $var'
echo GOOD | atf_check -s exit:0 -o inline:'GOOD\n' -e empty \
${TEST_SH} -c 'cat </dev/stdin'
fi
if test -c /dev/stderr
then
atf_check -s exit:0 -e inline:'OK\n' -o empty \
${TEST_SH} -c 'echo OK 2>/dev/stderr >&2'
atf_check -s exit:0 -e inline:'OK\n' -o empty \
${TEST_SH} -c '/bin/echo OK 2>/dev/stderr >&2'
fi
if test -c /dev/fd/8 && test -c /dev/fd/9
then
atf_check -s exit:0 -o inline:'EIGHT\n' -e empty \
${TEST_SH} -c 'printf "%s\n" EIGHT 8>&1 >/dev/fd/8 |
cat 9<&0 </dev/fd/9'
fi
return 0
}
atf_test_case redir_in_case
redir_in_case_head()
{
atf_set "descr" "Tests that sh(1) allows just redirections " \
"in case statements. (PR bin/48631)"
}
redir_in_case_body()
{
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c 'case x in (whatever) >foo;; esac'
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c 'case x in (whatever) >foo 2>&1;; esac'
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c 'case x in (whatever) >foo 2>&1 </dev/null;; esac'
atf_check -s exit:0 -o empty -e empty \
${TEST_SH} -c 'case x in (whatever) >${somewhere};; esac'
}
atf_test_case incorrect_redirections
incorrect_redirections_head()
{
atf_set "descr" "Tests that sh(1) correctly ignores non-redirections"
}
incorrect_redirections_body() {
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo>'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'read foo<'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c 'echo foo<>'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x > '"$nl"
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'read x < '"$nl"
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x <> '"$nl"
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x >< anything'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x >>< anything'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x >|< anything'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'echo x > ; read x < /dev/null || echo bad'
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
'read x < & echo y > /dev/null; wait && echo bad'
rm -f Output 2>/dev/null || :
atf_check -s exit:0 -e empty -o inline:'A Line > Output\n' \
${TEST_SH} -c 'echo A Line \> Output'
test -f Output && atf_file "File 'Output' appeared and should not have"
rm -f Output 2>/dev/null || :
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} -c 'echo A Line \>> Output'
test -f Output || atf_file "File 'Output' not created when it should"
test "$(cat Output)" = 'A Line >' || atf_fail \
"Output file contains '$(cat Output)' instead of '"'A Line >'\'
rm -f Output \> 2>/dev/null || :
atf_check -s exit:0 -e empty -o empty \
${TEST_SH} -c 'echo A Line >\> Output'
test -f Output && atf_file "File 'Output' appeared and should not have"
test -f '>' || atf_file "File '>' not created when it should"
test "$(cat '>')" = 'A Line Output' || atf_fail \
"Output file ('>') contains '$(cat '>')' instead of 'A Line Output'"
}
# Many more tests in t_here, so here we have just rudimentary checks
atf_test_case redir_here_doc
redir_here_doc_head()
{
atf_set "descr" "Tests that sh(1) correctly processes 'here' doc " \
"input redirections"
}
redir_here_doc_body()
{
# nb: the printf is not executed, it is data
cat <<- 'DONE' |
cat <<EOF
printf '%s\n' 'hello\n'
EOF
DONE
atf_check -s exit:0 -o match:printf -o match:'hello\\n' \
-e empty ${TEST_SH}
}
atf_test_case subshell_redirections
subshell_redirections_head()
{
atf_set "descr" "Tests redirection interactions between shell and " \
"its sub-shell(s)"
}
subshell_redirections_body()
{
atf_require_prog cat
LIM=$(ulimit -n)
cat <<- 'DONE' |
exec 6>output-file
( printf "hello\n" >&6 )
exec 8<output-file
( read hello <&8 ; test hello = "$hello" || echo >&2 Hello )
( printf "bye-bye\n" >&6 )
( exec 8<&- )
read bye <&8 || echo >&2 "Closed?"
echo Bye="$bye"
DONE
atf_check -s exit:0 -o match:Bye=bye-bye -e empty \
${TEST_SH}
cat <<- 'DONE' |
for arg in one-4 two-24 three-14
do
fd=${arg#*-}
file=${arg%-*}
eval "exec ${fd}>${file}"
done
for arg in one-5 two-7 three-19
do
fd=${arg#*-}
file=${arg%-*}
eval "exec ${fd}<${file}"
done
(
echo line-1 >&4
echo line-2 >&24
echo line-3 >&14
echo go
) | (
read go
read x <&5
read y <&7
read z <&19
printf "%s\n" "${x}" "${y}" "${z}"
)
DONE
atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
-e empty ${TEST_SH}
cat <<- 'DONE' |
for arg in one-4-5 two-6-7 three-8-9 four-11-10 five-3-12
do
ofd=${arg##*-}
file=${arg%-*}
ifd=${file#*-}
file=${file%-*}
eval "exec ${ofd}>${file}"
eval "exec ${ifd}<${file}"
done
( ( ( echo line-1 >& 13 ) 13>&12 ) 12>&5 ) >stdout 2>errout
( ( ( echo line-2 >& 4) 13>&12 ) 4>&7 ) >>stdout 2>>errout
( ( ( echo line-3 >& 6) 8>&1 6>&11 >&12) 11>&9 >&7 ) >>stdout
( ( ( cat <&13 >&12 ) 13<&8 12>&10 ) 10>&1 8<&6 ) 6<&4
( ( ( cat <&4 ) <&4 6<&8 8<&11 )
<&4 4<&6 6<&8 8<&11 ) <&4 4<&6 6<&8 8<&11 11<&3
( ( ( cat <&7 >&1 ) 7<&6 >&10 ) 10>&2 6<&8 ) 2>&1
DONE
atf_check -s exit:0 -o inline:'line-1\nline-2\nline-3\n' \
-e empty ${TEST_SH}
}
atf_test_case ulimit_redirection_interaction
ulimit_redirection_interaction_head()
{
atf_set "descr" "Tests interactions between redirect and ulimit -n "
}
ulimit_redirection_interaction_body()
{
atf_require_prog ls
cat <<- 'DONE' > helper.sh
oLIM=$(ulimit -n)
HRD=$(ulimit -H -n)
test "${oLIM}" -lt "${HRD}" && ulimit -n "${HRD}"
LIM=$(ulimit -n)
FDs=
LFD=-1
while [ ${LIM} -gt 16 ]
do
FD=$(( ${LIM} - 1 ))
if [ "${FD}" -eq "${LFD}" ]; then
echo >&2 "Infinite loop... (busted $(( )) ??)"
exit 1
fi
LFD="${FD}"
eval "exec ${FD}"'> /dev/null'
FDs="${FD}${FDs:+ }${FDs}"
(
FD=$(( ${LIM} + 1 ))
eval "exec ${FD}"'> /dev/null'
echo "Reached unreachable command"
) 2>/dev/null && echo >&2 "Opened beyond limit!"
(eval 'ls 2>&1 3>&1 4>&1 5>&1 '"${FD}"'>&1') >&"${FD}"
LIM=$(( ${LIM} / 2 ))
ulimit -S -n "${LIM}"
done
# Even though ulimit has been reduced, open fds should work
for FD in ${FDs}
do
echo ${FD} in ${FDs} >&"${FD}" || exit 1
done
ulimit -S -n "${oLIM}"
# maybe more later...
DONE
atf_check -s exit:0 -o empty -e empty ${TEST_SH} helper.sh
}
atf_test_case validate_fn_redirects
validate_fn_redirects_head()
{
# These test cases inspired by PR bin/48875 and the sh
# changes that were required to fix it.
atf_set "descr" "Tests various redirections applied to functions " \
"See PR bin/48875"
}
validate_fn_redirects_body()
{
cat <<- 'DONE' > f-def
f() {
printf '%s\n' In-Func
}
DONE
atf_check -s exit:0 -o inline:'In-Func\nsuccess1\n' -e empty \
${TEST_SH} -c ". ./f-def; f ; printf '%s\n' success1"
atf_check -s exit:0 -o inline:'success2\n' -e empty \
${TEST_SH} -c ". ./f-def; f >/dev/null; printf '%s\n' success2"
atf_check -s exit:0 -o inline:'success3\n' -e empty \
${TEST_SH} -c ". ./f-def; f >&- ; printf '%s\n' success3"
atf_check -s exit:0 -o inline:'In-Func\nsuccess4\n' -e empty \
${TEST_SH} -c ". ./f-def; f & wait; printf '%s\n' success4"
atf_check -s exit:0 -o inline:'success5\n' -e empty \
${TEST_SH} -c ". ./f-def; f >&- & wait; printf '%s\n' success5"
atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess6\n' -e empty \
${TEST_SH} -c ". ./f-def; f;f; printf '%s\n' success6"
atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess7\n' -e empty \
${TEST_SH} -c ". ./f-def; { f;f;}; printf '%s\n' success7"
atf_check -s exit:0 -o inline:'In-Func\nIn-Func\nsuccess8\n' -e empty \
${TEST_SH} -c ". ./f-def; { f;f;}& wait; printf '%s\n' success8"
atf_check -s exit:0 -o inline:'In-Func\nsuccess9\n' -e empty \
${TEST_SH} -c \
". ./f-def; { f>/dev/null;f;}& wait; printf '%s\n' success9"
atf_check -s exit:0 -o inline:'In-Func\nsuccess10\n' -e empty \
${TEST_SH} -c \
". ./f-def; { f;f>/dev/null;}& wait; printf '%s\n' success10"
# This one tests the issue etcupdate had with the original 48875 fix
atf_check -s exit:0 -o inline:'Func a\nFunc b\nFunc c\n' -e empty \
${TEST_SH} -c '
f() {
echo Func "$1"
}
exec 3<&0 4>&1
( echo x-a; echo y-b; echo z-c ) |
while read A
do
B=${A#?-}
f "$B" <&3 >&4
done >&2'
# And this tests a similar condition with that same fix
cat <<- 'DONE' >Script
f() {
printf '%s' " hello $1"
}
exec 3>&1
echo $( for i in a b c
do printf '%s' @$i; f $i >&3; done >foo
)
printf '%s\n' foo=$(cat foo)
DONE
atf_check -s exit:0 -e empty \
-o inline:' hello a hello b hello c\nfoo=@a@b@c\n' \
${TEST_SH} Script
# Tests with sh reading stdin, which is not quite the same internal
# mechanism.
echo ". ./f-def || echo >&2 FAIL
f
printf '%s\n' stdin1
"| atf_check -s exit:0 -o inline:'In-Func\nstdin1\n' -e empty ${TEST_SH}
echo '
. ./f-def || echo >&2 FAIL
f >&-
printf "%s\n" stdin2
' | atf_check -s exit:0 -o inline:'stdin2\n' -e empty ${TEST_SH}
cat <<- 'DONE' > fgh.def
f() {
echo -n f >&3
sleep 4
echo -n F >&3
}
g() {
echo -n g >&3
sleep 2
echo -n G >&3
}
h() {
echo -n h >&3
}
DONE
atf_check -s exit:0 -o inline:'fFgGh' -e empty \
${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
exec 3>&1
f; g; h'
atf_check -s exit:0 -o inline:'fghGF' -e empty \
${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
exec 3>&1
f & sleep 1; g & sleep 1; h; wait'
atf_check -s exit:0 -o inline:'fFgGhX Y\n' -e empty \
${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
exec 3>&1
echo X $( f ; g ; h ) Y'
# This one is the real test for PR bin/48875. If the
# cmdsub does not complete before f g (and h) exit,
# then the 'F' & 'G' will precede 'X Y' in the output.
# If the cmdsub finishes while f & g are still running,
# then the X Y will appear before the F and G.
# The trailing "sleep 3" is just so we catch all the
# output (otherwise atf_check will be finished while
# f & g are still sleeping).
atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty \
${TEST_SH} -c '. ./fgh.def || echo >&2 FAIL
exec 3>&1
echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
sleep 3
exec 4>&1 || echo FD_FAIL
'
# Do the test again to verify it also all works reading stdin
# (which is a slightly different path through the shell)
echo '
. ./fgh.def || echo >&2 FAIL
exec 3>&1
echo X $( f >&- & sleep 1; g >&- & sleep 1 ; h ) Y
sleep 3
exec 4>&1 || echo FD_FAIL
' | atf_check -s exit:0 -o inline:'fghX Y\nGF' -e empty ${TEST_SH}
}
atf_init_test_cases() {
atf_add_test_case basic_test_method_test
atf_add_test_case do_input_redirections
atf_add_test_case do_output_redirections
atf_add_test_case fd_redirections
atf_add_test_case local_redirections
atf_add_test_case incorrect_redirections
atf_add_test_case named_fd_redirections
atf_add_test_case redir_here_doc
atf_add_test_case redir_in_case
atf_add_test_case subshell_redirections
atf_add_test_case ulimit_redirection_interaction
atf_add_test_case validate_fn_redirects
}

178
bin/sh/t_redircloexec.sh Executable file
View file

@ -0,0 +1,178 @@
# $NetBSD: t_redircloexec.sh,v 1.3 2016/05/15 15:44:43 kre Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by Christos Zoulas.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
mkhelper() {
name=$1
fd=$2
shift 2
echo "$@" > ./"${name}1"
echo "echo ${name}2" ">&${fd}" > ./"${name}2"
}
runhelper() {
${TEST_SH} "./${1}1"
}
cleanhelper() {
# not really needed, atf cleans up...
rm -f ./"${1}1" ./"${1}2" out
}
atf_test_case exec_redir_closed
exec_redir_closed_head() {
atf_set "descr" "Tests that redirections created by exec are closed on exec"
}
exec_redir_closed_body() {
mkhelper exec 6 \
"exec 6> out; echo exec1 >&6; ${TEST_SH} exec2; exec 6>&-"
atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} ./exec1
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -e ./exec1
mkhelper exec 9 \
"exec 9> out; echo exec1 >&9; ${TEST_SH} exec2"
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} ./exec1
mkhelper exec 8 \
"exec 8> out; printf OK; echo exec1 >&8;" \
"printf OK; ${TEST_SH} exec2; printf ERR"
atf_check -s not-exit:0 -o match:OKOK -o not-match:ERR -e not-empty \
${TEST_SH} -e ./exec1
mkhelper exec 7 \
"exec 7> out; printf OK; echo exec1 >&7;" \
"printf OK; ${TEST_SH} exec2 || printf ERR"
atf_check -s exit:0 -o match:OKOKERR -e not-empty \
${TEST_SH} ./exec1
cleanhelper exec
}
atf_test_case exec_redir_open
exec_redir_open_head() {
atf_set "descr" "Tests that redirections created by exec can remain open"
}
exec_redir_open_body() {
mkhelper exec 6 \
"exec 6> out 6>&6; echo exec1 >&6; ${TEST_SH} exec2; exec 6>&-"
atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -e ./exec1
mkhelper exec 9 \
"exec 9> out ; echo exec1 >&9; ${TEST_SH} exec2 9>&9"
atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
mkhelper exec 8 \
"exec 8> out; printf OK; exec 8>&8; echo exec1 >&8;" \
"printf OK; ${TEST_SH} exec2; printf OK"
atf_check -s exit:0 -o match:OKOKOK -e empty \
${TEST_SH} -e ./exec1
mkhelper exec 7 \
"exec 7> out; printf OK; echo exec1 >&7;" \
"printf OK; ${TEST_SH} 7>&7 exec2; printf OK"
atf_check -s exit:0 -o match:OKOKOK -e empty \
${TEST_SH} -e ./exec1
cleanhelper exec
}
atf_test_case loop_redir_open
loop_redir_open_head() {
atf_set "descr" "Tests that redirections in loops don't close on exec"
}
loop_redir_open_body() {
mkhelper for 3 "for x in x; do ${TEST_SH} ./for2; done 3>out"
atf_check -s exit:0 \
-o empty \
-e empty \
${TEST_SH} ./for1
cleanhelper for
}
atf_test_case compound_redir_open
compound_redir_open_head() {
atf_set "descr" "Tests that redirections in compound statements don't close on exec"
}
compound_redir_open_body() {
mkhelper comp 3 "{ ${TEST_SH} ./comp2; } 3>out"
atf_check -s exit:0 \
-o empty \
-e empty \
${TEST_SH} ./comp1
cleanhelper comp
}
atf_test_case simple_redir_open
simple_redir_open_head() {
atf_set "descr" "Tests that redirections in simple commands don't close on exec"
}
simple_redir_open_body() {
mkhelper simp 4 "${TEST_SH} ./simp2 4>out"
atf_check -s exit:0 \
-o empty \
-e empty \
${TEST_SH} ./simp1
cleanhelper simp
}
atf_test_case subshell_redir_open
subshell_redir_open_head() {
atf_set "descr" "Tests that redirections on subshells don't close on exec"
}
subshell_redir_open_body() {
mkhelper comp 5 "( ${TEST_SH} ./comp2; ${TEST_SH} ./comp2 ) 5>out"
atf_check -s exit:0 \
-o empty \
-e empty \
${TEST_SH} ./comp1
cleanhelper comp
}
atf_init_test_cases() {
atf_add_test_case exec_redir_closed
atf_add_test_case exec_redir_open
atf_add_test_case loop_redir_open
atf_add_test_case compound_redir_open
atf_add_test_case simple_redir_open
atf_add_test_case subshell_redir_open
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_set_e.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $
# $NetBSD: t_set_e.sh,v 1.4 2016/03/31 16:22:27 christos Exp $
#
# Copyright (c) 2007 The NetBSD Foundation, Inc.
# All rights reserved.
@ -30,7 +30,7 @@
# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
# the implementation of "sh" to test
: ${TEST_SH:="sh"}
: ${TEST_SH:="/bin/sh"}
failwith()
{
@ -63,7 +63,7 @@ dcheck()
# is thus important to test. (PR bin/29861)
echeck()
{
check1 'eval '"'($1)'" "$2" "eval '($1)'"
check1 'eval '"'( $1 )'" "$2" "eval '($1)'"
}
atf_test_case all
@ -81,8 +81,8 @@ all_body() {
# first, check basic functioning.
# The ERR shouldn't print; the result of the () should be 1.
# Henceforth we'll assume that we don't need to check $?.
dcheck '(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
echeck '(set -e; false; echo ERR$?); echo -n OK$?' 'OK1'
dcheck '(set -e; false; echo ERR$?); echo OK$?' 'OK1'
echeck '(set -e; false; echo ERR$?); echo OK$?' 'OK1'
# these cases should be equivalent to the preceding.
dcheck '(set -e; /nonexistent; echo ERR); echo OK' 'OK'
@ -205,6 +205,9 @@ all_body() {
# According to dsl@ in PR bin/32282, () is not defined as a
# subshell, only as a grouping operator [and a scope, I guess]
# (This is incorrect. () is definitely a sub-shell)
# so the nested false ought to cause the whole shell to exit,
# not just the subshell. dholland@ would like to see C&V,
# because that seems like a bad idea. (Among other things, it
@ -215,8 +218,10 @@ all_body() {
#
# XXX: the second set has been disabled in the name of making
# all tests "pass".
#
# As they should be, they are utter nonsense.
# 1. error if the whole shell exits (current behavior)
# 1. error if the whole shell exits (current correct behavior)
dcheck 'echo OK; (set -e; false); echo OK' 'OK OK'
echeck 'echo OK; (set -e; false); echo OK' 'OK OK'
# 2. error if the whole shell does not exit (dsl's suggested behavior)
@ -232,29 +237,32 @@ all_body() {
# backquote expansion (PR bin/17514)
# correct
# (in-)correct
#dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
#dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
#dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
#dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
# wrong current behavior
# Not-wrong current behavior
# the exit status of ommand substitution is ignored in most cases
# None of these should be causing the shell to exit.
dcheck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
dcheck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
dcheck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
dcheck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK'
# This is testing one case (the case?) where the exit status is used
dcheck '(set -e; x=`false`; echo ERR); echo OK' 'OK'
dcheck '(set -e; x=$(false); echo ERR); echo OK' 'OK'
dcheck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK'
dcheck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK'
# correct
# correct (really just commented out incorrect nonsense)
#echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'OK'
#echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'OK'
#echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'OK'
#echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'OK'
# wrong current behavior
# not-wrong current behavior (as above)
echeck '(set -e; echo ERR `false`; echo ERR); echo OK' 'ERR ERR OK'
echeck '(set -e; echo ERR $(false); echo ERR); echo OK' 'ERR ERR OK'
echeck '(set -e; echo ERR `exit 3`; echo ERR); echo OK' 'ERR ERR OK'
@ -267,11 +275,19 @@ all_body() {
# shift (PR bin/37493)
# correct
# Actually, both ways are correct, both are permitted
#dcheck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
#echeck '(set -e; shift || true; echo OK); echo OK' 'OK OK'
# wrong current behavior
dcheck '(set -e; shift || true; echo OK); echo OK' 'OK'
echeck '(set -e; shift || true; echo OK); echo OK' 'OK'
# (not-) wrong current behavior
#dcheck '(set -e; shift || true; echo OK); echo OK' 'OK'
#echeck '(set -e; shift || true; echo OK); echo OK' 'OK'
# what is wrong is this test assuming one behaviour or the other
# (and incidentally this has nothing whatever to do with "-e",
# the test should really be moved elsewhere...)
# But for now, leave it here, and correct it:
dcheck '(set -e; shift && echo OK); echo OK' 'OK'
echeck '(set -e; shift && echo OK); echo OK' 'OK'
# Done.

181
bin/sh/t_shift.sh Executable file
View file

@ -0,0 +1,181 @@
# $NetBSD: t_shift.sh,v 1.2 2016/05/17 09:05:14 kre Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
atf_test_case basic_shift_test
basic_shift_test_head() {
atf_set "descr" "Test correct operation of valid shifts"
}
basic_shift_test_body() {
for a in \
"one-arg::0:one-arg" \
"one-arg:1:0:one-arg" \
"one-arg:0:1 one-arg" \
"a b c::2 b c:a" \
"a b c:1:2 b c:a" \
"a b c:2:1 c:a:b" \
"a b c:3:0:a:b:c" \
"a b c:0:3 a b c" \
"a b c d e f g h i j k l m n o p:1:15 b c d e f g h i j k l m n o p"\
"a b c d e f g h i j k l m n o p:9:7 j k l m n o p:a:b:c:g:h:i" \
"a b c d e f g h i j k l m n o p:13:3 n o p:a:b:c:d:k:l:m" \
"a b c d e f g h i j k l m n o p:16:0:a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p"
do
oIFS="${IFS}"
IFS=:; set -- $a
IFS="${oIFS}"
init="$1"; n="$2"; res="$3"; shift 3
not=
for b
do
not="${not} -o not-match:$b"
done
atf_check -s exit:0 -o "match:${res}" ${not} -e empty \
${TEST_SH} -c "set -- ${init}; shift $n;"' echo "$# $*"'
done
atf_check -s exit:0 -o match:complete -o not-match:ERR -e empty \
${TEST_SH} -c \
'set -- a b c d e;while [ $# -gt 0 ];do shift||echo ERR;done;echo complete'
}
atf_test_case excessive_shift
excessive_shift_head() {
atf_set "descr" "Test acceptable operation of shift too many"
}
# In:
#
# http://pubs.opengroup.org/onlinepubs/9699919799
# /utilities/V3_chap02.html#tag_18_26_01
#
# (that URL should be one line, with the /util... immediately after ...9799)
#
# POSIX says of shift (in the "EXIT STATUS" paragraph):
#
# If the n operand is invalid or is greater than "$#", this may be considered
# a syntax error and a non-interactive shell may exit; if the shell does not
# exit in this case, a non-zero exit status shall be returned.
# Otherwise, zero shall be returned.
#
# NetBSD's sh treats it as an error and exits (if non-interactive, as here),
# other shells do not.
#
# Either behaviour is acceptable - so the test allows for both
# (and checks that if the shell does not exit, "shift" returns status != 0)
excessive_shift_body() {
for a in \
"one-arg:2" \
"one-arg:4" \
"one-arg:13" \
"one two:3" \
"one two:7" \
"one two three four five:6" \
"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:16" \
"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:17" \
"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:30" \
"I II III IV V VI VII VIII IX X XI XII XIII XIV XV:9999"
do
oIFS="${IFS}"
IFS=:; set -- $a
IFS="${oIFS}"
atf_check -s not-exit:0 -o match:OK -o not-match:ERR \
-e ignore ${TEST_SH} -c \
"set -- $1 ;"'echo OK:$#-'"$2;shift $2 && echo ERR"
done
}
atf_test_case function_shift
function_shift_head() {
atf_set "descr" "Test that shift in a function does not affect outside"
}
function_shift_body() {
: # later...
}
atf_test_case non_numeric_shift
non_numeric_shift_head() {
atf_set "descr" "Test that non-numeric args to shift are detected"
}
# from the DESCRIPTION section at the URL mentioned with the excessive_shift
# test:
#
# The value n shall be an unsigned decimal integer ...
#
# That is not hex (octal will be treated as if it were decimal, a leading 0
# will simply be ignored - we test for this by giving an "octal" value that
# would be OK if parsed as octal, but not if parsed (correctly) as decimal)
#
# Obviously total trash like roman numerals or alphabetic strings are out.
#
# Also no signed values (no + or -) and not a string that looks kind of like
# a number, but only if you're generous
#
# But as the EXIT STATUS section quoted above says, with an invalid 'n'
# the shell has the option of exiting, or returning status != 0, so
# again this test allows both.
non_numeric_shift_body() {
# there are 9 args set, 010 is 8 if parsed octal, 10 decimal
for a in a I 0x12 010 5V -1 ' ' '' +1 ' 1'
do
atf_check -s not-exit:0 -o empty -e ignore ${TEST_SH} -c \
"set -- a b c d e f g h i; shift '$a' && echo ERROR"
done
}
atf_test_case too_many_args
too_many_args_head() {
# See PR bin/50896
atf_set "descr" "Test that sh detects invalid extraneous args to shift"
}
# This is a syntax error, a non-interactive shell (us) must exit $? != 0
too_many_args_body() {
# This tests the bug in PR bin/50896 is fixed
for a in "1 1" "1 0" "1 2 3" "1 foo" "1 --" "-- 1"
do
atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
" set -- a b c d; shift ${a} ; echo FAILED "
done
}
atf_init_test_cases() {
atf_add_test_case basic_shift_test
atf_add_test_case excessive_shift
atf_add_test_case function_shift
atf_add_test_case non_numeric_shift
atf_add_test_case too_many_args
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_ulimit.sh,v 1.1 2012/06/11 18:32:59 njoly Exp $
# $NetBSD: t_ulimit.sh,v 1.3 2016/03/27 14:50:01 christos Exp $
#
# Copyright (c) 2012 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,6 +24,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
# ulimit builtin test.
@ -31,13 +33,22 @@ atf_test_case limits
limits_head() {
atf_set "descr" "Checks for limits flags"
}
get_ulimits() {
local limits=$(${TEST_SH} -c 'ulimit -a' |
sed -e 's/.*\(-[A-Za-z0-9]\)[^A-Za-z0-9].*/\1/' | sort -u)
if [ -z "$limits" ]; then
# grr ksh
limits="-a -b -c -d -f -l -m -n -p -r -s -t -v"
fi
echo "$limits"
}
limits_body() {
atf_check -s eq:0 -o ignore -e empty \
/bin/sh -c "ulimit -a"
for l in $(ulimit -a | sed 's,^.*(,,;s, .*$,,');
atf_check -s eq:0 -o ignore -e empty ${TEST_SH} -c "ulimit -a"
for l in $(get_ulimits)
do
atf_check -s eq:0 -o ignore -e empty \
/bin/sh -c "ulimit $l"
atf_check -s eq:0 -o ignore -e empty ${TEST_SH} -c "ulimit $l"
done
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_varquote.sh,v 1.2 2012/03/25 18:50:19 christos Exp $
# $NetBSD: t_varquote.sh,v 1.5 2016/03/27 14:50:01 christos Exp $
#
# Copyright (c) 2007 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,6 +24,8 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
# Variable quoting test.
@ -39,30 +41,70 @@ all_head() {
atf_set "descr" "Basic checks for variable quoting"
}
all_body() {
foo='${a:-foo}'
check "$foo" '${a:-foo}'
foo="${a:-foo}"
check "$foo" "foo"
cat <<-'EOF' > script.sh
T=0
check() {
T=$((${T} + 1))
foo=${a:-"'{}'"}
check "$foo" "'{}'"
if [ "$1" != "$2" ]
then
printf '%s\n' "T${T}: expected [$2], found [$1]"
exit 1
fi
}
foo=${a:-${b:-"'{}'"}}
check "$foo" "'{}'"
#1
foo='${a:-foo}'
check "$foo" '${a:-foo}'
#2
foo="${a:-foo}"
check "$foo" "foo"
#3
foo=${a:-"'{}'"}
check "$foo" "'{}'"
#4
foo=${a:-${b:-"'{}'"}}
check "$foo" "'{}'"
#5
# ${ } The ' are inside ".." so are literal (not quotes).
foo="${a-'}'}"
check "$foo" "''}"
#6
# The rules for quoting in ${var-word} expressions are somewhat
# weird, in the following there is not one quoted string being
# assigned to foo (with internally quoted sub-strings), rather
# it is a mixed quoted/unquoted string, with parts that are
# quoted, separated by 2 unquoted sections...
# qqqqqqqqqq uuuuuuuuuu qq uuuu qqqq
foo="${a:-${b:-"${c:-${d:-"x}"}}y}"}}z}"
# " z*"
# ${a:- }
# ${b:- }
# " y*"
# ${c:- }
# ${d:- }
# "x*"
check "$foo" "x}y}z}"
#7
# And believe it or not, this is the one that gives
# most problems, with 3 different observed outputs...
# qqqqq qq q is one interpretation
# qqqqq QQQQ q is another (most common)
# (the third is syntax error...)
foo="${a:-"'{}'"}"
check "$foo" "'{}'"
foo="${a:-"'{}'"}"
check "$foo" "'{}'"
EOF
foo="${a:-${b:-"${c:-${d:-"x}"}}y}"}}z}"
# " z*"
# ${a:- }
# ${b:- }
# " y*"
# ${c:- }
# ${d:- }
# "x*"
check "$foo" "x}y}z}"
OUT=$( ${TEST_SH} script.sh 2>&1 )
if [ $? -ne 0 ]
then
atf_fail "${OUT}"
elif [ -n "${OUT}" ]
then
atf_fail "script.sh unexpectedly said: ${OUT}"
fi
}
atf_test_case nested_quotes_multiword
@ -72,10 +114,21 @@ nested_quotes_multiword_head() {
}
nested_quotes_multiword_body() {
atf_check -s eq:0 -o match:"first-word second-word" -e empty \
/bin/sh -c 'echo "${foo:="first-word"} second-word"'
${TEST_SH} -c 'echo "${foo:="first-word"} second-word"'
}
atf_test_case default_assignment_with_arith
default_assignment_with_arith_head() {
atf_set "descr" "Tests default variable assignment with arithmetic" \
"string works (PR bin/50827)"
}
default_assignment_with_arith_body() {
atf_check -s eq:0 -o empty -e empty ${TEST_SH} -c ': "${x=$((1))}"'
atf_check -s eq:0 -o match:1 -e empty ${TEST_SH} -c 'echo "${x=$((1))}"'
}
atf_init_test_cases() {
atf_add_test_case all
atf_add_test_case nested_quotes_multiword
atf_add_test_case default_assignment_with_arith
}

251
bin/sh/t_varval.sh Executable file
View file

@ -0,0 +1,251 @@
# $NetBSD: t_varval.sh,v 1.1 2016/03/16 15:49:19 christos Exp $
#
# Copyright (c) 2016 The NetBSD Foundation, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
# Test all kinds of weird values in various ways to use shell $... expansions
oneline()
{
q="'"
test $# -eq 4 && q=""
v=$( printf '\\%3.3o' $(( $2 & 0xFF )) )
printf "%s" "$1"
if [ $2 != 39 ]; then
printf "%sprefix${v}suffix%s" "$q" "$q"
elif [ $# -ne 4 ]; then
printf %s prefix\"\'\"suffix
else
printf %s prefix\'suffix
fi
printf "%s\n" "$3"
}
mkdata() {
quote= pfx=
while [ $# -gt 0 ]
do
case "$1" in
--) shift; break;;
-q) quote=no; shift; continue;;
esac
pfx="${pfx}${pfx:+ }${1}"
shift
done
sfx=
while [ $# -gt 0 ]
do
sfx="${sfx}${sfx:+ }${1}"
shift
done
i=1 # '\0' is not expected to work, anywhere...
while [ $i -lt 256 ]
do
oneline "${pfx}" "$i" "${sfx}" $quote
i=$(( $i + 1 ))
done
}
atf_test_case aaa
aaa_head() {
atf_set "descr" "Check that this test has a hope of working. " \
"Just give up on these tests if the aaa test fails".
}
aaa_body() {
oneline "echo " 9 '' |
atf_check -s exit:0 -o inline:'prefix\tsuffix\n' -e empty \
${TEST_SH}
oneline "VAR=" 65 '; echo "${#VAR}:${VAR}"' |
atf_check -s exit:0 -o inline:'13:prefixAsuffix\n' -e empty \
${TEST_SH}
oneline "VAR=" 1 '; echo "${#VAR}:${VAR}"' |
atf_check -s exit:0 -o inline:'13:prefixsuffix\n' -e empty \
${TEST_SH}
oneline "VAR=" 10 '; echo "${#VAR}:${VAR}"' |
atf_check -s exit:0 -o inline:'13:prefix\nsuffix\n' -e empty \
${TEST_SH}
rm -f prefix* 2>/dev/null || :
oneline "echo hello >" 45 "" |
atf_check -s exit:0 -o empty -e empty ${TEST_SH}
test -f "prefix-suffix" ||
atf_fail "failed to create prefix-suffix (45)"
test -s "prefix-suffix" ||
atf_fail "no data in prefix-suffix (45)"
test "$(cat prefix-suffix)" = "hello" ||
atf_fail "incorrect data in prefix-suffix (45)"
return 0
}
atf_test_case assignment
assignment_head() {
atf_set "descr" "Check that all chars can be assigned to vars"
}
assignment_body() {
atf_require_prog grep
atf_require_prog rm
rm -f results || :
mkdata "VAR=" -- '; echo ${#VAR}' |
atf_check -s exit:0 -o save:results -e empty ${TEST_SH}
test -z $( grep -v "^13$" results ) ||
atf_fail "Incorrect lengths: $(grep -nv '^13$' results)"
return 0
}
atf_test_case cmdline
cmdline_head() {
atf_set "descr" "Check vars containing all chars can be used"
}
cmdline_body() {
atf_require_prog rm
atf_require_prog wc
rm -f results || :
mkdata "VAR=" -- '; echo "${VAR}"' |
atf_check -s exit:0 -o save:results -e empty ${TEST_SH}
# 256 because one output line contains a \n ...
test $( wc -l < results ) -eq 256 ||
atf_fail "incorrect line count in results"
test $(wc -c < results) -eq $(( 255 * 14 )) ||
atf_fail "incorrect character count in results"
return 0
}
atf_test_case redirect
redirect_head() {
atf_set "descr" "Check vars containing all chars can be used"
}
redirect_body() {
atf_require_prog ls
atf_require_prog wc
atf_require_prog rm
atf_require_prog mkdir
atf_require_prog rmdir
nl='
'
rm -f prefix* suffix || :
mkdir prefix # one of the files will be prefix/suffix
mkdata "VAR=" -- '; echo "${VAR}" > "${VAR}"' |
atf_check -s exit:0 -o empty -e empty ${TEST_SH}
test -f "prefix/suffix" ||
atf_fail "Failed to create file in subdirectory"
test $( wc -l < "prefix/suffix" ) -eq 1 ||
atf_fail "Not exactly one line in prefix/suffix file"
atf_check -s exit:0 -o empty -e empty rm "prefix/suffix"
atf_check -s exit:0 -o empty -e empty rmdir "prefix"
test -f "prefix${nl}suffix" ||
atf_fail "Failed to create file with newline in its name"
test $( wc -l < "prefix${nl}suffix" ) -eq 2 ||
atf_fail "NewLine file did not contain embedded newline"
atf_check -s exit:0 -o empty -e empty rm "prefix${nl}suffix"
# Now there should be 253 files left...
test $( ls | wc -l ) -eq 253 ||
atf_fail \
"Did not create all expected files: wanted: 253, found ($( ls | wc -l ))"
# and each of them should have a name that is 13 chars long (+ \n)
test $( ls | wc -c ) -eq $(( 253 * 14 )) ||
atf_fail "File names do not appear to be as expected"
return 0
}
atf_test_case read
read_head() {
atf_set "descr" "Check vars containing all chars can be used"
}
read_body() {
atf_require_prog ls
atf_require_prog wc
atf_require_prog rm
atf_require_prog mkdir
atf_require_prog rmdir
nl='
'
rm -f prefix* suffix || :
mkdir prefix # one of the files will be prefix/suffix
mkdata -q |
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c '
while read -r VAR
do
# skip the mess made by embedded newline
case "${VAR}" in
(prefix | suffix) continue;;
esac
echo "${VAR}" > "${VAR}"
done'
test -f "prefix/suffix" ||
atf_fail "Failed to create file in subdirectory"
test $( wc -l < "prefix/suffix" ) -eq 1 ||
atf_fail "Not exactly one line in prefix/suffix file"
atf_check -s exit:0 -o empty -e empty rm "prefix/suffix"
atf_check -s exit:0 -o empty -e empty rmdir "prefix"
# Now there should be 253 files left...
test $( ls | wc -l ) -eq 253 ||
atf_fail \
"Did not create all expected files: wanted: 253, found ($( ls | wc -l ))"
# and each of them should have a name that is 13 chars long (+ \n)
test $( ls | wc -c ) -eq $(( 253 * 14 )) ||
atf_fail "File names do not appear to be as expected"
return 0
}
atf_init_test_cases() {
atf_add_test_case aaa
atf_add_test_case assignment
atf_add_test_case cmdline
atf_add_test_case redirect
atf_add_test_case read
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_wait.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $
# $NetBSD: t_wait.sh,v 1.8 2016/03/31 16:22:54 christos Exp $
#
# Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc.
# All rights reserved.
@ -24,36 +24,172 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# the implementation of "sh" to test
: ${TEST_SH:="/bin/sh"}
atf_test_case basic_wait
basic_wait_head() {
atf_set "descr" "Tests simple uses of wait"
}
basic_wait_body() {
atf_require_prog sleep
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'(echo nothing >/dev/null) & wait'
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'(exit 3) & wait $!; S=$?; test $S -eq 3 || {
echo "status: $S"; exit 1; }'
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'sleep 3 & sleep 2 & sleep 1 & wait'
atf_check -s exit:0 -o empty -e empty ${TEST_SH} -c \
'sleep 3 & (exit 2) & sleep 1 & wait'
}
atf_test_case individual
individual_head() {
atf_set "descr" "Tests that waiting for individual jobs works"
atf_set "descr" "Tests that waiting for individual processes works"
}
individual_body() {
# atf-sh confuses wait for some reason; work it around by creating
# a helper script that executes /bin/sh directly.
cat >helper.sh <<EOF
sleep 3 &
sleep 1 &
atf_require_prog sleep
wait %1
if [ \$? -ne 0 ]; then
echo "Waiting of first job failed"
cat >individualhelper.sh <<\EOF
sleep 3 & P1=$!
sleep 1 & P2=$!
wait ${P1}
S=$?
if [ $S -ne 0 ]; then
echo "Waiting for first process failed: $S"
exit 1
fi
wait %2
if [ \$? -ne 0 ]; then
echo "Waiting of second job failed"
wait ${P2}
S=$?
if [ $? -ne 0 ]; then
echo "Waiting for second process failed"
exit 1
fi
exit 0
EOF
output=$(/bin/sh helper.sh)
output=$(${TEST_SH} individualhelper.sh 2>&1)
[ $? -eq 0 ] || atf_fail "${output}"
}
atf_init_test_cases() {
atf_add_test_case individual
atf_test_case jobs
jobs_head() {
atf_set "descr" "Tests that waiting for individual jobs works"
}
jobs_body() {
# atf-sh confuses wait for some reason; work it around by creating
# a helper script that executes /bin/sh directly.
if ! ${TEST_SH} -c 'sleep 1 & wait %1' 2>/dev/null
then
atf_skip "No job control support in this shell"
fi
cat >individualhelper.sh <<\EOF
sleep 3 &
sleep 1 &
wait %1
if [ $? -ne 0 ]; then
echo "Waiting for first job failed"
exit 1
fi
wait %2
if [ $? -ne 0 ]; then
echo "Waiting for second job failed"
exit 1
fi
exit 0
EOF
output=$(${TEST_SH} individualhelper.sh 2>&1)
[ $? -eq 0 ] || atf_fail "${output}"
cat >individualhelper.sh <<\EOF
{ sleep 3; exit 3; } &
{ sleep 1; exit 7; } &
wait %1
S=$?
if [ $S -ne 3 ]; then
echo "Waiting for first job failed - status: $S != 3 (expected)"
exit 1
fi
wait %2
S=$?
if [ $S -ne 7 ]; then
echo "Waiting for second job failed - status: $S != 7 (expected)"
exit 1
fi
exit 0
EOF
output=$(${TEST_SH} individualhelper.sh 2>&1)
[ $? -eq 0 ] || atf_fail "${output}"
}
atf_test_case kill
kill_head() {
atf_set "descr" "Tests that killing the shell while in wait calls trap"
}
kill_body() {
atf_require_prog sleep
atf_require_prog kill
s=killhelper.sh
z=killhelper.$$
pid=
# waiting for a specific process that is not a child
# should return exit status of 127 according to the spec
# This test is here before the next, to avoid that one
# entering an infinite loop should the shell have a bug here.
atf_check -s exit:127 -o empty -e ignore ${TEST_SH} -c 'wait 1'
cat > "${s}" <<'EOF'
trap "echo SIGHUP" 1
(sleep 5; exit 3) &
sl=$!
wait
S=$?
echo $S
LS=9999
while [ $S -ne 0 ] && [ $S != 127 ]; do
wait $sl; S=$?; echo $S
test $S = $LS && { echo "wait repeats..."; exit 2; }
LS=$S
done
EOF
${TEST_SH} $s > $z &
pid=$!
sleep 1
kill -HUP "${pid}"
wait
output="$(cat $z | tr '\n' ' ')"
if [ "$output" != "SIGHUP 129 3 127 " ]; then
atf_fail "${output} != 'SIGHUP 129 3 127 '"
fi
}
atf_init_test_cases() {
atf_add_test_case basic_wait
atf_add_test_case individual
atf_add_test_case jobs
atf_add_test_case kill
}

View file

@ -1,4 +1,4 @@
# $NetBSD: t_opencrypto.sh,v 1.4 2014/01/18 15:15:16 pgoyette Exp $
# $NetBSD: t_opencrypto.sh,v 1.6 2015/12/26 07:10:03 pgoyette Exp $
#
# Copyright (c) 2014 The NetBSD Foundation, Inc.
# All rights reserved.
@ -80,7 +80,11 @@ arc4_body() {
}
arc4_cleanup() {
common_cleanup
# No cleanup required since test is skipped. Trying to run rump.halt
# at this point fails, causing the ATF environment to erroneously
# report a failed test!
#
# common_cleanup
}
atf_test_case camellia cleanup
@ -98,7 +102,7 @@ camellia_cleanup() {
atf_test_case cbcdes cleanup
cbcdes_head() {
common_head "Test ARC4 crypto"
common_head "Test DES_CBC crypto"
}
cbcdes_body() {

View file

@ -1,13 +1,13 @@
# $NetBSD: Makefile,v 1.8 2012/08/08 13:57:05 christos Exp $
# $NetBSD: Makefile,v 1.11 2016/07/29 06:13:39 pgoyette Exp $
#
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/dev
TESTS_SUBDIRS+= cgd raidframe
.if (${MKRUMP} != "no")
TESTS_SUBDIRS+= audio md scsipi sysmon
TESTS_SUBDIRS+= cgd fss raidframe
.if (${MKRUMP} != "no") && !defined(BSD_MK_COMPAT_FILE)
TESTS_SUBDIRS+= audio md scsipi sysmon usb
.endif

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.4 2012/12/02 18:39:53 pgoyette Exp $
# $NetBSD: Makefile,v 1.5 2016/01/23 21:22:48 christos Exp $
#
.include <bsd.own.mk>
@ -13,6 +13,7 @@ MKMAN=no
PROGS= h_pad
CPPFLAGS+= -D_KERNTYPES
LDADD+= -lrumpdev_pad -lrumpdev_audio -lrumpdev -lrumpvfs
LDADD+= -lrump
LDADD+= -lrumpuser

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
# $NetBSD: Makefile,v 1.2 2012/12/02 18:39:53 pgoyette Exp $
# $NetBSD: Makefile,v 1.3 2016/01/23 21:22:48 christos Exp $
#
.include <bsd.own.mk>
@ -14,6 +14,7 @@ MKMAN=no
PROGS= h_dm
CPPFLAGS+=-D_KERNTYPES
LDADD+= -lprop -lutil
LDADD+= -lrumpdev_disk -lrumpdev_dm
LDADD+= -lrumpdev -lrumpvfs

View file

@ -1,4 +1,4 @@
/* $NetBSD: h_dm.c,v 1.1 2010/10/06 11:24:55 haad Exp $ */
/* $NetBSD: h_dm.c,v 1.2 2016/01/23 21:18:27 christos Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -83,6 +83,7 @@ dm_test_versions(void) {
dict_out = prop_dictionary_internalize(prefp.pref_plist);
xml = prop_dictionary_externalize(dict_out);
__USE(xml);
rump_sys_close(fd);
@ -122,6 +123,7 @@ dm_test_targets(void) {
dict_out = prop_dictionary_internalize(prefp.pref_plist);
xml = prop_dictionary_externalize(dict_out);
__USE(xml);
rump_sys_close(fd);

3
dev/fss/CVS/Entries Normal file
View file

@ -0,0 +1,3 @@
/Makefile/1.2/Wed Aug 3 23:53:50 2016//D2016.08.12.00.58.30
/t_fss.sh/1.2/Fri Jul 29 20:27:37 2016//D2016.08.12.00.58.30
D

1
dev/fss/CVS/Repository Normal file
View file

@ -0,0 +1 @@
src/tests/dev/fss

1
dev/fss/CVS/Root Normal file
View file

@ -0,0 +1 @@
anoncvs@anoncvs.NetBSD.org:/cvsroot

1
dev/fss/CVS/Tag Normal file
View file

@ -0,0 +1 @@
D2016.08.12.00.58.30

10
dev/fss/Makefile Normal file
View file

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.2 2016/08/03 23:53:50 pgoyette Exp $
#
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/dev/fss
TESTS_SH= t_fss
.include <bsd.test.mk>

84
dev/fss/t_fss.sh Executable file
View file

@ -0,0 +1,84 @@
# $NetBSD: t_fss.sh,v 1.2 2016/07/29 20:27:37 pgoyette Exp $
#
# Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#
# Verify basic operation of fss(4) file system snapshot device
#
orig_data="Original data"
repl_data="Replacement data"
atf_test_case basic cleanup
basic_body() {
# create of mount-points for the file system and snapshot
mkdir ./m1
mkdir ./m2
# create a small 4MB file, treat it as a disk, init a file-system on it,
# and mount it
dd if=/dev/zero of=./image bs=32k count=64
vndconfig -c vnd0 ./image
newfs /dev/vnd0a
mount /dev/vnd0a ./m1
echo "${orig_data}" > ./m1/text
# configure and mount a snapshot of the file system
fssconfig -c fss0 ./m1 ./backup
mount -o rdonly /dev/fss0 ./m2
# Modify the data on the underlying file system
echo "${repl_data}" > ./m1/text || abort
# Verify that original data is still visible in the snapshot
read test_data < ./m2/text
atf_check_equal "${orig_data}" "${test_data}"
# Unmount our temporary stuff
umount /dev/fss0 || true
fssconfig -u fss0 || true
umount /dev/vnd0a || true
vndconfig -u vnd0 || true
}
basic_cleanup() {
umount /dev/vnd0a || true
fssconfig -u fss0 || true
umount /dev/fss0 || true
vndconfig -u vnd0 || true
}
atf_init_test_cases()
{
atf_add_test_case basic
}

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.4 2014/06/09 18:22:05 he Exp $
# $NetBSD: Makefile,v 1.6 2016/01/23 21:22:48 christos Exp $
#
.include <bsd.own.mk>
@ -13,10 +13,10 @@ MKMAN=no
PROGS= h_mdserv
CPPFLAGS+= -D_KERNTYPES
LDADD+= -lrumpdev_md -lrumpdev_disk -lrumpdev -lrumpvfs
LDADD+= -lrump
LDADD+= -lrumpkern_sysproxy -lrump
LDADD+= -lrumpuser
LDADD+= -lrump
LDADD+= -lpthread
WARNS= 4

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.6 2014/06/10 04:28:39 he Exp $
# $NetBSD: Makefile,v 1.7 2016/01/23 21:22:48 christos Exp $
#
.include <bsd.own.mk>
@ -7,7 +7,7 @@ TESTSDIR= ${TESTSBASE}/dev/scsipi
TESTS_C= t_cd
CPPFLAGS+= -I${.CURDIR}/libscsitest
CPPFLAGS+= -I${.CURDIR}/libscsitest -D_KERNTYPES
# kernel component required by test
SUBDIR= libscsitest

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2014/06/10 04:28:39 he Exp $
# $NetBSD: Makefile,v 1.4 2016/01/23 21:22:48 christos Exp $
#
.include <bsd.own.mk>
@ -7,6 +7,7 @@ TESTSDIR= ${TESTSBASE}/dev/sysmon
TESTS_C= t_swwdog
CPPFLAGS+= -D_KERNTYPES
LDADD+= -lrumpdev_sysmon -lrumpdev -lrumpvfs
LDADD+= -lrump
LDADD+= -lrumpuser

View file

@ -1,4 +1,4 @@
# $NetBSD: t_swsensor.sh,v 1.7 2013/04/14 16:07:46 martin Exp $
# $NetBSD: t_swsensor.sh,v 1.9 2015/04/23 23:23:28 pgoyette Exp $
get_sensor_info() {
rump.envstat -x | \
@ -6,7 +6,13 @@ get_sensor_info() {
}
get_sensor_key() {
get_sensor_info | grep -A1 $1 | grep integer | sed -e 's;<[/a-z]*>;;g'
local v
v=$(get_sensor_info | grep -A1 $1 | grep integer | \
sed -e 's;<[/a-z]*>;;g')
if [ -z "$v" ] ; then
v="key_$1_not_found"
fi
echo $v
}
get_powerd_event_count() {
@ -60,7 +66,7 @@ start_rump() {
common_head() {
atf_set descr "$1"
atf_set timeout 60
atf_set timeout 120
atf_set require.progs rump.powerd rump.envstat rump.modload \
rump.halt rump.sysctl rump_server \
sed grep awk \

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_swwdog.c,v 1.5 2011/06/26 12:14:59 christos Exp $ */
/* $NetBSD: t_swwdog.c,v 1.6 2015/04/23 04:49:37 pgoyette Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -121,6 +121,7 @@ testbody(int max)
_exit(2);
}
/* fail */
printf("no watchdog registered!\n");
_exit(1);
}

4
dev/usb/CVS/Entries Normal file
View file

@ -0,0 +1,4 @@
/Makefile/1.3/Fri Jan 8 17:27:48 2016//D2016.08.12.00.58.30
/t_hid.c/1.8/Thu May 5 17:40:26 2016//D2016.08.12.00.58.30
D/libhid////
D/t_hid////

1
dev/usb/CVS/Repository Normal file
View file

@ -0,0 +1 @@
src/tests/dev/usb

1
dev/usb/CVS/Root Normal file
View file

@ -0,0 +1 @@
anoncvs@anoncvs.NetBSD.org:/cvsroot

1
dev/usb/CVS/Tag Normal file
View file

@ -0,0 +1 @@
D2016.08.12.00.58.30

12
dev/usb/Makefile Normal file
View file

@ -0,0 +1,12 @@
# $NetBSD: Makefile,v 1.3 2016/01/08 17:27:48 jakllsch Exp $
#
.include <bsd.own.mk>
SUBDIR= libhid .WAIT
TESTSDIR= ${TESTSBASE}/dev/usb
TESTS_SUBDIRS= t_hid
.include <bsd.test.mk>

View file

@ -0,0 +1,2 @@
/Makefile/1.1/Tue Jan 5 17:22:39 2016//D2016.08.12.00.58.30
D

View file

@ -0,0 +1 @@
src/tests/dev/usb/libhid

1
dev/usb/libhid/CVS/Root Normal file
View file

@ -0,0 +1 @@
anoncvs@anoncvs.NetBSD.org:/cvsroot

1
dev/usb/libhid/CVS/Tag Normal file
View file

@ -0,0 +1 @@
D2016.08.12.00.58.30

16
dev/usb/libhid/Makefile Normal file
View file

@ -0,0 +1,16 @@
# $NetBSD: Makefile,v 1.1 2016/01/05 17:22:39 jakllsch Exp $
#
.include <bsd.own.mk>
RUMPTOP= ${NETBSDSRCDIR}/sys/rump
.PATH: ${.CURDIR}/../../../../sys/dev/usb
LIB= rumpdev_hid
LIBISPRIVATE= #defined
SRCS= hid.c
.include "${RUMPTOP}/Makefile.rump"
.include <bsd.lib.mk>
.include <bsd.klinks.mk>

267
dev/usb/t_hid.c Normal file
View file

@ -0,0 +1,267 @@
/* $NetBSD: t_hid.c,v 1.8 2016/05/05 17:40:26 jakllsch Exp $ */
/*
* Copyright (c) 2016 Jonathan A. Kollasch
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_hid.c,v 1.8 2016/05/05 17:40:26 jakllsch Exp $");
#include <machine/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <atf-c.h>
#include <rump/rump.h>
#define hid_start_parse rumpns_hid_start_parse
#define hid_end_parse rumpns_hid_end_parse
#define hid_get_item rumpns_hid_get_item
#define hid_locate rumpns_hid_locate
#define hid_report_size rumpns_hid_report_size
#define hid_get_data rumpns_hid_get_data
#define hid_get_udata rumpns_hid_get_udata
#define uhidevdebug rumpns_uhidevdebug
#include <usb.h>
#include <usbhid.h>
#include <hid.h>
#include "../../lib/libusbhid/hid_test_data.c"
#define MYd_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== %d", (d))
#define MYld_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== %ld", (d))
#define MYu_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== %u", (d))
#define MYlu_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== %lu", (d))
#define MYx_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== 0x%x", (d))
#define MYlx_ATF_CHECK_EQ(d, v) \
ATF_CHECK_EQ_MSG(d, v, "== 0x%lx", (d))
int uhidevdebug;
ATF_TC(khid);
ATF_TC_HEAD(khid, tc)
{
atf_tc_set_md_var(tc, "descr", "check kernel hid.c");
}
static int
locate_item(const void *desc, int size, u_int32_t u, u_int8_t id,
enum hid_kind k, struct hid_item *hip)
{
struct hid_data *d;
struct hid_item h;
h.report_ID = 0;
for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) {
if (h.kind == k && !(h.flags & HIO_CONST) &&
(/*XXX*/uint32_t)h.usage == u && h.report_ID == id) {
if (hip != NULL)
*hip = h;
hid_end_parse(d);
return (1);
}
}
hid_end_parse(d);
return (0);
}
ATF_TC_BODY(khid, tc)
{
int ret;
struct hid_item hi;
uhidevdebug = 0;
rump_init();
rump_schedule();
ret = locate_item(range_test_report_descriptor,
sizeof(range_test_report_descriptor), 0xff000003, 0, hid_input,
&hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 32);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 0);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYd_ATF_CHECK_EQ(hi.logical_minimum, -2147483648);
MYd_ATF_CHECK_EQ(hi.logical_maximum, 2147483647);
MYd_ATF_CHECK_EQ(hi.physical_minimum, -2147483648);
MYd_ATF_CHECK_EQ(hi.physical_maximum, 2147483647);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
&hi.loc), -2147483648);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
&hi.loc), -1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
&hi.loc), 1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
&hi.loc), 2147483647);
ret = locate_item(range_test_report_descriptor,
sizeof(range_test_report_descriptor), 0xff000002, 0, hid_input,
&hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 16);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 32);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYd_ATF_CHECK_EQ(hi.logical_minimum, -32768);
MYd_ATF_CHECK_EQ(hi.logical_maximum, 32767);
MYd_ATF_CHECK_EQ(hi.physical_minimum, -32768);
MYd_ATF_CHECK_EQ(hi.physical_maximum, 32767);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
&hi.loc), -32768);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
&hi.loc), -1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
&hi.loc), 1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
&hi.loc), 32767);
ret = locate_item(range_test_report_descriptor,
sizeof(range_test_report_descriptor), 0xff000001, 0, hid_input,
&hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 8);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 48);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYd_ATF_CHECK_EQ(hi.logical_minimum, -128);
MYd_ATF_CHECK_EQ(hi.logical_maximum, 127);
MYd_ATF_CHECK_EQ(hi.physical_minimum, -128);
MYd_ATF_CHECK_EQ(hi.physical_maximum, 127);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_minimum_report,
&hi.loc), -128);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_negative_one_report,
&hi.loc), -1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_positive_one_report,
&hi.loc), 1);
MYld_ATF_CHECK_EQ(hid_get_data(range_test_maximum_report,
&hi.loc), 127);
ret = locate_item(unsigned_range_test_report_descriptor,
sizeof(unsigned_range_test_report_descriptor), 0xff000013, 0,
hid_input, &hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 32);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 0);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
&hi.loc), 0x0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
&hi.loc), 0x1);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
&hi.loc), 0xfffffffe);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
&hi.loc), 0xffffffff);
ret = locate_item(unsigned_range_test_report_descriptor,
sizeof(unsigned_range_test_report_descriptor), 0xff000012, 0,
hid_input, &hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 16);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 32);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
&hi.loc), 0x0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
&hi.loc), 0x1);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
&hi.loc), 0xfffe);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
&hi.loc), 0xffff);
ret = locate_item(unsigned_range_test_report_descriptor,
sizeof(unsigned_range_test_report_descriptor), 0xff000011, 0,
hid_input, &hi);
ATF_REQUIRE(ret > 0);
MYu_ATF_CHECK_EQ(hi.loc.size, 8);
MYu_ATF_CHECK_EQ(hi.loc.count, 1);
MYu_ATF_CHECK_EQ(hi.loc.pos, 48);
MYx_ATF_CHECK_EQ(hi.flags, 0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_minimum_report,
&hi.loc), 0x0);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_positive_one_report,
&hi.loc), 0x1);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_negative_one_report,
&hi.loc), 0xfe);
MYlx_ATF_CHECK_EQ(hid_get_udata(unsigned_range_test_maximum_report,
&hi.loc), 0xff);
rump_unschedule();
}
ATF_TC(khid_parse_just_pop);
ATF_TC_HEAD(khid_parse_just_pop, tc)
{
atf_tc_set_md_var(tc, "descr", "check kernel hid.c for "
"Pop on empty stack bug");
}
ATF_TC_BODY(khid_parse_just_pop, tc)
{
struct hid_data *hdp;
struct hid_item hi;
rump_init();
rump_schedule();
hdp = hid_start_parse(just_pop_report_descriptor,
sizeof just_pop_report_descriptor, hid_none);
while (hid_get_item(hdp, &hi) > 0) {
}
hid_end_parse(hdp);
rump_unschedule();
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, khid);
ATF_TP_ADD_TC(tp, khid_parse_just_pop);
return atf_no_error();
}

View file

@ -0,0 +1,2 @@
/Makefile/1.1/Fri Jan 8 17:27:48 2016//D2016.08.12.00.58.30
D

View file

@ -0,0 +1 @@
src/tests/dev/usb/t_hid

1
dev/usb/t_hid/CVS/Root Normal file
View file

@ -0,0 +1 @@
anoncvs@anoncvs.NetBSD.org:/cvsroot

1
dev/usb/t_hid/CVS/Tag Normal file
View file

@ -0,0 +1 @@
D2016.08.12.00.58.30

26
dev/usb/t_hid/Makefile Normal file
View file

@ -0,0 +1,26 @@
# $NetBSD: Makefile,v 1.1 2016/01/08 17:27:48 jakllsch Exp $
#
PROG= t_hid
NOMAN=
.PATH: ${.CURDIR}/..
CPPFLAGS.t_hid.c= -I${.CURDIR}/../../../../sys/dev/usb
.include <bsd.own.mk>
BINDIR= ${TESTSBASE}/dev/usb
LIBHIDDIR!= cd ${.CURDIR}/../libhid && ${PRINTOBJDIR}
LDFLAGS+= -L${LIBHIDDIR}
LDADD+= -Wl,--whole-archive -lrumpdev_hid -Wl,--no-whole-archive
DPADD+= ${LIBHIDDIR}/librumpdev_hid.a
DPADD+= ${ATF_C}
LDADD+= -latf-c
LDADD+= -lrump
LDADD+= -lrumpuser
LDADD+= -lpthread
.include <bsd.prog.mk>

View file

@ -1 +1,2 @@
.include "../Makefile.inc"
CPPFLAGS+= -D_KERNTYPES

View file

@ -1,4 +1,4 @@
/* $NetBSD: fstest_lfs.c,v 1.4 2010/07/30 16:15:05 pooka Exp $ */
/* $NetBSD: fstest_lfs.c,v 1.5 2015/08/30 18:27:26 dholland Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -48,8 +48,6 @@
#include "h_fsmacros.h"
#include "mount_lfs.h"
sem_t lfs_clearnerloop;
struct lfstestargs {
struct ufs_args ta_uargs;
pthread_t ta_cleanerthread;

View file

@ -1,4 +1,4 @@
/* $NetBSD: h_fsmacros.h,v 1.38 2013/06/26 19:29:24 reinoud Exp $ */
/* $NetBSD: h_fsmacros.h,v 1.40 2015/08/29 19:19:43 dholland Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -110,10 +110,6 @@ do { \
atf_tc_set_md_var(tc, "descr", type " test for " desc); \
atf_tc_set_md_var(tc, "X-fs.type", #fs); \
atf_tc_set_md_var(tc, "X-fs.mntname", type); \
if (strcmp(#fs, "zfs") == 0) { \
/* This should not be necessary. */ \
atf_tc_set_md_var(tc, "require.user", "root"); \
} \
} \
void *fs##func##tmp; \
\
@ -136,10 +132,6 @@ do { \
atf_tc_set_md_var(tc, "descr",_type_" test for "_desc_);\
atf_tc_set_md_var(tc, "X-fs.type", #_fs_); \
atf_tc_set_md_var(tc, "X-fs.mntname", _type_); \
if (strcmp(#_fs_, "zfs") == 0) { \
/* This should not be necessary. */ \
atf_tc_set_md_var(tc, "require.user", "root"); \
} \
} \
void *_fs_##_func_##tmp; \
\
@ -153,7 +145,7 @@ do { \
atf_tc_fail_errno("unmount r/w failed"); \
if (_fs_##_fstest_mount(tc, _fs_##_func_##tmp, \
FSTEST_MNTNAME, MNT_RDONLY) != 0) \
atf_tc_fail_errno("mount ro failed"); \
atf_tc_fail_errno("mount ro failed"); \
_func_(tc,FSTEST_MNTNAME); \
if (_fs_##_fstest_unmount(tc, FSTEST_MNTNAME, 0) != 0) {\
rump_pub_vfs_mount_print(FSTEST_MNTNAME, 1); \

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.17 2012/01/18 20:51:23 bouyer Exp $
# $NetBSD: Makefile,v 1.18 2015/01/07 22:24:03 pooka Exp $
#
.include <bsd.own.mk>
@ -34,6 +34,7 @@ LDADD+=-lrumpdev_disk -lrumpdev # disk device
LDADD+=-lrumpvfs_fifofs -lrumpnet_local -lrumpnet_net -lrumpnet # fifos
VFSTESTDIR != cd ${.CURDIR}/../common && ${PRINTOBJDIR}
LDADD+=-L${VFSTESTDIR} -lvfstest
LDADD+=-lrumpvfs -lrump -lrumpuser -lpthread # base
LDADD+=-lrumpvfs -lrumpkern_sysproxy -lrump -lrumpuser # base
LDADD+=-lpthread
.include <bsd.test.mk>

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.1 2010/04/13 10:21:47 pooka Exp $
# $NetBSD: Makefile,v 1.2 2015/01/07 23:12:31 pooka Exp $
#
TESTSDIR= ${TESTSBASE}/fs/msdosfs
@ -9,6 +9,7 @@ TESTS_C= t_snapshot
LDADD+=-lrumpfs_msdos -lrumpfs_tmpfs # fs drivers
LDADD+=-lrumpdev_fss # snapshot dev
LDADD+=-lrumpdev_disk -lrumpdev # disk device
LDADD+=-lrumpvfs -lrump -lrumpuser -lpthread # base
LDADD+=-lrumpvfs -lrumpkern_sysproxy -lrump -lrumpuser # base
LDADD+=-lpthread
.include <bsd.test.mk>

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.9 2014/06/10 04:28:39 he Exp $
# $NetBSD: Makefile,v 1.10 2015/01/08 03:50:56 pooka Exp $
#
.include <bsd.own.mk>
@ -22,7 +22,8 @@ LDADD+=-lrumpfs_ffs -lrumpvfs # ffs
LDADD+=-lrumpdev_disk -lrumpdev # disk device
LDADD+=-lrumpnet_shmif # shmif
LDADD+=-lrumpnet_netinet -lrumpnet_net -lrumpnet
LDADD+=-lrump -lrumpuser -lrump -lpthread # base
LDADD+=-lrumpkern_sysproxy -lrump -lrumpuser # base
LDADD+=-lpthread
LDADD+=-lutil

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.7 2013/03/06 13:35:22 christos Exp $
# $NetBSD: Makefile,v 1.11 2015/12/23 18:42:23 christos Exp $
#
NOMAN= 1
@ -16,22 +16,35 @@ LDADD+= -L${VFSTESTDIR} -Wl,--whole-archive -lvfstest -Wl,--no-whole-archive
TESTS_C=rumpnfsd
SRCS.rumpnfsd= rumpnfsd.c nfsd.c mountd.c getmntinfo.c
SRCS.rumpnfsd= rumpnfsd.c nfsd.c mountd.c getmntinfo.c get_net.c
LDADD+= -lrumpfs_nfsserver -lrumpfs_nfs # NFS support
LDADD+= -lrumpdev_disk -lrumpdev # disk devices
LDADD+= -lrumpfs_ffs -lrumpvfs # FFS
LDADD+= -lrumpnet_netinet -lrumpnet_net -lrumpnet_local # TCP/IP
LDADD+= -lrumpnet_shmif # shmif
LDADD+= -lrumpnet -lrump -lrumpuser # base
LDADD+= -lrumpnet -lrumpkern_sysproxy -lrump -lrumpuser # base
LDADD+= -lpthread -lutil
CPPFLAGS+= -DDEBUG -DMOUNT_NOMAIN -D_REENTRANT
CPPFLAGS+= -DRUMP_SYS_NETWORKING
CPPFLAGS+= -DRUMP_SYS_NETWORKING -DMOUNTD_RUMP -DNFSD_RUMP
.PATH: ${.CURDIR}/rpcbind
.include "rpcbind/Makefile.inc"
.PATH.c: ${NETBSDSRCDIR}/usr.sbin/mountd ${NETBSDSRCDIR}/usr.sbin/nfsd
WARNS= 2
# RPCBIND
.PATH.c: ${NETBSDSRCDIR}/usr.sbin/rpcbind
SRCS.rumpnfsd+= check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \
rpcb_svc.c rpcb_svc_com.c security.c util.c
LIBRPCDIR= ${NETBSDSRCDIR}/lib/libc/rpc
CPPFLAGS+= -I${LIBRPCDIR} -DPORTMAP -DLIBWRAP -DRPCBIND_RUMP
# Uncomment these to get any useful output from 'rpcbind -d'
# CPPFLAGS+= -DRPCBIND_DEBUG
# CPPFLAGS+= -DSVC_RUN_DEBUG
LDADD+= -lwrap -lutil
DPADD+= ${LIBWRAP} ${LIBUTIL}
.include <bsd.test.mk>

File diff suppressed because it is too large Load diff

View file

@ -1,571 +0,0 @@
/* $NetBSD: nfsd.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
#else
__RCSID("$NetBSD: nfsd.c,v 1.4 2013/10/19 17:45:00 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/uio.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <poll.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_prot.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <netdb.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
/* Global defs */
#ifdef DEBUG
#define syslog(e, s, args...) \
do { \
fprintf(stderr,(s), ## args); \
fprintf(stderr, "\n"); \
} while (/*CONSTCOND*/0)
int debug = 1;
#else
int debug = 0;
#endif
int main __P((int, char **));
void nonfs __P((int));
void usage __P((void));
static void *
child(void *arg)
{
struct nfsd_srvargs nsd;
int nfssvc_flag;
nfssvc_flag = NFSSVC_NFSD;
memset(&nsd, 0, sizeof(nsd));
while (rump_sys_nfssvc(nfssvc_flag, &nsd) < 0) {
if (errno != ENEEDAUTH) {
syslog(LOG_ERR, "nfssvc: %m %d", errno);
exit(1);
}
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
}
return NULL;
}
/*
* Nfs server daemon mostly just a user context for nfssvc()
*
* 1 - do file descriptor and signal cleanup
* 2 - create the nfsd thread(s)
* 3 - create server socket(s)
* 4 - register socket with portmap
*
* For connectionless protocols, just pass the socket into the kernel via
* nfssvc().
* For connection based sockets, loop doing accepts. When you get a new
* socket from accept, pass the msgsock into the kernel via nfssvc().
* The arguments are:
* -c - support iso cltp clients
* -r - reregister with portmapper
* -t - support tcp nfs clients
* -u - support udp nfs clients
* followed by "n" which is the number of nfsd threads to create
*/
int nfsd_main(int, char**);
int
nfsd_main(argc, argv)
int argc;
char *argv[];
{
struct nfsd_args nfsdargs;
struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
struct sockaddr_in inetpeer;
struct pollfd set[4];
socklen_t len;
int ch, connect_type_cnt, i, msgsock;
int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock;
int tcp6sock, ip6flag;
int tp4cnt, tp4flag, tpipcnt, udpflag, ecode, s;
int error = 0;
#define DEFNFSDCNT 4
nfsdcnt = DEFNFSDCNT;
reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
udpflag = ip6flag = 0;
nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
tcpsock = tcp6sock = -1;
#define GETOPT "6n:rtu"
#define USAGE "[-rtu] [-n num_servers]"
while ((ch = getopt(argc, argv, GETOPT)) != -1) {
switch (ch) {
case '6':
ip6flag = 1;
s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0 && (errno == EPROTONOSUPPORT ||
errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
ip6flag = 0;
else
close(s);
break;
case 'n':
nfsdcnt = atoi(optarg);
if (nfsdcnt < 1) {
warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
nfsdcnt = DEFNFSDCNT;
}
break;
case 'r':
reregister = 1;
break;
case 't':
tcpflag = 1;
break;
case 'u':
udpflag = 1;
break;
default:
case '?':
usage();
};
}
argv += optind;
argc -= optind;
/*
* XXX
* Backward compatibility, trailing number is the count of daemons.
*/
if (argc > 1)
usage();
if (argc == 1) {
nfsdcnt = atoi(argv[0]);
if (nfsdcnt < 1) {
warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
nfsdcnt = DEFNFSDCNT;
}
}
/*
* If none of TCP or UDP are specified, default to UDP only.
*/
if (tcpflag == 0 && udpflag == 0)
udpflag = 1;
if (debug == 0) {
fprintf(stderr, "non-debug not supported here\n");
exit(1);
#ifdef not_the_debug_man
daemon(0, 0);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGSYS, nonfs);
#endif
}
if (udpflag) {
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
if (ecode != 0) {
syslog(LOG_ERR, "getaddrinfo udp: %s",
gai_strerror(ecode));
exit(1);
}
nconf_udp = getnetconfigent("udp");
if (nconf_udp == NULL)
err(1, "getnetconfigent udp failed");
nb_udp.buf = ai_udp->ai_addr;
nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
if (reregister)
if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp))
err(1, "rpcb_set udp failed");
}
if (tcpflag) {
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
if (ecode != 0) {
syslog(LOG_ERR, "getaddrinfo tcp: %s",
gai_strerror(ecode));
exit(1);
}
nconf_tcp = getnetconfigent("tcp");
if (nconf_tcp == NULL)
err(1, "getnetconfigent tcp failed");
nb_tcp.buf = ai_tcp->ai_addr;
nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
if (reregister)
if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp))
err(1, "rpcb_set tcp failed");
}
if (udpflag && ip6flag) {
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
if (ecode != 0) {
syslog(LOG_ERR, "getaddrinfo udp: %s",
gai_strerror(ecode));
exit(1);
}
nconf_udp6 = getnetconfigent("udp6");
if (nconf_udp6 == NULL)
err(1, "getnetconfigent udp6 failed");
nb_udp6.buf = ai_udp6->ai_addr;
nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
if (reregister)
if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6))
err(1, "rpcb_set udp6 failed");
}
if (tcpflag && ip6flag) {
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
if (ecode != 0) {
syslog(LOG_ERR, "getaddrinfo tcp: %s",
gai_strerror(ecode));
exit(1);
}
nconf_tcp6 = getnetconfigent("tcp6");
if (nconf_tcp6 == NULL)
err(1, "getnetconfigent tcp6 failed");
nb_tcp6.buf = ai_tcp6->ai_addr;
nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
if (reregister)
if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6))
err(1, "rpcb_set tcp6 failed");
}
openlog("nfsd", LOG_PID, LOG_DAEMON);
for (i = 0; i < nfsdcnt; i++) {
pthread_t t;
pthread_create(&t, NULL, child, NULL);
}
/* If we are serving udp, set up the socket. */
if (udpflag) {
if ((sock = rump_sys_socket(ai_udp->ai_family, ai_udp->ai_socktype,
ai_udp->ai_protocol)) < 0) {
syslog(LOG_ERR, "can't create udp socket");
exit(1);
}
if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) {
syslog(LOG_ERR, "can't bind udp addr");
exit(1);
}
if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) ||
!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) {
syslog(LOG_ERR, "can't register with udp portmap");
exit(1);
}
nfsdargs.sock = sock;
nfsdargs.name = NULL;
nfsdargs.namelen = 0;
if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
syslog(LOG_ERR, "can't add UDP socket");
exit(1);
}
(void)rump_sys_close(sock);
}
if (udpflag &&ip6flag) {
if ((sock = rump_sys_socket(ai_udp6->ai_family, ai_udp6->ai_socktype,
ai_udp6->ai_protocol)) < 0) {
syslog(LOG_ERR, "can't create udp socket");
exit(1);
}
if (rump_sys_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof on) < 0) {
syslog(LOG_ERR, "can't set v6-only binding for udp6 "
"socket: %m");
exit(1);
}
if (rump_sys_bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) {
syslog(LOG_ERR, "can't bind udp addr");
exit(1);
}
if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) ||
!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) {
syslog(LOG_ERR, "can't register with udp portmap");
exit(1);
}
nfsdargs.sock = sock;
nfsdargs.name = NULL;
nfsdargs.namelen = 0;
if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
syslog(LOG_ERR, "can't add UDP6 socket");
exit(1);
}
(void)rump_sys_close(sock);
}
/* Now set up the master server socket waiting for tcp connections. */
on = 1;
connect_type_cnt = 0;
if (tcpflag) {
if ((tcpsock = rump_sys_socket(ai_tcp->ai_family, ai_tcp->ai_socktype,
ai_tcp->ai_protocol)) < 0) {
syslog(LOG_ERR, "can't create tcp socket");
exit(1);
}
if (setsockopt(tcpsock,
SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) {
syslog(LOG_ERR, "can't bind tcp addr");
exit(1);
}
if (rump_sys_listen(tcpsock, 5) < 0) {
syslog(LOG_ERR, "listen failed");
exit(1);
}
if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) ||
!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) {
syslog(LOG_ERR, "can't register tcp with rpcbind");
exit(1);
}
set[0].fd = tcpsock;
set[0].events = POLLIN;
connect_type_cnt++;
} else
set[0].fd = -1;
if (tcpflag && ip6flag) {
if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype,
ai_tcp6->ai_protocol)) < 0) {
syslog(LOG_ERR, "can't create tcp socket");
exit(1);
}
if (setsockopt(tcp6sock,
SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof on) < 0) {
syslog(LOG_ERR, "can't set v6-only binding for tcp6 "
"socket: %m");
exit(1);
}
if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) {
syslog(LOG_ERR, "can't bind tcp6 addr");
exit(1);
}
if (listen(tcp6sock, 5) < 0) {
syslog(LOG_ERR, "listen failed");
exit(1);
}
if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) ||
!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) {
syslog(LOG_ERR, "can't register tcp6 with rpcbind");
exit(1);
}
set[1].fd = tcp6sock;
set[1].events = POLLIN;
connect_type_cnt++;
} else
set[1].fd = -1;
set[2].fd = -1;
set[3].fd = -1;
if (connect_type_cnt == 0) {
pause();
exit(0);
}
/*
* Loop forever accepting connections and passing the sockets
* into the kernel for the mounts.
*/
for (;;) {
if (rump_sys_poll(set, 4, INFTIM) < 1) {
syslog(LOG_ERR, "poll failed: %m");
exit(1);
}
len = sizeof(inetpeer);
if ((msgsock = accept(tcpsock,
(struct sockaddr *)&inetpeer, &len)) < 0) {
syslog(LOG_ERR, "accept failed: %d", error);
exit(1);
}
memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
if (setsockopt(msgsock, SOL_SOCKET,
SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
syslog(LOG_ERR,
"setsockopt SO_KEEPALIVE: %m");
nfsdargs.sock = msgsock;
nfsdargs.name = (caddr_t)&inetpeer;
nfsdargs.namelen = sizeof(inetpeer);
rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
(void)rump_sys_close(msgsock);
#ifdef notyet
if (set[1].revents & POLLIN) {
len = sizeof(inet6peer);
if ((msgsock = rump_sys_accept(tcp6sock,
(struct sockaddr *)&inet6peer, &len, &error)) < 0) {
syslog(LOG_ERR, "accept failed: %m");
exit(1);
}
if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
syslog(LOG_ERR,
"setsockopt SO_KEEPALIVE: %m");
nfsdargs.sock = msgsock;
nfsdargs.name = (caddr_t)&inet6peer;
nfsdargs.namelen = sizeof(inet6peer);
rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
(void)rump_sys_close(msgsock, &error);
}
if (set[2].revents & POLLIN) {
len = sizeof(isopeer);
if ((msgsock = rump_sys_accept(tp4sock,
(struct sockaddr *)&isopeer, &len, &error)) < 0) {
syslog(LOG_ERR, "accept failed: %m");
exit(1);
}
if (rump_sys_setsockopt(msgsock, SOL_SOCKET,
SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0)
syslog(LOG_ERR,
"setsockopt SO_KEEPALIVE: %m");
nfsdargs.sock = msgsock;
nfsdargs.name = (caddr_t)&isopeer;
nfsdargs.namelen = len;
rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error);
(void)rump_sys_close(msgsock, &error);
}
if (set[3].revents & POLLIN) {
len = sizeof(inetpeer);
if ((msgsock = rump_sys_accept(tpipsock,
(struct sockaddr *)&inetpeer, &len)) < 0) {
syslog(LOG_ERR, "accept failed: %m");
exit(1);
}
if (setsockopt(msgsock, SOL_SOCKET,
SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
nfsdargs.sock = msgsock;
nfsdargs.name = (caddr_t)&inetpeer;
nfsdargs.namelen = len;
rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
(void)rump_sys_close(msgsock);
}
#endif /* notyet */
}
}
void
usage()
{
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
exit(1);
}
void
nonfs(signo)
int signo;
{
syslog(LOG_ERR, "missing system call: NFS not available.");
}

View file

@ -1,15 +0,0 @@
# $NetBSD: Makefile.inc,v 1.3 2013/03/06 13:36:50 christos Exp $
SRCS.rumpnfsd+= check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \
rpcb_svc.c rpcb_svc_com.c security.c util.c
LIBRPCDIR= ${NETBSDSRCDIR}/lib/libc/rpc
CPPFLAGS+= -I${LIBRPCDIR} -DPORTMAP -DLIBWRAP
# Uncomment these to get any useful output from 'rpcbind -d'
# CPPFLAGS+= -DRPCBIND_DEBUG
# CPPFLAGS+= -DSVC_RUN_DEBUG
LDADD+= -lwrap -lutil
DPADD+= ${LIBWRAP} ${LIBUTIL}

View file

@ -1,231 +0,0 @@
/* $NetBSD: check_bound.c,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)check_bound.c 1.15 93/07/05 SMI" */
#if 0
#ifndef lint
static char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
#endif
#endif
/*
* check_bound.c
* Checks to see whether the program is still bound to the
* claimed address and returns the univeral merged address
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <stdio.h>
#include <netconfig.h>
#include <syslog.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include "rpcbind.h"
struct fdlist {
int fd;
struct netconfig *nconf;
struct fdlist *next;
int check_binding;
};
static struct fdlist *fdhead; /* Link list of the check fd's */
static struct fdlist *fdtail;
static const char emptystring[] = "";
static bool_t check_bound(struct fdlist *, const char *uaddr);
/*
* Returns 1 if the given address is bound for the given addr & transport
* For all error cases, we assume that the address is bound
* Returns 0 for success.
*/
static bool_t
check_bound(struct fdlist *fdl, const char *uaddr)
{
int fd;
struct netbuf *na;
int ans;
if (fdl->check_binding == FALSE)
return (TRUE);
na = uaddr2taddr(fdl->nconf, uaddr);
if (!na)
return (TRUE); /* punt, should never happen */
fd = __rpc_nconf2fd(fdl->nconf);
if (fd < 0) {
free(na);
return (TRUE);
}
ans = bind(fd, (struct sockaddr *)na->buf, na->len);
rump_sys_close(fd);
free(na);
return (ans == 0 ? FALSE : TRUE);
}
int
add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
{
struct fdlist *fdl;
struct netconfig *newnconf;
newnconf = getnetconfigent(nconf->nc_netid);
if (newnconf == NULL)
return (-1);
fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
if (fdl == NULL) {
freenetconfigent(newnconf);
syslog(LOG_ERR, "no memory!");
return (-1);
}
fdl->nconf = newnconf;
fdl->next = NULL;
if (fdhead == NULL) {
fdhead = fdl;
fdtail = fdl;
} else {
fdtail->next = fdl;
fdtail = fdl;
}
/* XXX no bound checking for now */
fdl->check_binding = FALSE;
return 0;
}
bool_t
is_bound(const char *netid, const char *uaddr)
{
struct fdlist *fdl;
for (fdl = fdhead; fdl; fdl = fdl->next)
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
break;
if (fdl == NULL)
return (TRUE);
return (check_bound(fdl, uaddr));
}
/*
* Returns NULL if there was some system error.
* Returns "" if the address was not bound, i.e the server crashed.
* Returns the merged address otherwise.
*/
char *
mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
{
struct fdlist *fdl;
char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
for (fdl = fdhead; fdl; fdl = fdl->next)
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
break;
if (fdl == NULL)
return (NULL);
if (check_bound(fdl, uaddr) == FALSE)
/* that server died */
return strdup(emptystring);
/*
* If saddr is not NULL, the remote client may have included the
* address by which it contacted us. Use that for the "client" uaddr,
* otherwise use the info from the SVCXPRT.
*/
if (saddr != NULL) {
c_uaddr = saddr;
} else {
c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
if (c_uaddr == NULL) {
syslog(LOG_ERR, "taddr2uaddr failed for %s",
fdl->nconf->nc_netid);
return (NULL);
}
allocated_uaddr = c_uaddr;
}
#ifdef RPCBIND_DEBUG
if (debugging) {
if (saddr == NULL) {
fprintf(stderr, "mergeaddr: client uaddr = %s\n",
c_uaddr);
} else {
fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
c_uaddr);
}
}
#endif
s_uaddr = uaddr;
/*
* This is all we should need for IP 4 and 6
*/
m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
uaddr, m_uaddr);
#endif
if (allocated_uaddr != NULL)
free(allocated_uaddr);
return (m_uaddr);
}
/*
* Returns a netconf structure from its internal list. This
* structure should not be freed.
*/
struct netconfig *
rpcbind_get_conf(const char *netid)
{
struct fdlist *fdl;
for (fdl = fdhead; fdl; fdl = fdl->next)
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
break;
if (fdl == NULL)
return (NULL);
return (fdl->nconf);
}

View file

@ -1,366 +0,0 @@
/* $NetBSD: pmap_svc.c,v 1.2 2013/10/19 17:45:00 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */
#if 0
#ifndef lint
static char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro";
#endif
#endif
/*
* pmap_svc.c
* The server procedure for the version 2 portmapper.
* All the portmapper related interface from the portmap side.
*/
#ifdef PORTMAP
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/rpcb_prot.h>
#ifdef RPCBIND_DEBUG
#include <stdlib.h>
#endif
#include "rpcbind.h"
static struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, rpcprot_t);
static bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long);
static bool_t pmapproc_getport(struct svc_req *, SVCXPRT *);
static bool_t pmapproc_dump(struct svc_req *, SVCXPRT *);
/*
* Called for all the version 2 inquiries.
*/
void
pmap_service(struct svc_req *rqstp, SVCXPRT *xprt)
{
rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc);
switch (rqstp->rq_proc) {
case PMAPPROC_NULL:
/*
* Null proc call
*/
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "PMAPPROC_NULL\n");
#endif
check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS);
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) &&
debugging) {
if (doabort) {
rpcbind_abort();
}
}
break;
case PMAPPROC_SET:
/*
* Set a program, version to port mapping
*/
pmapproc_change(rqstp, xprt, rqstp->rq_proc);
break;
case PMAPPROC_UNSET:
/*
* Remove a program, version to port mapping.
*/
pmapproc_change(rqstp, xprt, rqstp->rq_proc);
break;
case PMAPPROC_GETPORT:
/*
* Lookup the mapping for a program, version and return its
* port number.
*/
pmapproc_getport(rqstp, xprt);
break;
case PMAPPROC_DUMP:
/*
* Return the current set of mapped program, version
*/
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "PMAPPROC_DUMP\n");
#endif
pmapproc_dump(rqstp, xprt);
break;
case PMAPPROC_CALLIT:
/*
* Calls a procedure on the local machine. If the requested
* procedure is not registered this procedure does not return
* error information!!
* This procedure is only supported on rpc/udp and calls via
* rpc/udp. It passes null authentication parameters.
*/
rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS);
break;
default:
svcerr_noproc(xprt);
break;
}
}
/*
* returns the item with the given program, version number. If that version
* number is not found, it returns the item with that program number, so that
* the port number is now returned to the caller. The caller when makes a
* call to this program, version number, the call will fail and it will
* return with PROGVERS_MISMATCH. The user can then determine the highest
* and the lowest version number for this program using clnt_geterr() and
* use those program version numbers.
*/
static struct pmaplist *
find_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
{
register struct pmaplist *hit = NULL;
register struct pmaplist *pml;
for (pml = list_pml; pml != NULL; pml = pml->pml_next) {
if ((pml->pml_map.pm_prog != prog) ||
(pml->pml_map.pm_prot != prot))
continue;
hit = pml;
if (pml->pml_map.pm_vers == vers)
break;
}
return (hit);
}
static bool_t
pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op)
{
struct pmap reg;
RPCB rpcbreg;
long ans;
struct sockcred *sc;
char uidbuf[32];
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "%s request for (%lu, %lu) : ",
op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET",
reg.pm_prog, reg.pm_vers);
#endif
if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
svcerr_decode(xprt);
return (FALSE);
}
if (!check_access(xprt, op, &reg, PMAPVERS)) {
svcerr_weakauth(xprt);
return FALSE;
}
(void)svc_getcaller(xprt);
sc = __svc_getcallercreds(xprt);
/*
* Can't use getpwnam here. We might end up calling ourselves
* and looping.
*/
if (sc == NULL)
rpcbreg.r_owner = __UNCONST(rpcbind_unknown);
else if (sc->sc_uid == 0)
rpcbreg.r_owner = __UNCONST(rpcbind_superuser);
else {
/* r_owner will be strdup-ed later */
snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid);
rpcbreg.r_owner = uidbuf;
}
rpcbreg.r_prog = reg.pm_prog;
rpcbreg.r_vers = reg.pm_vers;
if (op == PMAPPROC_SET) {
char buf[32];
snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d",
(int)((reg.pm_port >> 8) & 0xff),
(int)(reg.pm_port & 0xff));
rpcbreg.r_addr = buf;
if (reg.pm_prot == IPPROTO_UDP) {
rpcbreg.r_netid = __UNCONST(udptrans);
} else if (reg.pm_prot == IPPROTO_TCP) {
rpcbreg.r_netid = __UNCONST(tcptrans);
} else {
ans = FALSE;
goto done_change;
}
ans = map_set(&rpcbreg, rpcbreg.r_owner);
} else if (op == PMAPPROC_UNSET) {
bool_t ans1, ans2;
rpcbreg.r_addr = NULL;
rpcbreg.r_netid = __UNCONST(tcptrans);
ans1 = map_unset(&rpcbreg, rpcbreg.r_owner);
rpcbreg.r_netid = __UNCONST(udptrans);
ans2 = map_unset(&rpcbreg, rpcbreg.r_owner);
ans = ans1 || ans2;
} else {
ans = FALSE;
}
done_change:
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) &&
debugging) {
fprintf(stderr, "portmap: svc_sendreply\n");
if (doabort) {
rpcbind_abort();
}
}
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
#endif
if (op == PMAPPROC_SET)
rpcbs_set(RPCBVERS_2_STAT, ans);
else
rpcbs_unset(RPCBVERS_2_STAT, ans);
return (TRUE);
}
/* ARGSUSED */
static bool_t
pmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt)
{
struct pmap reg;
long lport;
int port = 0;
struct pmaplist *fnd;
#ifdef RPCBIND_DEBUG
char *uaddr;
#endif
if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
svcerr_decode(xprt);
return (FALSE);
}
if (!check_access(xprt, PMAPPROC_GETPORT, &reg, PMAPVERS)) {
svcerr_weakauth(xprt);
return FALSE;
}
#ifdef RPCBIND_DEBUG
if (debugging) {
uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid),
svc_getrpccaller(xprt));
fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :",
reg.pm_prog, reg.pm_vers,
reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr);
free(uaddr);
}
#endif
fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot);
if (fnd) {
char serveuaddr[32];
int h1, h2, h3, h4, p1, p2;
const char *netid, *ua;
if (reg.pm_prot == IPPROTO_UDP) {
ua = udp_uaddr;
netid = udptrans;
} else {
ua = tcp_uaddr; /* To get the len */
netid = tcptrans;
}
if (ua == NULL) {
goto sendreply;
}
if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3,
&h4, &p1, &p2) == 6) {
p1 = (fnd->pml_map.pm_port >> 8) & 0xff;
p2 = (fnd->pml_map.pm_port) & 0xff;
snprintf(serveuaddr, sizeof(serveuaddr),
"%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2);
if (is_bound(netid, serveuaddr)) {
port = fnd->pml_map.pm_port;
} else { /* this service is dead; delete it */
delete_prog(reg.pm_prog);
}
}
}
sendreply:
lport = port;
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) &&
debugging) {
(void) fprintf(stderr, "portmap: svc_sendreply\n");
if (doabort) {
rpcbind_abort();
}
}
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "port = %d\n", port);
#endif
rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers,
reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans,
port ? udptrans : "");
return (TRUE);
}
/* ARGSUSED */
static bool_t
pmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt)
{
if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) {
svcerr_decode(xprt);
return (FALSE);
}
if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) {
svcerr_weakauth(xprt);
return FALSE;
}
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr,
(caddr_t)&list_pml)) && debugging) {
if (debugging)
(void) fprintf(stderr, "portmap: svc_sendreply\n");
if (doabort) {
rpcbind_abort();
}
}
return (TRUE);
}
#endif /* PORTMAP */

View file

@ -1,206 +0,0 @@
/* $NetBSD: rpcb_stat.c,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* #pragma ident "@(#)rpcb_stat.c 1.7 94/04/25 SMI" */
/*
* rpcb_stat.c
* Allows for gathering of statistics
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <netconfig.h>
#include <rpc/rpc.h>
#include <rpc/rpcb_prot.h>
#include <sys/stat.h>
#ifdef PORTMAP
#include <rpc/pmap_prot.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "rpcbind.h"
static rpcb_stat_byvers inf;
void
rpcbs_init(void)
{
}
void
rpcbs_procinfo(rpcvers_t rtype, rpcproc_t proc)
{
switch (rtype + 2) {
#ifdef PORTMAP
case PMAPVERS: /* version 2 */
if (proc > rpcb_highproc_2)
return;
break;
#endif
case RPCBVERS: /* version 3 */
if (proc > rpcb_highproc_3)
return;
break;
case RPCBVERS4: /* version 4 */
if (proc > rpcb_highproc_4)
return;
break;
default: return;
}
inf[rtype].info[proc]++;
return;
}
void
rpcbs_set(rpcvers_t rtype, bool_t success)
{
if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
return;
inf[rtype].setinfo++;
return;
}
void
rpcbs_unset(rpcvers_t rtype, bool_t success)
{
if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
return;
inf[rtype].unsetinfo++;
return;
}
void
rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers,
const char *netid, const char *uaddr)
{
rpcbs_addrlist *al;
struct netconfig *nconf;
if (rtype >= RPCBVERS_STAT)
return;
for (al = inf[rtype].addrinfo; al; al = al->next) {
if(al->netid == NULL)
return;
if ((al->prog == prog) && (al->vers == vers) &&
(strcmp(al->netid, netid) == 0)) {
if ((uaddr == NULL) || (uaddr[0] == 0))
al->failure++;
else
al->success++;
return;
}
}
nconf = rpcbind_get_conf(netid);
if (nconf == NULL) {
return;
}
al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist));
if (al == NULL) {
return;
}
al->prog = prog;
al->vers = vers;
al->netid = nconf->nc_netid;
if ((uaddr == NULL) || (uaddr[0] == 0)) {
al->failure = 1;
al->success = 0;
} else {
al->failure = 0;
al->success = 1;
}
al->next = inf[rtype].addrinfo;
inf[rtype].addrinfo = al;
}
void
rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog,
rpcvers_t vers, rpcproc_t proc, char *netid, rpcblist_ptr rbl)
{
rpcbs_rmtcalllist *rl;
struct netconfig *nconf;
if (rtype >= RPCBVERS_STAT)
return;
for (rl = inf[rtype].rmtinfo; rl; rl = rl->next) {
if(rl->netid == NULL)
return;
if ((rl->prog == prog) && (rl->vers == vers) &&
(rl->proc == proc) &&
(strcmp(rl->netid, netid) == 0)) {
if ((rbl == NULL) ||
(rbl->rpcb_map.r_vers != vers))
rl->failure++;
else
rl->success++;
if (rpcbproc == RPCBPROC_INDIRECT)
rl->indirect++;
return;
}
}
nconf = rpcbind_get_conf(netid);
if (nconf == NULL) {
return;
}
rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist));
if (rl == NULL) {
return;
}
rl->prog = prog;
rl->vers = vers;
rl->proc = proc;
rl->netid = nconf->nc_netid;
if ((rbl == NULL) ||
(rbl->rpcb_map.r_vers != vers)) {
rl->failure = 1;
rl->success = 0;
} else {
rl->failure = 0;
rl->success = 1;
}
rl->indirect = 1;
rl->next = inf[rtype].rmtinfo;
inf[rtype].rmtinfo = rl;
return;
}
/*
*/
void *
rpcbproc_getstat(void *arg, struct svc_req *req, SVCXPRT *xprt,
rpcvers_t versnum)
{
return (void *)&inf;
}

View file

@ -1,232 +0,0 @@
/* $NetBSD: rpcb_svc.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)rpcb_svc.c 1.16 93/07/05 SMI" */
/*
* rpcb_svc.c
* The server procedure for the version 3 rpcbind (TLI).
*
* It maintains a separate list of all the registered services with the
* version 3 of rpcbind.
*/
#include <sys/types.h>
#include <rpc/rpc.h>
#include <rpc/rpcb_prot.h>
#include <netconfig.h>
#include <syslog.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rpcbind.h"
static void *rpcbproc_getaddr_3_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
static void *rpcbproc_dump_3_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
/*
* Called by svc_getreqset. There is a separate server handle for
* every transport that it waits on.
*/
void
rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
RPCB rpcbproc_set_3_arg;
RPCB rpcbproc_unset_3_arg;
RPCB rpcbproc_getaddr_3_local_arg;
struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
char *rpcbproc_uaddr2taddr_3_arg;
struct netbuf rpcbproc_taddr2uaddr_3_arg;
} argument;
char *result;
xdrproc_t xdr_argument, xdr_result;
void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
switch (rqstp->rq_proc) {
case NULLPROC:
/*
* Null proc call
*/
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_NULL\n");
#endif
/* This call just logs, no actual checks */
check_access(transp, rqstp->rq_proc, NULL, RPCBVERS);
(void) svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
return;
case RPCBPROC_SET:
xdr_argument = (xdrproc_t )xdr_rpcb;
xdr_result = (xdrproc_t )xdr_bool;
local = rpcbproc_set_com;
break;
case RPCBPROC_UNSET:
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_bool;
local = rpcbproc_unset_com;
break;
case RPCBPROC_GETADDR:
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_wrapstring;
local = rpcbproc_getaddr_3_local;
break;
case RPCBPROC_DUMP:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_DUMP\n");
#endif
xdr_argument = (xdrproc_t)xdr_void;
xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
local = rpcbproc_dump_3_local;
break;
case RPCBPROC_CALLIT:
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
return;
case RPCBPROC_GETTIME:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_GETTIME\n");
#endif
xdr_argument = (xdrproc_t)xdr_void;
xdr_result = (xdrproc_t)xdr_u_long;
local = rpcbproc_gettime_com;
break;
case RPCBPROC_UADDR2TADDR:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
#endif
xdr_argument = (xdrproc_t)xdr_wrapstring;
xdr_result = (xdrproc_t)xdr_netbuf;
local = rpcbproc_uaddr2taddr_com;
break;
case RPCBPROC_TADDR2UADDR:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
#endif
xdr_argument = (xdrproc_t)xdr_netbuf;
xdr_result = (xdrproc_t)xdr_wrapstring;
local = rpcbproc_taddr2uaddr_com;
break;
default:
svcerr_noproc(transp);
return;
}
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
(char *) &argument)) {
svcerr_decode(transp);
if (debugging)
(void) fprintf(stderr, "rpcbind: could not decode\n");
return;
}
if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS)) {
svcerr_weakauth(transp);
goto done;
}
result = (*local)(&argument, rqstp, transp, RPCBVERS);
if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
result)) {
svcerr_systemerr(transp);
if (debugging) {
(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
if (doabort) {
rpcbind_abort();
}
}
}
done:
if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
&argument)) {
if (debugging) {
(void) fprintf(stderr, "unable to free arguments\n");
if (doabort) {
rpcbind_abort();
}
}
}
}
/*
* Lookup the mapping for a program, version and return its
* address. Assuming that the caller wants the address of the
* server running on the transport on which the request came.
*
* We also try to resolve the universal address in terms of
* address of the caller.
*/
/* ARGSUSED */
static void *
rpcbproc_getaddr_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
rpcvers_t versnum)
{
RPCB *regp = (RPCB *)arg;
#ifdef RPCBIND_DEBUG
if (debugging) {
char *uaddr;
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
svc_getrpccaller(transp));
fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
regp->r_netid, uaddr);
free(uaddr);
}
#endif
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
RPCB_ALLVERS));
}
/* ARGSUSED */
static void *
rpcbproc_dump_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
rpcvers_t versnum)
{
return ((void *)&list_rbl);
}

View file

@ -1,455 +0,0 @@
/* $NetBSD: rpcb_svc_4.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)rpcb_svc_4.c 1.8 93/07/05 SMI" */
/*
* rpcb_svc_4.c
* The server procedure for the version 4 rpcbind.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <rpc/rpc.h>
#include <stdio.h>
#include <unistd.h>
#include <netconfig.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include "rpcbind.h"
static void *rpcbproc_getaddr_4_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
static void *rpcbproc_getversaddr_4_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
static void *rpcbproc_getaddrlist_4_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
static void free_rpcb_entry_list(rpcb_entry_list_ptr *);
static void *rpcbproc_dump_4_local(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
/*
* Called by svc_getreqset. There is a separate server handle for
* every transport that it waits on.
*/
void
rpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
rpcb rpcbproc_set_4_arg;
rpcb rpcbproc_unset_4_arg;
rpcb rpcbproc_getaddr_4_local_arg;
char *rpcbproc_uaddr2taddr_4_arg;
struct netbuf rpcbproc_taddr2uaddr_4_arg;
} argument;
char *result;
xdrproc_t xdr_argument, xdr_result;
void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc);
switch (rqstp->rq_proc) {
case NULLPROC:
/*
* Null proc call
*/
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_NULL\n");
#endif
check_access(transp, rqstp->rq_proc, NULL, RPCBVERS4);
(void) svc_sendreply(transp, (xdrproc_t) xdr_void, NULL);
return;
case RPCBPROC_SET:
/*
* Check to see whether the message came from
* loopback transports (for security reasons)
*/
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_bool;
local = rpcbproc_set_com;
break;
case RPCBPROC_UNSET:
/*
* Check to see whether the message came from
* loopback transports (for security reasons)
*/
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_bool;
local = rpcbproc_unset_com;
break;
case RPCBPROC_GETADDR:
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_wrapstring;
local = rpcbproc_getaddr_4_local;
break;
case RPCBPROC_GETVERSADDR:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_GETVERSADDR\n");
#endif
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_wrapstring;
local = rpcbproc_getversaddr_4_local;
break;
case RPCBPROC_DUMP:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_DUMP\n");
#endif
xdr_argument = (xdrproc_t)xdr_void;
xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
local = rpcbproc_dump_4_local;
break;
case RPCBPROC_INDIRECT:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_INDIRECT\n");
#endif
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
return;
/* case RPCBPROC_CALLIT: */
case RPCBPROC_BCAST:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_BCAST\n");
#endif
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
return;
case RPCBPROC_GETTIME:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_GETTIME\n");
#endif
xdr_argument = (xdrproc_t)xdr_void;
xdr_result = (xdrproc_t)xdr_u_long;
local = rpcbproc_gettime_com;
break;
case RPCBPROC_UADDR2TADDR:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
#endif
xdr_argument = (xdrproc_t)xdr_wrapstring;
xdr_result = (xdrproc_t)xdr_netbuf;
local = rpcbproc_uaddr2taddr_com;
break;
case RPCBPROC_TADDR2UADDR:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
#endif
xdr_argument = (xdrproc_t)xdr_netbuf;
xdr_result = (xdrproc_t)xdr_wrapstring;
local = rpcbproc_taddr2uaddr_com;
break;
case RPCBPROC_GETADDRLIST:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_GETADDRLIST\n");
#endif
xdr_argument = (xdrproc_t)xdr_rpcb;
xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr;
local = rpcbproc_getaddrlist_4_local;
break;
case RPCBPROC_GETSTAT:
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "RPCBPROC_GETSTAT\n");
#endif
xdr_argument = (xdrproc_t)xdr_void;
xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers;
local = rpcbproc_getstat;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
(char *)&argument)) {
svcerr_decode(transp);
if (debugging)
(void) fprintf(stderr, "rpcbind: could not decode\n");
return;
}
if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS4)) {
svcerr_weakauth(transp);
goto done;
}
result = (*local)(&argument, rqstp, transp, RPCBVERS4);
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result,
result)) {
svcerr_systemerr(transp);
if (debugging) {
(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
if (doabort) {
rpcbind_abort();
}
}
}
done:
if (!svc_freeargs(transp, (xdrproc_t) xdr_argument,
(char *)&argument)) {
if (debugging) {
(void) fprintf(stderr, "unable to free arguments\n");
if (doabort) {
rpcbind_abort();
}
}
}
return;
}
/*
* Lookup the mapping for a program, version and return its
* address. Assuming that the caller wants the address of the
* server running on the transport on which the request came.
* Even if a service with a different version number is available,
* it will return that address. The client should check with an
* clnt_call to verify whether the service is the one that is desired.
* We also try to resolve the universal address in terms of
* address of the caller.
*/
/* ARGSUSED */
static void *
rpcbproc_getaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
rpcvers_t rpcbversnum)
{
RPCB *regp = (RPCB *)arg;
#ifdef RPCBIND_DEBUG
if (debugging) {
char *uaddr;
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
svc_getrpccaller(transp));
fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
regp->r_netid, uaddr);
free(uaddr);
}
#endif
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
RPCB_ALLVERS));
}
/*
* Lookup the mapping for a program, version and return its
* address. Assuming that the caller wants the address of the
* server running on the transport on which the request came.
*
* We also try to resolve the universal address in terms of
* address of the caller.
*/
/* ARGSUSED */
static void *
rpcbproc_getversaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
rpcvers_t versnum)
{
RPCB *regp = (RPCB *)arg;
#ifdef RPCBIND_DEBUG
if (debugging) {
char *uaddr;
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
svc_getrpccaller(transp));
fprintf(stderr, "RPCB_GETVERSADDR rqst for (%lu, %lu, %s)"
" from %s : ",
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
regp->r_netid, uaddr);
free(uaddr);
}
#endif
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
RPCB_ONEVERS));
}
/*
* Lookup the mapping for a program, version and return the
* addresses for all transports in the current transport family.
* We return a merged address.
*/
/* ARGSUSED */
static void *
rpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
rpcvers_t versnum)
{
RPCB *regp = (RPCB *)arg;
static rpcb_entry_list_ptr rlist;
register rpcblist_ptr rbl;
rpcb_entry_list_ptr rp, tail = NULL;
rpcprog_t prog;
rpcvers_t vers;
rpcb_entry *a;
struct netconfig *nconf;
struct netconfig *reg_nconf;
char *saddr, *maddr = NULL;
free_rpcb_entry_list(&rlist);
prog = regp->r_prog;
vers = regp->r_vers;
reg_nconf = rpcbind_get_conf(transp->xp_netid);
if (reg_nconf == NULL)
return (NULL);
if (*(regp->r_addr) != '\0') {
saddr = regp->r_addr;
} else {
saddr = NULL;
}
#ifdef RPCBIND_DEBUG
if (debugging) {
fprintf(stderr, "r_addr: %s r_netid: %s nc_protofmly: %s\n",
regp->r_addr, regp->r_netid, reg_nconf->nc_protofmly);
}
#endif
for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
if ((rbl->rpcb_map.r_prog == prog) &&
(rbl->rpcb_map.r_vers == vers)) {
nconf = rpcbind_get_conf(rbl->rpcb_map.r_netid);
if (nconf == NULL)
goto fail;
if (strcmp(nconf->nc_protofmly, reg_nconf->nc_protofmly)
!= 0) {
continue; /* not same proto family */
}
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "\tmerge with: %s\n", rbl->rpcb_map.r_addr);
#endif
if ((maddr = mergeaddr(transp, rbl->rpcb_map.r_netid,
rbl->rpcb_map.r_addr, saddr)) == NULL) {
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, " FAILED\n");
#endif
continue;
} else if (!maddr[0]) {
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, " SUCCEEDED, but port died - maddr: nullstring\n");
#endif
/* The server died. Unset this combination */
delete_prog(regp->r_prog);
free(maddr);
continue;
}
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, " SUCCEEDED maddr: %s\n", maddr);
#endif
/*
* Add it to rlist.
*/
rp = (rpcb_entry_list_ptr)
malloc((u_int)sizeof (rpcb_entry_list));
if (rp == NULL) {
free(maddr);
goto fail;
}
a = &rp->rpcb_entry_map;
a->r_maddr = maddr;
a->r_nc_netid = nconf->nc_netid;
a->r_nc_semantics = nconf->nc_semantics;
a->r_nc_protofmly = nconf->nc_protofmly;
a->r_nc_proto = nconf->nc_proto;
rp->rpcb_entry_next = NULL;
if (rlist == NULL) {
rlist = rp;
tail = rp;
} else if (tail) {
tail->rpcb_entry_next = rp;
tail = rp;
}
rp = NULL;
}
}
#ifdef RPCBIND_DEBUG
if (debugging) {
for (rp = rlist; rp; rp = rp->rpcb_entry_next) {
fprintf(stderr, "\t%s %s\n", rp->rpcb_entry_map.r_maddr,
rp->rpcb_entry_map.r_nc_proto);
}
}
#endif
/*
* XXX: getaddrlist info is also being stuffed into getaddr.
* Perhaps wrong, but better than it not getting counted at all.
*/
rpcbs_getaddr(RPCBVERS4 - 2, prog, vers, transp->xp_netid, maddr);
return (void *)&rlist;
fail: free_rpcb_entry_list(&rlist);
return (NULL);
}
/*
* Free only the allocated structure, rest is all a pointer to some
* other data somewhere else.
*/
static void
free_rpcb_entry_list(rpcb_entry_list_ptr *rlistp)
{
register rpcb_entry_list_ptr rbl, tmp;
for (rbl = *rlistp; rbl != NULL; ) {
tmp = rbl;
rbl = rbl->rpcb_entry_next;
free((char *)tmp->rpcb_entry_map.r_maddr);
free((char *)tmp);
}
*rlistp = NULL;
}
/* ARGSUSED */
static void *
rpcbproc_dump_4_local(void *arg, struct svc_req *req, SVCXPRT *xprt,
rpcvers_t versnum)
{
return ((void *)&list_rbl);
}

File diff suppressed because it is too large Load diff

View file

@ -1,127 +0,0 @@
.\" $NetBSD: rpcbind.8,v 1.1 2010/07/26 15:53:00 pooka Exp $
.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4
.\" Copyright 1989 AT&T
.\" Copyright 1991 Sun Microsystems, Inc.
.Dd October 19, 2008
.Dt RPCBIND 8
.Sh NAME
.Nm rpcbind
.Nd universal addresses to RPC program number mapper
.Sh SYNOPSIS
.Nm
.Op Fl dilLs
.Sh DESCRIPTION
.Nm
is a server that converts
.Tn RPC
program numbers into
universal addresses.
It must be running on the host to be able to make
.Tn RPC
calls
on a server on that machine.
.Pp
When an
.Tn RPC
service is started,
it tells
.Nm
the address at which it is listening,
and the
.Tn RPC
program numbers it is prepared to serve.
When a client wishes to make an
.Tn RPC
call to a given program number,
it first contacts
.Nm
on the server machine to determine
the address where
.Tn RPC
requests should be sent.
.Pp
.Nm
should be started before any other RPC service.
Normally, standard
.Tn RPC
servers are started by port monitors, so
.Nm
must be started before port monitors are invoked.
.Pp
When
.Nm
is started, it checks that certain name-to-address
translation-calls function correctly.
If they fail, the network configuration databases may be corrupt.
Since
.Tn RPC
services cannot function correctly in this situation,
.Nm
reports the condition and terminates.
.Pp
.Nm
can only be started by the super-user.
.Pp
Access control is provided by
.Pa /etc/hosts.allow
and
.Pa /etc/hosts.deny ,
as described in
.Xr hosts_access 5
with daemon name
.Nm .
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl d
Run in debug mode.
In this mode,
.Nm
will not fork when it starts, will print additional information
during operation, and will abort on certain errors.
With this option, the name-to-address translation consistency
checks are shown in detail.
.It Fl i
.Dq insecure
mode.
Allows calls to SET and UNSET from any host.
Normally
.Nm
accepts these requests only from the loopback interface for security reasons.
This change is necessary for programs that were compiled with earlier
versions of the rpc library and do not make those requests using the
loopback interface.
.It Fl l
Turns on libwrap connection logging.
.It Fl s
Causes
.Nm
to change to the user daemon as soon as possible.
This causes
.Nm
to use non-privileged ports for outgoing connections, preventing non-privileged
clients from using
.Nm
to connect to services from a privileged port.
.It Fl L
Allow old-style local connections over the loopback interface.
Without this flag, local connections are only allowed over a local socket,
.Pa /var/run/rpcbind.sock
.El
.Sh NOTES
All RPC servers must be restarted if
.Nm
is restarted.
.Sh FILES
.Bl -tag -width "/var/run/rpcbind.sock" -compact
.It Pa /var/run/rpcbind.sock
.It Pa /etc/hosts.allow
explicit remote host access list.
.It Pa /etc/hosts.deny
explicit remote host denial of service list.
.El
.Sh SEE ALSO
.Xr rpcbind 3 ,
.Xr hosts_access 5 ,
.Xr hosts_options 5 ,
.Xr netconfig 5 ,
.Xr rpcinfo 8

View file

@ -1,613 +0,0 @@
/* $NetBSD: rpcbind.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)rpcbind.c 1.19 94/04/25 SMI" */
#if 0
#ifndef lint
static char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro";
#endif
#endif
/*
* rpcbind.c
* Implements the program, version to address mapping for rpc.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <rpc/rpc.h>
#ifdef PORTMAP
#include <netinet/in.h>
#endif
#include <netdb.h>
#include <stdio.h>
#include <netconfig.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <err.h>
#include <util.h>
#include <pwd.h>
#include <semaphore.h>
#include <string.h>
#include <errno.h>
#include "rpcbind.h"
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
/* Global variables */
int debugging = 1; /* Tell me what's going on */
int doabort = 0; /* When debugging, do an abort on errors */
rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
#include "svc_fdset.h"
/* who to suid to if -s is given */
#define RUN_AS "daemon"
int runasdaemon = 0;
int insecure = 0;
int oldstyle_local = 0;
int verboselog = 0;
#ifdef WARMSTART
/* Local Variable */
static int warmstart = 0; /* Grab a old copy of registrations */
#endif
#ifdef PORTMAP
struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
const char *udptrans; /* Name of UDP transport */
const char *tcptrans; /* Name of TCP transport */
const char *udp_uaddr; /* Universal UDP address */
const char *tcp_uaddr; /* Universal TCP address */
#endif
static const char servname[] = "sunrpc";
const char rpcbind_superuser[] = "superuser";
const char rpcbind_unknown[] = "unknown";
static int init_transport(struct netconfig *);
static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
struct netbuf *);
static void terminate(int);
#if 0
static void parseargs(int, char *[]);
#endif
int rpcbind_main(void *);
int
rpcbind_main(void *arg)
{
struct netconfig *nconf;
void *nc_handle; /* Net config handle */
struct rlimit rl;
int maxrec = RPC_MAXDATASIZE;
extern sem_t gensem;
#if 0
parseargs(argc, argv);
#endif
alloc_fdset();
getrlimit(RLIMIT_NOFILE, &rl);
if (rl.rlim_cur < 128) {
if (rl.rlim_max <= 128)
rl.rlim_cur = rl.rlim_max;
else
rl.rlim_cur = 128;
setrlimit(RLIMIT_NOFILE, &rl);
}
#if 0
if (geteuid()) /* This command allowed only to root */
errx(1, "Sorry. You are not superuser");
#endif
nc_handle = setnetconfig(); /* open netconfig file */
if (nc_handle == NULL)
errx(1, "could not read /etc/netconfig");
#ifdef PORTMAP
udptrans = "";
tcptrans = "";
#endif
nconf = getnetconfigent("local");
if (nconf == NULL)
errx(1, "can't find local transport");
rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
init_transport(nconf);
while ((nconf = getnetconfig(nc_handle))) {
if (nconf->nc_flag & NC_VISIBLE)
init_transport(nconf);
}
endnetconfig(nc_handle);
/* catch the usual termination signals for graceful exit */
(void) signal(SIGCHLD, reap);
(void) signal(SIGINT, terminate);
(void) signal(SIGTERM, terminate);
(void) signal(SIGQUIT, terminate);
/* ignore others that could get sent */
(void) signal(SIGPIPE, SIG_IGN);
//(void) signal(SIGHUP, SIG_IGN); used by mountd
(void) signal(SIGUSR1, SIG_IGN);
(void) signal(SIGUSR2, SIG_IGN);
#ifdef WARMSTART
if (warmstart) {
read_warmstart();
}
#endif
if (debugging) {
printf("rpcbind debugging enabled.");
if (doabort) {
printf(" Will abort on errors!\n");
} else {
printf("\n");
}
} else {
if (daemon(0, 0))
err(1, "fork failed");
}
openlog("rpcbind", 0, LOG_DAEMON);
pidfile(NULL);
if (runasdaemon) {
struct passwd *p;
if((p = getpwnam(RUN_AS)) == NULL) {
syslog(LOG_ERR, "cannot get uid of daemon: %m");
exit(1);
}
if (setuid(p->pw_uid) == -1) {
syslog(LOG_ERR, "setuid to daemon failed: %m");
exit(1);
}
}
network_init();
sem_post(&gensem);
my_svc_run();
syslog(LOG_ERR, "svc_run returned unexpectedly");
rpcbind_abort();
/* NOTREACHED */
return 0;
}
/*
* Adds the entry into the rpcbind database.
* If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
* Returns 0 if succeeds, else fails
*/
static int
init_transport(struct netconfig *nconf)
{
int fd;
struct t_bind taddr;
struct addrinfo hints, *res = NULL;
struct __rpc_sockinfo si;
SVCXPRT *my_xprt;
int aicode, status, addrlen;
struct sockaddr *sa;
struct sockaddr_un sun;
const int one = 1;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
return 1; /* not my type */
#ifdef RPCBIND_DEBUG
if (debugging) {
int i;
char **s;
(void)fprintf(stderr, "%s: %ld lookup routines :\n",
nconf->nc_netid, nconf->nc_nlookups);
for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
i++, s++)
(void)fprintf(stderr, "[%d] - %s\n", i, *s);
}
#endif
/*
* XXX - using RPC library internal functions.
*/
if ((fd = __rpc_nconf2fd(nconf)) < 0) {
if (errno == EAFNOSUPPORT)
return 1;
warn("Cannot create socket for `%s'", nconf->nc_netid);
return 1;
}
if (!__rpc_nconf2sockinfo(nconf, &si)) {
warnx("Cannot get information for `%s'", nconf->nc_netid);
return 1;
}
if (si.si_af == AF_INET6) {
/*
* We're doing host-based access checks here, so don't allow
* v4-in-v6 to confuse things.
*/
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one,
sizeof one) < 0) {
warn("Can't make socket ipv6 only");
return 1;
}
}
if (!strcmp(nconf->nc_netid, "local")) {
(void)memset(&sun, 0, sizeof sun);
sun.sun_family = AF_LOCAL;
(void)rump_sys_unlink(_PATH_RPCBINDSOCK);
(void)strlcpy(sun.sun_path, _PATH_RPCBINDSOCK,
sizeof(sun.sun_path));
sun.sun_len = SUN_LEN(&sun);
addrlen = sizeof(struct sockaddr_un);
sa = (struct sockaddr *)&sun;
} else {
/* Get rpcbind's address on this transport */
(void)memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = si.si_af;
hints.ai_socktype = si.si_socktype;
hints.ai_protocol = si.si_proto;
if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
warnx("Cannot get local address for `%s' (%s)",
nconf->nc_netid, gai_strerror(aicode));
return 1;
}
addrlen = res->ai_addrlen;
sa = (struct sockaddr *)res->ai_addr;
}
if (bind(fd, sa, addrlen) < 0) {
warn("Cannot bind `%s'", nconf->nc_netid);
if (res != NULL)
freeaddrinfo(res);
return 1;
}
#if 0
if (sa->sa_family == AF_LOCAL)
if (rump_sys_chmod(sun.sun_path, S_IRWXU|S_IRWXG|S_IRWXO) == -1)
warn("Cannot chmod `%s'", sun.sun_path);
#endif
/* Copy the address */
taddr.addr.len = taddr.addr.maxlen = addrlen;
taddr.addr.buf = malloc(addrlen);
if (taddr.addr.buf == NULL) {
warn("Cannot allocate memory for `%s' address",
nconf->nc_netid);
if (res != NULL)
freeaddrinfo(res);
return 1;
}
(void)memcpy(taddr.addr.buf, sa, addrlen);
#ifdef RPCBIND_DEBUG
if (debugging) {
/* for debugging print out our universal address */
char *uaddr;
struct netbuf nb;
nb.buf = sa;
nb.len = nb.maxlen = sa->sa_len;
uaddr = taddr2uaddr(nconf, &nb);
(void)fprintf(stderr, "rpcbind: my address is %s\n", uaddr);
(void)free(uaddr);
}
#endif
if (res != NULL)
freeaddrinfo(res);
if (nconf->nc_semantics != NC_TPI_CLTS)
listen(fd, SOMAXCONN);
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE,
RPC_MAXDATASIZE);
if (my_xprt == NULL) {
warnx("Could not create service for `%s'", nconf->nc_netid);
goto error;
}
#ifdef PORTMAP
/*
* Register both the versions for tcp/ip, udp/ip and local.
*/
if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
strcmp(nconf->nc_netid, "local") == 0) {
struct pmaplist *pml;
if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
pmap_service, 0)) {
warn("Could not register on `%s'", nconf->nc_netid);
goto error;
}
pml = malloc(sizeof (struct pmaplist));
if (pml == NULL) {
warn("Cannot allocate memory");
goto error;
}
pml->pml_map.pm_prog = PMAPPROG;
pml->pml_map.pm_vers = PMAPVERS;
pml->pml_map.pm_port = PMAPPORT;
if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
if (tcptrans[0]) {
warnx(
"Cannot have more than one TCP transport");
free(pml);
goto error;
}
tcptrans = strdup(nconf->nc_netid);
if (tcptrans == NULL) {
free(pml);
warn("Cannot allocate memory");
goto error;
}
pml->pml_map.pm_prot = IPPROTO_TCP;
/* Let's snarf the universal address */
/* "h1.h2.h3.h4.p1.p2" */
tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
if (udptrans[0]) {
free(pml);
warnx(
"Cannot have more than one UDP transport");
goto error;
}
udptrans = strdup(nconf->nc_netid);
if (udptrans == NULL) {
free(pml);
warn("Cannot allocate memory");
goto error;
}
pml->pml_map.pm_prot = IPPROTO_UDP;
/* Let's snarf the universal address */
/* "h1.h2.h3.h4.p1.p2" */
udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
}
pml->pml_next = list_pml;
list_pml = pml;
/* Add version 3 information */
pml = malloc(sizeof (struct pmaplist));
if (pml == NULL) {
warn("Cannot allocate memory");
goto error;
}
pml->pml_map = list_pml->pml_map;
pml->pml_map.pm_vers = RPCBVERS;
pml->pml_next = list_pml;
list_pml = pml;
/* Add version 4 information */
pml = malloc(sizeof (struct pmaplist));
if (pml == NULL) {
warn("Cannot allocate memory");
goto error;
}
pml->pml_map = list_pml->pml_map;
pml->pml_map.pm_vers = RPCBVERS4;
pml->pml_next = list_pml;
list_pml = pml;
/* Also add version 2 stuff to rpcbind list */
rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
}
#endif
/* version 3 registration */
if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
warn("Could not register %s version 3", nconf->nc_netid);
goto error;
}
rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
/* version 4 registration */
if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
warn("Could not register %s version 4", nconf->nc_netid);
goto error;
}
rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
/* decide if bound checking works for this transport */
status = add_bndlist(nconf, &taddr.addr);
#ifdef RPCBIND_DEBUG
if (debugging) {
if (status < 0) {
fprintf(stderr, "Error in finding bind status for %s\n",
nconf->nc_netid);
} else if (status == 0) {
fprintf(stderr, "check binding for %s\n",
nconf->nc_netid);
} else if (status > 0) {
fprintf(stderr, "No check binding for %s\n",
nconf->nc_netid);
}
}
#else
__USE(status);
#endif
/*
* rmtcall only supported on CLTS transports for now.
*/
if (nconf->nc_semantics == NC_TPI_CLTS) {
status = create_rmtcall_fd(nconf);
#ifdef RPCBIND_DEBUG
if (debugging) {
if (status < 0) {
fprintf(stderr,
"Could not create rmtcall fd for %s\n",
nconf->nc_netid);
} else {
fprintf(stderr, "rmtcall fd for %s is %d\n",
nconf->nc_netid, status);
}
}
#endif
}
return (0);
error:
(void)rump_sys_close(fd);
return (1);
}
static void
rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
struct netbuf *addr)
{
rpcblist_ptr rbl;
rbl = malloc(sizeof(rpcblist));
if (rbl == NULL) {
warn("Out of memory");
return;
}
rbl->rpcb_map.r_prog = prog;
rbl->rpcb_map.r_vers = vers;
rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
rbl->rpcb_map.r_owner = strdup(rpcbind_superuser);
rbl->rpcb_next = list_rbl; /* Attach to global list */
list_rbl = rbl;
}
/*
* Catch the signal and die
*/
static void
terminate(int dummy)
{
#ifdef WARMSTART
syslog(LOG_ERR,
"rpcbind terminating on signal. Restart with \"rpcbind -w\"");
write_warmstart(); /* Dump yourself */
#endif
exit(2);
}
void
rpcbind_abort()
{
#ifdef WARMSTART
write_warmstart(); /* Dump yourself */
#endif
abort();
}
#if 0
/* get command line options */
static void
parseargs(int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv, "dwailLs")) != -1) {
switch (c) {
case 'a':
doabort = 1; /* when debugging, do an abort on */
break; /* errors; for rpcbind developers */
/* only! */
case 'd':
debugging = 1;
break;
case 'i':
insecure = 1;
break;
case 'L':
oldstyle_local = 1;
break;
case 'l':
verboselog = 1;
break;
case 's':
runasdaemon = 1;
break;
#ifdef WARMSTART
case 'w':
warmstart = 1;
break;
#endif
default: /* error */
fprintf(stderr, "usage: rpcbind [-Idwils]\n");
exit (1);
}
}
if (doabort && !debugging) {
fprintf(stderr,
"-a (abort) specified without -d (debugging) -- ignored.\n");
doabort = 0;
}
}
#endif
void
reap(int dummy)
{
int save_errno = errno;
while (wait3(NULL, WNOHANG, NULL) > 0)
;
errno = save_errno;
}
void
toggle_verboselog(int dummy)
{
verboselog = !verboselog;
}

View file

@ -1,146 +0,0 @@
/* $NetBSD: rpcbind.h,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
*/
/* #ident "@(#)rpcbind.h 1.4 90/04/12 SMI" */
/*
* rpcbind.h
* The common header declarations
*/
#ifndef rpcbind_h
#define rpcbind_h
#ifdef PORTMAP
#include <rpc/pmap_prot.h>
#endif
#include <rpc/rpcb_prot.h>
/*
* Stuff for the rmtcall service
*/
struct encap_parms {
u_int32_t arglen;
char *args;
};
struct r_rmtcall_args {
u_int32_t rmt_prog;
u_int32_t rmt_vers;
u_int32_t rmt_proc;
int rmt_localvers; /* whether to send port # or uaddr */
char *rmt_uaddr;
struct encap_parms rmt_args;
};
extern int debugging;
extern int doabort;
extern int verboselog;
extern int insecure;
extern int oldstyle_local;
extern rpcblist_ptr list_rbl; /* A list of version 3 & 4 rpcbind services */
#ifdef PORTMAP
extern struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
extern const char *udptrans; /* Name of UDP transport */
extern const char *tcptrans; /* Name of TCP transport */
extern const char *udp_uaddr; /* Universal UDP address */
extern const char *tcp_uaddr; /* Universal TCP address */
#endif
extern const char rpcbind_superuser[];
extern const char rpcbind_unknown[];
int add_bndlist(struct netconfig *, struct netbuf *);
bool_t is_bound(const char *, const char *);
char *mergeaddr(SVCXPRT *, char *, char *, char *);
struct netconfig *rpcbind_get_conf(const char *);
void rpcbs_init(void);
void rpcbs_procinfo(rpcvers_t, rpcproc_t);
void rpcbs_set(rpcvers_t, bool_t);
void rpcbs_unset(rpcvers_t, bool_t);
void rpcbs_getaddr(rpcvers_t, rpcprog_t, rpcvers_t, const char *, const char *);
void rpcbs_rmtcall(rpcvers_t, rpcproc_t, rpcprog_t, rpcvers_t, rpcproc_t,
char *, rpcblist_ptr);
void *rpcbproc_getstat(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
void rpcb_service_3(struct svc_req *, SVCXPRT *);
void rpcb_service_4(struct svc_req *, SVCXPRT *);
/* Common functions shared between versions */
void *rpcbproc_set_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
void *rpcbproc_unset_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
bool_t map_set(RPCB *, char *);
bool_t map_unset(RPCB *, const char *);
void delete_prog(int);
void *rpcbproc_getaddr_com(RPCB *, struct svc_req *, SVCXPRT *, rpcvers_t,
rpcvers_t);
void *rpcbproc_gettime_com(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
void *rpcbproc_uaddr2taddr_com(void *, struct svc_req *,
SVCXPRT *, rpcvers_t);
void *rpcbproc_taddr2uaddr_com(void *, struct svc_req *, SVCXPRT *,
rpcvers_t);
int create_rmtcall_fd(struct netconfig *);
void rpcbproc_callit_com(struct svc_req *, SVCXPRT *, rpcvers_t,
rpcvers_t);
void my_svc_run(void);
void rpcbind_abort(void);
void reap(int);
void toggle_verboselog(int);
int check_access(SVCXPRT *, rpcproc_t, void *, int);
int check_callit(SVCXPRT *, struct r_rmtcall_args *, int);
void logit(int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *);
int is_loopback(struct netbuf *);
#ifdef PORTMAP
extern void pmap_service(struct svc_req *, SVCXPRT *);
#endif
void write_warmstart(void);
void read_warmstart(void);
char *addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
char *netid);
void network_init(void);
struct sockaddr *local_sa(int);
/* For different getaddr semantics */
#define RPCB_ALLVERS 0
#define RPCB_ONEVERS 1
#endif /* rpcbind_h */

View file

@ -1,282 +0,0 @@
/* $NetBSD: security.c,v 1.1 2010/07/26 15:53:01 pooka Exp $ */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/rpcb_prot.h>
#include <rpc/pmap_prot.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <syslog.h>
#include <netdb.h>
/*
* XXX for special case checks in check_callit.
*/
#include <rpcsvc/mount.h>
#include <rpcsvc/rquota.h>
#include <rpcsvc/nfs_prot.h>
#include <rpcsvc/yp.h>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/yppasswd.h>
#include "rpcbind.h"
#ifdef LIBWRAP
# include <tcpd.h>
#ifndef LIBWRAP_ALLOW_FACILITY
# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
#endif
#ifndef LIBWRAP_ALLOW_SEVERITY
# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
#endif
#ifndef LIBWRAP_DENY_FACILITY
# define LIBWRAP_DENY_FACILITY LOG_AUTH
#endif
#ifndef LIBWRAP_DENY_SEVERITY
# define LIBWRAP_DENY_SEVERITY LOG_WARNING
#endif
int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
#endif
#ifndef PORTMAP_LOG_FACILITY
# define PORTMAP_LOG_FACILITY LOG_AUTH
#endif
#ifndef PORTMAP_LOG_SEVERITY
# define PORTMAP_LOG_SEVERITY LOG_INFO
#endif
int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
extern int verboselog;
int
check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, int rpcbvers)
{
struct netbuf *caller = svc_getrpccaller(xprt);
struct sockaddr *addr = (struct sockaddr *)caller->buf;
#ifdef LIBWRAP
struct request_info req;
#endif
rpcprog_t prog = 0;
rpcb *rpcbp;
struct pmap *pmap;
/*
* The older PMAP_* equivalents have the same numbers, so
* they are accounted for here as well.
*/
switch (proc) {
case RPCBPROC_GETADDR:
case RPCBPROC_SET:
case RPCBPROC_UNSET:
if (rpcbvers > PMAPVERS) {
rpcbp = (rpcb *)args;
prog = rpcbp->r_prog;
} else {
pmap = (struct pmap *)args;
prog = pmap->pm_prog;
}
if (proc == RPCBPROC_GETADDR)
break;
if (!insecure && !is_loopback(caller)) {
if (verboselog)
logit(log_severity, addr, proc, prog,
" declined (non-loopback sender)");
return 0;
}
break;
case RPCBPROC_CALLIT:
case RPCBPROC_INDIRECT:
case RPCBPROC_DUMP:
case RPCBPROC_GETTIME:
case RPCBPROC_UADDR2TADDR:
case RPCBPROC_TADDR2UADDR:
case RPCBPROC_GETVERSADDR:
case RPCBPROC_GETADDRLIST:
case RPCBPROC_GETSTAT:
default:
break;
}
#ifdef LIBWRAP
if (addr->sa_family == AF_LOCAL)
return 1;
request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
sock_methods(&req);
if(!hosts_access(&req)) {
logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
return 0;
}
#endif
if (verboselog)
logit(log_severity, addr, proc, prog, "");
return 1;
}
int
is_loopback(struct netbuf *nbuf)
{
struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
struct sockaddr_in *sin;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
switch (addr->sa_family) {
case AF_INET:
if (!oldstyle_local)
return 0;
sin = (struct sockaddr_in *)addr;
return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
(ntohs(sin->sin_port) < IPPORT_RESERVED));
#ifdef INET6
case AF_INET6:
if (!oldstyle_local)
return 0;
sin6 = (struct sockaddr_in6 *)addr;
return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
(ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
#endif
case AF_LOCAL:
return 1;
default:
break;
}
return 0;
}
/* logit - report events of interest via the syslog daemon */
void
logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
const char *text)
{
const char *procname;
char procbuf[32];
char *progname;
char progbuf[32];
char fromname[NI_MAXHOST];
struct rpcent *rpc;
static const char *procmap[] = {
/* RPCBPROC_NULL */ "null",
/* RPCBPROC_SET */ "set",
/* RPCBPROC_UNSET */ "unset",
/* RPCBPROC_GETADDR */ "getport/addr",
/* RPCBPROC_DUMP */ "dump",
/* RPCBPROC_CALLIT */ "callit",
/* RPCBPROC_GETTIME */ "gettime",
/* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
/* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
/* RPCBPROC_GETVERSADDR */ "getversaddr",
/* RPCBPROC_INDIRECT */ "indirect",
/* RPCBPROC_GETADDRLIST */ "getaddrlist",
/* RPCBPROC_GETSTAT */ "getstat"
};
/*
* Fork off a process or the portmap daemon might hang while
* getrpcbynumber() or syslog() does its thing.
*/
if (fork() == 0) {
setproctitle("logit");
/* Try to map program number to name. */
if (prognum == 0) {
progname = __UNCONST("");
} else if ((rpc = getrpcbynumber((int) prognum))) {
progname = rpc->r_name;
} else {
snprintf(progname = progbuf, sizeof(progbuf), "%u",
(unsigned)prognum);
}
/* Try to map procedure number to name. */
if (procnum >= (sizeof procmap / sizeof (char *))) {
snprintf(procbuf, sizeof procbuf, "%u",
(unsigned)procnum);
procname = procbuf;
} else
procname = procmap[procnum];
/* Write syslog record. */
if (addr->sa_family == AF_LOCAL)
strlcpy(fromname, "local", sizeof(fromname));
else
getnameinfo(addr, addr->sa_len, fromname,
sizeof fromname, NULL, 0, NI_NUMERICHOST);
syslog(severity, "connect from %s to %s(%s)%s",
fromname, procname, progname, text);
_exit(0);
}
}
int
check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum)
{
struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
/*
* Always allow calling NULLPROC
*/
if (args->rmt_proc == 0)
return 1;
/*
* XXX - this special casing sucks.
*/
switch (args->rmt_prog) {
case RPCBPROG:
/*
* Allow indirect calls to ourselves in insecure mode.
* The is_loopback checks aren't useful then anyway.
*/
if (!insecure)
goto deny;
break;
case MOUNTPROG:
if (args->rmt_proc != MOUNTPROC_MNT &&
args->rmt_proc != MOUNTPROC_UMNT)
break;
goto deny;
case YPBINDPROG:
if (args->rmt_proc != YPBINDPROC_SETDOM)
break;
/* FALLTHROUGH */
case YPPASSWDPROG:
case NFS_PROGRAM:
case RQUOTAPROG:
goto deny;
case YPPROG:
switch (args->rmt_proc) {
case YPPROC_ALL:
case YPPROC_MATCH:
case YPPROC_FIRST:
case YPPROC_NEXT:
goto deny;
default:
break;
}
default:
break;
}
return 1;
deny:
logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
": indirect call not allowed");
return 0;
}

View file

@ -1,401 +0,0 @@
/* $NetBSD: util.c,v 1.2 2011/06/11 18:03:17 christos Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Frank van der Linden.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <net/if.h>
#include <netinet/in.h>
#include <assert.h>
#include <ifaddrs.h>
#include <poll.h>
#include <rpc/rpc.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <netconfig.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include "rpcbind.h"
static struct sockaddr_in *local_in4;
#ifdef INET6
static struct sockaddr_in6 *local_in6;
#endif
static int bitmaskcmp(void *, void *, void *, int);
#ifdef INET6
static void in6_fillscopeid(struct sockaddr_in6 *);
#endif
/*
* For all bits set in "mask", compare the corresponding bits in
* "dst" and "src", and see if they match.
*/
static int
bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
{
int i, j;
u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
u_int8_t bitmask;
for (i = 0; i < bytelen; i++) {
for (j = 0; j < 8; j++) {
bitmask = 1 << j;
if (!(netmask[i] & bitmask))
continue;
if ((p1[i] & bitmask) != (p2[i] & bitmask))
return 1;
}
}
return 0;
}
/*
* Taken from ifconfig.c
*/
#ifdef INET6
static void
in6_fillscopeid(struct sockaddr_in6 *sin6)
{
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
sin6->sin6_scope_id =
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
}
}
#endif
char *
addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
char *netid)
{
struct ifaddrs *ifap, *ifp, *bestif;
#ifdef INET6
struct sockaddr_in6 *servsin6, *sin6mask, *clntsin6, *ifsin6, *realsin6;
struct sockaddr_in6 *newsin6;
#endif
struct sockaddr_in *servsin, *sinmask, *clntsin, *newsin, *ifsin;
struct netbuf *serv_nbp, *clnt_nbp = NULL, tbuf;
struct sockaddr *serv_sa;
struct sockaddr *clnt_sa;
struct sockaddr_storage ss;
struct netconfig *nconf;
struct sockaddr *clnt = caller->buf;
char *ret = NULL;
#ifdef INET6
servsin6 = ifsin6 = newsin6 = NULL; /* XXXGCC -Wuninitialized */
#endif
servsin = newsin = NULL; /* XXXGCC -Wuninitialized */
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr,
clnt_uaddr, netid);
#endif
nconf = getnetconfigent(netid);
if (nconf == NULL)
return NULL;
/*
* Local merge, just return a duplicate.
*/
if (clnt_uaddr != NULL && strncmp(clnt_uaddr, "0.0.0.0.", 8) == 0)
return strdup(clnt_uaddr);
serv_nbp = uaddr2taddr(nconf, serv_uaddr);
if (serv_nbp == NULL)
return NULL;
serv_sa = (struct sockaddr *)serv_nbp->buf;
if (clnt_uaddr != NULL) {
clnt_nbp = uaddr2taddr(nconf, clnt_uaddr);
if (clnt_nbp == NULL) {
free(serv_nbp);
return NULL;
}
clnt_sa = (struct sockaddr *)clnt_nbp->buf;
if (clnt_sa->sa_family == AF_LOCAL) {
free(serv_nbp);
free(clnt_nbp);
free(clnt_sa);
return strdup(serv_uaddr);
}
} else {
clnt_sa = (struct sockaddr *)
malloc(sizeof (struct sockaddr_storage));
memcpy(clnt_sa, clnt, clnt->sa_len);
}
if (getifaddrs(&ifp) < 0) {
free(serv_nbp);
free(clnt_sa);
if (clnt_nbp != NULL)
free(clnt_nbp);
return 0;
}
/*
* Loop through all interfaces. For each interface, see if the
* network portion of its address is equal to that of the client.
* If so, we have found the interface that we want to use.
*/
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
if (ifap->ifa_addr->sa_family != clnt->sa_family ||
!(ifap->ifa_flags & IFF_UP))
continue;
switch (clnt->sa_family) {
case AF_INET:
/*
* realsin: address that recvfrom gave us.
* ifsin: address of interface being examined.
* clntsin: address that client want us to contact
* it on
* servsin: local address of RPC service.
* sinmask: netmask of this interface
* newsin: initially a copy of clntsin, eventually
* the merged address
*/
servsin = (struct sockaddr_in *)serv_sa;
clntsin = (struct sockaddr_in *)clnt_sa;
sinmask = (struct sockaddr_in *)ifap->ifa_netmask;
newsin = (struct sockaddr_in *)&ss;
ifsin = (struct sockaddr_in *)ifap->ifa_addr;
if (!bitmaskcmp(&ifsin->sin_addr, &clntsin->sin_addr,
&sinmask->sin_addr, sizeof (struct in_addr))) {
goto found;
}
break;
#ifdef INET6
case AF_INET6:
/*
* realsin6: address that recvfrom gave us.
* ifsin6: address of interface being examined.
* clntsin6: address that client want us to contact
* it on
* servsin6: local address of RPC service.
* sin6mask: netmask of this interface
* newsin6: initially a copy of clntsin, eventually
* the merged address
*
* For v6 link local addresses, if the client contacted
* us via a link-local address, and wants us to reply
* to one, use the scope id to see which one.
*/
realsin6 = (struct sockaddr_in6 *)clnt;
ifsin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
in6_fillscopeid(ifsin6);
clntsin6 = (struct sockaddr_in6 *)clnt_sa;
servsin6 = (struct sockaddr_in6 *)serv_sa;
sin6mask = (struct sockaddr_in6 *)ifap->ifa_netmask;
newsin6 = (struct sockaddr_in6 *)&ss;
if (IN6_IS_ADDR_LINKLOCAL(&ifsin6->sin6_addr) &&
IN6_IS_ADDR_LINKLOCAL(&realsin6->sin6_addr) &&
IN6_IS_ADDR_LINKLOCAL(&clntsin6->sin6_addr)) {
if (ifsin6->sin6_scope_id !=
realsin6->sin6_scope_id)
continue;
goto found;
}
if (!bitmaskcmp(&ifsin6->sin6_addr,
&clntsin6->sin6_addr, &sin6mask->sin6_addr,
sizeof (struct in6_addr)))
goto found;
break;
#endif
default:
goto freeit;
}
}
/*
* Didn't find anything. Get the first possibly useful interface,
* preferring "normal" interfaces to point-to-point and loopback
* ones.
*/
bestif = NULL;
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
if (ifap->ifa_addr->sa_family != clnt->sa_family ||
!(ifap->ifa_flags & IFF_UP))
continue;
if (!(ifap->ifa_flags & IFF_LOOPBACK) &&
!(ifap->ifa_flags & IFF_POINTOPOINT)) {
bestif = ifap;
break;
}
if (bestif == NULL)
bestif = ifap;
else if ((bestif->ifa_flags & IFF_LOOPBACK) &&
!(ifap->ifa_flags & IFF_LOOPBACK))
bestif = ifap;
}
ifap = bestif;
found:
switch (clnt->sa_family) {
case AF_INET:
memcpy(newsin, ifap->ifa_addr, clnt_sa->sa_len);
newsin->sin_port = servsin->sin_port;
tbuf.len = clnt_sa->sa_len;
tbuf.maxlen = sizeof (struct sockaddr_storage);
tbuf.buf = newsin;
break;
#ifdef INET6
case AF_INET6:
assert(newsin6);
memcpy(newsin6, ifsin6, clnt_sa->sa_len);
newsin6->sin6_port = servsin6->sin6_port;
tbuf.maxlen = sizeof (struct sockaddr_storage);
tbuf.len = clnt_sa->sa_len;
tbuf.buf = newsin6;
break;
#endif
default:
goto freeit;
}
if (ifap != NULL)
ret = taddr2uaddr(nconf, &tbuf);
freeit:
freenetconfigent(nconf);
free(serv_sa);
free(serv_nbp);
if (clnt_sa != NULL)
free(clnt_sa);
if (clnt_nbp != NULL)
free(clnt_nbp);
freeifaddrs(ifp);
#ifdef RPCBIND_DEBUG
if (debugging)
fprintf(stderr, "addrmerge: returning %s\n", ret);
#endif
return ret;
}
void
network_init()
{
#ifdef INET6
struct ifaddrs *ifap, *ifp;
struct ipv6_mreq mreq6;
int ifindex, s;
#endif
int ecode;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
if (debugging)
fprintf(stderr, "can't get local ip4 address: %s\n",
gai_strerror(ecode));
} else {
local_in4 = (struct sockaddr_in *)malloc(sizeof *local_in4);
if (local_in4 == NULL) {
if (debugging)
fprintf(stderr, "can't alloc local ip4 addr\n");
}
memcpy(local_in4, res->ai_addr, sizeof *local_in4);
}
#ifdef INET6
hints.ai_family = AF_INET6;
if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
if (debugging)
fprintf(stderr, "can't get local ip6 address: %s\n",
gai_strerror(ecode));
} else {
local_in6 = (struct sockaddr_in6 *)malloc(sizeof *local_in6);
if (local_in6 == NULL) {
if (debugging)
fprintf(stderr, "can't alloc local ip6 addr\n");
}
memcpy(local_in6, res->ai_addr, sizeof *local_in6);
}
/*
* Now join the RPC ipv6 multicast group on all interfaces.
*/
if (getifaddrs(&ifp) < 0)
return;
mreq6.ipv6mr_interface = 0;
inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, &mreq6.ipv6mr_multiaddr);
s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
/*
* Loop through all interfaces. For each interface, see if the
* network portion of its address is equal to that of the client.
* If so, we have found the interface that we want to use.
*/
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
if (ifap->ifa_addr->sa_family != AF_INET6 ||
!(ifap->ifa_flags & IFF_MULTICAST))
continue;
ifindex = if_nametoindex(ifap->ifa_name);
if (ifindex == mreq6.ipv6mr_interface)
/*
* Already did this one.
*/
continue;
mreq6.ipv6mr_interface = ifindex;
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
sizeof mreq6) < 0)
if (debugging)
warn("setsockopt v6 multicast");
}
#endif
/* close(s); */
}
struct sockaddr *
local_sa(int af)
{
switch (af) {
case AF_INET:
return (struct sockaddr *)local_in4;
#ifdef INET6
case AF_INET6:
return (struct sockaddr *)local_in6;
#endif
default:
return NULL;
}
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: rumpnfsd.c,v 1.8 2014/05/12 15:31:07 christos Exp $ */
/* $NetBSD: rumpnfsd.c,v 1.9 2015/11/08 02:45:16 christos Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -37,6 +37,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <rpc/rpc.h>
void *mountd_main(void *);
void *rpcbind_main(void *);
@ -87,7 +88,7 @@ main(int argc, char *argv[])
}
rump_init();
init_fdsets();
svc_fdset_init(SVC_FDSET_MT);
rv = rump_pub_etfs_register("/etc/exports", "./exports", RUMP_ETFS_REG);
if (rv) {

View file

@ -1,4 +1,4 @@
# $NetBSD: t_rquotad.sh,v 1.4 2014/03/13 12:45:14 gson Exp $
# $NetBSD: t_rquotad.sh,v 1.5 2016/08/10 23:25:39 kre Exp $
#
# Copyright (c) 2011 Manuel Bouyer
# All rights reserved.
@ -114,7 +114,7 @@ get_nfs_quota()
unset RUMPHIJACK
unset LD_PRELOAD
atf_check -s exit:0 rump_server -lrumpvfs -lrumpnet \
atf_check -s exit:0 rump_server -lrumpvfs -lrumpnet -lrumpdev \
-lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif -lrumpfs_nfs\
${RUMP_SERVER}

View file

@ -1,10 +1,11 @@
# $NetBSD: Makefile,v 1.4 2010/07/13 21:13:23 jmmv Exp $
# $NetBSD: Makefile,v 1.5 2016/01/23 21:22:48 christos Exp $
TESTSDIR= ${TESTSBASE}/fs/puffs/h_dtfs
ATFFILE= no
TESTS_C= h_dtfs
CPPFLAGS+= -D_KERNTYPES
SRCS.h_dtfs= dtfs.c dtfs_vfsops.c dtfs_vnops.c dtfs_subr.c
LDADD+= -lpuffs -lutil

View file

@ -1,4 +1,4 @@
# $NetBSD: t_vnd.sh,v 1.8 2011/04/21 22:26:46 haad Exp $
# $NetBSD: t_vnd.sh,v 1.9 2016/07/29 05:23:24 pgoyette Exp $
#
# Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
# All rights reserved.
@ -38,7 +38,7 @@ basic_body() {
atf_check -s eq:0 -o ignore -e ignore \
dd if=/dev/zero of=disk.img bs=1m count=10
atf_check -s eq:0 -o empty -e empty vnconfig /dev/vnd3 disk.img
atf_check -s eq:0 -o empty -e empty vndconfig /dev/vnd3 disk.img
atf_check -s eq:0 -o ignore -e ignore newfs /dev/rvnd3a
@ -58,7 +58,7 @@ basic_body() {
done
atf_check -s eq:0 -o empty -e empty umount mnt
atf_check -s eq:0 -o empty -e empty vnconfig -u /dev/vnd3
atf_check -s eq:0 -o empty -e empty vndconfig -u /dev/vnd3
test_unmount
touch done
@ -66,7 +66,7 @@ basic_body() {
basic_cleanup() {
if [ ! -f done ]; then
umount mnt 2>/dev/null 1>&2
vnconfig -u /dev/vnd3 2>/dev/null 1>&2
vndconfig -u /dev/vnd3 2>/dev/null 1>&2
fi
}

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.19 2013/06/28 13:04:06 reinoud Exp $
# $NetBSD: Makefile,v 1.20 2015/01/07 22:24:03 pooka Exp $
#
.include <bsd.own.mk>
@ -35,7 +35,8 @@ LDADD+=-L${VFSTESTDIR} -lvfstest
LDADD+=-lrumpfs_nfs # NFS
LDADD+=-lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net -lrumpnet
LDADD+=-lrumpvfs -lrump -lrumpuser -lpthread # base
LDADD+=-lrumpvfs -lrumpkern_sysproxy -lrump -lrumpuser # base
LDADD+=-lpthread
LDADD+=-lutil

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_io.c,v 1.12 2013/08/04 11:02:02 pooka Exp $ */
/* $NetBSD: t_io.c,v 1.16 2015/04/04 12:34:44 riastradh Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -222,6 +222,22 @@ wrrd_after_unlink(const atf_tc_t *tc, const char *mp)
FSTEST_EXIT();
}
static void
read_fault(const atf_tc_t *tc, const char *mp)
{
char ch = 123;
int fd;
FSTEST_ENTER();
RL(fd = rump_sys_open("file", O_CREAT | O_RDWR, 0777));
ATF_REQUIRE_EQ(rump_sys_write(fd, &ch, 1), 1);
RL(rump_sys_close(fd));
RL(fd = rump_sys_open("file", O_RDONLY | O_SYNC | O_RSYNC));
ATF_REQUIRE_ERRNO(EFAULT, rump_sys_read(fd, NULL, 1) == -1);
RL(rump_sys_close(fd));
FSTEST_EXIT();
}
ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole");
ATF_TC_FSAPPLY(extendfile, "check that extending a file works");
ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works "
@ -232,6 +248,7 @@ ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite");
ATF_TC_FSAPPLY(shrinkfile, "shrink file");
ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink");
ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink");
ATF_TC_FSAPPLY(read_fault, "read at bad address must return EFAULT");
ATF_TP_ADD_TCS(tp)
{
@ -245,6 +262,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_FSAPPLY(shrinkfile);
ATF_TP_FSAPPLY(read_after_unlink);
ATF_TP_FSAPPLY(wrrd_after_unlink);
ATF_TP_FSAPPLY(read_fault);
return atf_no_error();
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_renamerace.c,v 1.32 2014/07/29 09:15:48 gson Exp $ */
/* $NetBSD: t_renamerace.c,v 1.33 2016/05/04 08:30:22 dholland Exp $ */
/*
* Modified for rump and atf from a program supplied
@ -127,7 +127,7 @@ renamerace(const atf_tc_t *tc, const char *mp)
atf_tc_fail("race did not trigger this time");
if (FSTYPE_MSDOS(tc)) {
atf_tc_expect_fail("PR kern/44661");
atf_tc_expect_fail("PR kern/43626");
/*
* XXX: race does not trigger every time at least
* on amd64/qemu.

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_unpriv.c,v 1.11 2014/08/29 17:39:18 gson Exp $ */
/* $NetBSD: t_unpriv.c,v 1.12 2015/04/09 19:51:13 riastradh Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
@ -55,8 +55,6 @@ owner(const atf_tc_t *tc, const char *mp)
rump_pub_lwproc_rfork(RUMP_RFCFDG);
if (rump_sys_setuid(1) == -1)
atf_tc_fail_errno("setuid");
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be broken");
if (rump_sys_chown(".", 1, -1) != -1 || errno != EPERM)
atf_tc_fail_errno("chown");
if (rump_sys_chmod(".", 0000) != -1 || errno != EPERM)

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_vnops.c,v 1.43 2014/09/09 06:51:00 gson Exp $ */
/* $NetBSD: t_vnops.c,v 1.55 2016/01/28 10:10:09 martin Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -31,6 +31,7 @@
#include <assert.h>
#include <atf-c.h>
#include <ctype.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdlib.h>
@ -118,10 +119,10 @@ lookup_complex(const atf_tc_t *tc, const char *mountpath)
FIELD(st_uid);
FIELD(st_gid);
FIELD(st_rdev);
TIME(st_atim);
TIME(st_mtim);
TIME(st_ctim);
TIME(st_birthtim);
TIME(st_atimespec);
TIME(st_mtimespec);
TIME(st_ctimespec);
TIME(st_birthtimespec);
FIELD(st_size);
FIELD(st_blocks);
FIELD(st_flags);
@ -179,8 +180,6 @@ dir_notempty(const atf_tc_t *tc, const char *mountpath)
rump_sys_close(fd);
rv = rump_sys_rmdir(pb);
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be broken");
if (rv != -1 || errno != ENOTEMPTY)
atf_tc_fail("non-empty directory removed succesfully");
@ -276,8 +275,6 @@ rename_dir(const atf_tc_t *tc, const char *mp)
md(pb1, mp, "dir3/.");
if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL)
atf_tc_fail_errno("rename 2");
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be broken");
if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR)
atf_tc_fail_errno("rename 3");
@ -442,6 +439,78 @@ rename_reg_nodir(const atf_tc_t *tc, const char *mp)
rump_sys_chdir("/");
}
/* PR kern/50607 */
static void
create_many(const atf_tc_t *tc, const char *mp)
{
char buf[64];
int nfiles = 2324; /* #Nancy */
int i;
/* takes forever with many files */
if (FSTYPE_MSDOS(tc))
nfiles /= 4;
RL(rump_sys_chdir(mp));
if (FSTYPE_SYSVBFS(tc)) {
/* fs doesn't support many files or subdirectories */
nfiles = 5;
} else {
/* msdosfs doesn't like many entries in the root directory */
RL(rump_sys_mkdir("subdir", 0777));
RL(rump_sys_chdir("subdir"));
}
/* create them */
#define TESTFN "testfile"
for (i = 0; i < nfiles; i++) {
int fd;
sprintf(buf, TESTFN "%d", i);
RL(fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666));
RL(rump_sys_close(fd));
}
/* wipe them out */
for (i = 0; i < nfiles; i++) {
sprintf(buf, TESTFN "%d", i);
RL(rump_sys_unlink(buf));
}
#undef TESTFN
rump_sys_chdir("/");
}
/*
* Test creating files with one-character names using all possible
* character values. Failures to create the file are ignored as the
* characters allowed in file names vary by file system, but at least
* we can check that the fs does not crash, and if the file is
* successfully created, unlinking it should also succeed.
*/
static void
create_nonalphanum(const atf_tc_t *tc, const char *mp)
{
char buf[64];
int i;
RL(rump_sys_chdir(mp));
for (i = 0; i < 256; i++) {
int fd;
sprintf(buf, "%c", i);
fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666);
if (fd == -1)
continue;
RL(rump_sys_close(fd));
RL(rump_sys_unlink(buf));
}
printf("\n");
rump_sys_chdir("/");
}
static void
create_nametoolong(const atf_tc_t *tc, const char *mp)
{
@ -645,8 +714,6 @@ attrs(const atf_tc_t *tc, const char *mp)
RL(rump_sys_stat(TESTFILE, &sb2));
#define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a)
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be broken");
if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
CHECK(st_uid);
CHECK(st_gid);
@ -684,9 +751,6 @@ fcntl_lock(const atf_tc_t *tc, const char *mp)
RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
RL(rump_sys_ftruncate(fd, 8192));
/* PR kern/43321 */
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be broken");
RL(rump_sys_fcntl(fd, F_SETLK, &l));
/* Next, we fork and try to lock the same area */
@ -820,9 +884,6 @@ fcntl_getlock_pids(const atf_tc_t *tc, const char *mp)
RL(rump_sys_ftruncate(fd[i], sz));
if (FSTYPE_ZFS(tc))
atf_tc_expect_fail("PR kern/47656: Test known to be "
"broken");
if (i < __arraycount(lock)) {
RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
expect[i].l_pid = pid[i];
@ -932,9 +993,6 @@ lstat_symlink(const atf_tc_t *tc, const char *mp)
USES_SYMLINKS;
if (FSTYPE_V7FS(tc))
atf_tc_expect_fail("PR kern/48864");
FSTEST_ENTER();
src = "source";
@ -973,6 +1031,11 @@ ATF_TC_FSAPPLY(access_simple, "access(2)");
ATF_TC_FSAPPLY(read_directory, "read(2) on directories");
ATF_TC_FSAPPLY(lstat_symlink, "lstat(2) values for symbolic links");
#undef FSTEST_IMGSIZE
#define FSTEST_IMGSIZE (1024*1024*64)
ATF_TC_FSAPPLY(create_many, "create many directory entries");
ATF_TC_FSAPPLY(create_nonalphanum, "non-alphanumeric filenames");
ATF_TP_ADD_TCS(tp)
{
@ -984,6 +1047,8 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_FSAPPLY(rename_dir);
ATF_TP_FSAPPLY(rename_dotdot);
ATF_TP_FSAPPLY(rename_reg_nodir);
ATF_TP_FSAPPLY(create_many);
ATF_TP_FSAPPLY(create_nonalphanum);
ATF_TP_FSAPPLY(create_nametoolong);
ATF_TP_FSAPPLY(create_exist);
ATF_TP_FSAPPLY(rename_nametoolong);

View file

@ -1,4 +1,4 @@
# $NetBSD: t_factor.sh,v 1.7 2010/11/19 12:31:36 pgoyette Exp $
# $NetBSD: t_factor.sh,v 1.9 2016/06/27 05:29:32 pgoyette Exp $
#
# Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
# All rights reserved.
@ -27,32 +27,55 @@
expect() {
echo "${2}" >expout
ncrypt=$( ldd /usr/games/factor | grep -c -- -lcrypt )
if [ "X$3" != "X" -a $ncrypt -eq 0 ] ; then
atf_skip "crypto needed for huge non-prime factors - PR bin/23663"
fi
atf_check -s eq:0 -o file:expout -e empty /usr/games/factor ${1}
}
atf_test_case overflow
overflow_head() {
atf_test_case overflow1
overflow1_head() {
atf_set "descr" "Tests for overflow conditions"
atf_set "require.progs" "/usr/games/factor"
}
overflow_body() {
overflow1_body() {
expect '8675309' '8675309: 8675309'
}
atf_test_case overflow2
overflow2_head() {
atf_set "descr" "Tests for overflow conditions"
atf_set "require.progs" "/usr/games/factor"
}
overflow2_body() {
expect '6172538568' '6172538568: 2 2 2 3 7 17 2161253'
}
atf_test_case loop
loop_head() {
atf_test_case loop1
loop1_head() {
atf_set "descr" "Tests some cases that once locked the program" \
"in an infinite loop"
atf_set "require.progs" "/usr/games/factor"
}
loop_body() {
expect '99999999999991' '99999999999991: 7 13 769231 1428571'
loop1_body() {
expect '2147483647111311' '2147483647111311: 3 3 3 131 607148331103'
}
atf_test_case loop2
loop2_head() {
atf_set "descr" "Tests some cases that once locked the program" \
"in an infinite loop"
atf_set "require.progs" "/usr/games/factor"
}
loop2_body() {
expect '99999999999991' '99999999999991: 7 13 769231 1428571' Need_Crypto
}
atf_init_test_cases()
{
atf_add_test_case overflow
atf_add_test_case loop
atf_add_test_case overflow1
atf_add_test_case overflow2
atf_add_test_case loop1
atf_add_test_case loop2
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: h_macros.h,v 1.9 2013/05/17 15:42:09 christos Exp $ */
/* $NetBSD: h_macros.h,v 1.12 2016/08/04 11:49:07 jakllsch Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -51,7 +51,7 @@ do { \
ATF_REQUIRE_MSG(RZ_rv == 0, "%s: %s", #x, strerror(RZ_rv)); \
} while (/*CONSTCOND*/0)
static __inline __printflike(1, 2) void
__dead static __inline __printflike(1, 2) void
atf_tc_fail_errno(const char *fmt, ...)
{
va_list ap;
@ -75,7 +75,7 @@ tests_makegarbage(void *space, size_t len)
uint16_t randval;
while (len >= sizeof(randval)) {
*sb++ = (random() & 0xffff);
*sb++ = (uint16_t)random();
len -= sizeof(*sb);
}
randval = (uint16_t)random();

View file

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.7 2012/08/08 13:57:06 christos Exp $
# $NetBSD: Makefile,v 1.12 2016/08/08 14:11:08 pgoyette Exp $
NOMAN= # defined
@ -6,14 +6,21 @@ NOMAN= # defined
TESTSDIR= ${TESTSBASE}/include/sys
TESTS_C= t_bitops t_bootblock t_cdefs t_tree t_types
TESTS_C+= t_bitops
TESTS_C+= t_bootblock
TESTS_C+= t_cdefs
TESTS_C+= t_pslist
TESTS_C+= t_tree
TESTS_C+= t_types
CPPFLAGS.t_pslist.c+= -I${NETBSDSRCDIR}/sys
LDADD.t_bitops+= -lm
.if (${MKRUMP} != "no")
.if (${MKRUMP} != "no") && !defined(BSD_MK_COMPAT_FILE)
TESTS_C+= t_socket
CPPFLAGS.t_socket.c+= -D_KERNTYPES
LDADD.t_socket+= -lrumpnet_local -lrumpnet_net -lrumpnet
LDADD.t_socket+= -lrumpvfs -lrump -lrumpuser -lpthread
LDADD.t_socket+= -lrumpvfs -lrump -lrumpuser -lpthread -lrumpdev
.endif
.include <bsd.test.mk>

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_bitops.c,v 1.16 2012/12/07 02:28:19 christos Exp $ */
/* $NetBSD: t_bitops.c,v 1.19 2015/03/21 05:50:19 isaki Exp $ */
/*-
* Copyright (c) 2011, 2012 The NetBSD Foundation, Inc.
@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_bitops.c,v 1.16 2012/12/07 02:28:19 christos Exp $");
__RCSID("$NetBSD: t_bitops.c,v 1.19 2015/03/21 05:50:19 isaki Exp $");
#include <atf-c.h>
@ -67,7 +67,7 @@ static const struct {
ATF_TC(bitmap_basic);
ATF_TC_HEAD(bitmap_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of __BITMAP_*");
atf_tc_set_md_var(tc, "descr", "A basic test of __BITMAP_*");
}
ATF_TC_BODY(bitmap_basic, tc)
@ -174,65 +174,191 @@ ATF_TC_BODY(ffsfls, tc)
}
}
ATF_TC(ilog2_basic);
ATF_TC_HEAD(ilog2_basic, tc)
ATF_TC(ilog2_32bit);
ATF_TC_HEAD(ilog2_32bit, tc)
{
atf_tc_set_md_var(tc, "descr", "Test ilog2(3) for correctness");
atf_tc_set_md_var(tc, "descr", "Test ilog2(3) for 32bit variable");
}
ATF_TC_BODY(ilog2_basic, tc)
ATF_TC_BODY(ilog2_32bit, tc)
{
uint64_t i, x;
int i;
uint32_t x;
for (i = x = 0; i < 64; i++) {
x = (uint64_t)1 << i;
ATF_REQUIRE(i == (uint64_t)ilog2(x));
for (i = 0; i < 32; i++) {
x = 1 << i;
ATF_REQUIRE(ilog2(x) == i);
}
}
ATF_TC(ilog2_log2);
ATF_TC_HEAD(ilog2_log2, tc)
ATF_TC(ilog2_64bit);
ATF_TC_HEAD(ilog2_64bit, tc)
{
atf_tc_set_md_var(tc, "descr", "Test log2(3) vs. ilog2(3)");
atf_tc_set_md_var(tc, "descr", "Test ilog2(3) for 64bit variable");
}
ATF_TC_BODY(ilog2_log2, tc)
ATF_TC_BODY(ilog2_64bit, tc)
{
#ifdef __vax__
atf_tc_skip("Test is unavailable on vax because of lack of log2()");
#else
double x, y;
uint64_t i;
int i;
uint64_t x;
for (i = 0; i < 64; i++) {
x = ((uint64_t)1) << i;
ATF_REQUIRE(ilog2(x) == i);
}
}
ATF_TC(ilog2_const);
ATF_TC_HEAD(ilog2_const, tc)
{
atf_tc_set_md_var(tc, "descr", "Test ilog2(3) for constant");
}
ATF_TC_BODY(ilog2_const, tc)
{
/*
* This may fail under QEMU; see PR misc/44767.
* These inlines test __builtin_constant_p() part of ilog2()
* at compile time, so don't change it to loop. PR lib/49745
*/
for (i = 1; i < UINT32_MAX; i += UINT16_MAX) {
ATF_REQUIRE(ilog2(0x0000000000000001ULL) == 0);
ATF_REQUIRE(ilog2(0x0000000000000002ULL) == 1);
ATF_REQUIRE(ilog2(0x0000000000000004ULL) == 2);
ATF_REQUIRE(ilog2(0x0000000000000008ULL) == 3);
ATF_REQUIRE(ilog2(0x0000000000000010ULL) == 4);
ATF_REQUIRE(ilog2(0x0000000000000020ULL) == 5);
ATF_REQUIRE(ilog2(0x0000000000000040ULL) == 6);
ATF_REQUIRE(ilog2(0x0000000000000080ULL) == 7);
ATF_REQUIRE(ilog2(0x0000000000000100ULL) == 8);
ATF_REQUIRE(ilog2(0x0000000000000200ULL) == 9);
ATF_REQUIRE(ilog2(0x0000000000000400ULL) == 10);
ATF_REQUIRE(ilog2(0x0000000000000800ULL) == 11);
ATF_REQUIRE(ilog2(0x0000000000001000ULL) == 12);
ATF_REQUIRE(ilog2(0x0000000000002000ULL) == 13);
ATF_REQUIRE(ilog2(0x0000000000004000ULL) == 14);
ATF_REQUIRE(ilog2(0x0000000000008000ULL) == 15);
ATF_REQUIRE(ilog2(0x0000000000010000ULL) == 16);
ATF_REQUIRE(ilog2(0x0000000000020000ULL) == 17);
ATF_REQUIRE(ilog2(0x0000000000040000ULL) == 18);
ATF_REQUIRE(ilog2(0x0000000000080000ULL) == 19);
ATF_REQUIRE(ilog2(0x0000000000100000ULL) == 20);
ATF_REQUIRE(ilog2(0x0000000000200000ULL) == 21);
ATF_REQUIRE(ilog2(0x0000000000400000ULL) == 22);
ATF_REQUIRE(ilog2(0x0000000000800000ULL) == 23);
ATF_REQUIRE(ilog2(0x0000000001000000ULL) == 24);
ATF_REQUIRE(ilog2(0x0000000002000000ULL) == 25);
ATF_REQUIRE(ilog2(0x0000000004000000ULL) == 26);
ATF_REQUIRE(ilog2(0x0000000008000000ULL) == 27);
ATF_REQUIRE(ilog2(0x0000000010000000ULL) == 28);
ATF_REQUIRE(ilog2(0x0000000020000000ULL) == 29);
ATF_REQUIRE(ilog2(0x0000000040000000ULL) == 30);
ATF_REQUIRE(ilog2(0x0000000080000000ULL) == 31);
ATF_REQUIRE(ilog2(0x0000000100000000ULL) == 32);
ATF_REQUIRE(ilog2(0x0000000200000000ULL) == 33);
ATF_REQUIRE(ilog2(0x0000000400000000ULL) == 34);
ATF_REQUIRE(ilog2(0x0000000800000000ULL) == 35);
ATF_REQUIRE(ilog2(0x0000001000000000ULL) == 36);
ATF_REQUIRE(ilog2(0x0000002000000000ULL) == 37);
ATF_REQUIRE(ilog2(0x0000004000000000ULL) == 38);
ATF_REQUIRE(ilog2(0x0000008000000000ULL) == 39);
ATF_REQUIRE(ilog2(0x0000010000000000ULL) == 40);
ATF_REQUIRE(ilog2(0x0000020000000000ULL) == 41);
ATF_REQUIRE(ilog2(0x0000040000000000ULL) == 42);
ATF_REQUIRE(ilog2(0x0000080000000000ULL) == 43);
ATF_REQUIRE(ilog2(0x0000100000000000ULL) == 44);
ATF_REQUIRE(ilog2(0x0000200000000000ULL) == 45);
ATF_REQUIRE(ilog2(0x0000400000000000ULL) == 46);
ATF_REQUIRE(ilog2(0x0000800000000000ULL) == 47);
ATF_REQUIRE(ilog2(0x0001000000000000ULL) == 48);
ATF_REQUIRE(ilog2(0x0002000000000000ULL) == 49);
ATF_REQUIRE(ilog2(0x0004000000000000ULL) == 50);
ATF_REQUIRE(ilog2(0x0008000000000000ULL) == 51);
ATF_REQUIRE(ilog2(0x0010000000000000ULL) == 52);
ATF_REQUIRE(ilog2(0x0020000000000000ULL) == 53);
ATF_REQUIRE(ilog2(0x0040000000000000ULL) == 54);
ATF_REQUIRE(ilog2(0x0080000000000000ULL) == 55);
ATF_REQUIRE(ilog2(0x0100000000000000ULL) == 56);
ATF_REQUIRE(ilog2(0x0200000000000000ULL) == 57);
ATF_REQUIRE(ilog2(0x0400000000000000ULL) == 58);
ATF_REQUIRE(ilog2(0x0800000000000000ULL) == 59);
ATF_REQUIRE(ilog2(0x1000000000000000ULL) == 60);
ATF_REQUIRE(ilog2(0x2000000000000000ULL) == 61);
ATF_REQUIRE(ilog2(0x4000000000000000ULL) == 62);
ATF_REQUIRE(ilog2(0x8000000000000000ULL) == 63);
x = log2(i);
y = (double)(ilog2(i));
ATF_REQUIRE(ceil(x) >= y);
if (fabs(floor(x) - y) > 1.0e-40) {
atf_tc_expect_fail("PR misc/44767");
atf_tc_fail("log2(%"PRIu64") != "
"ilog2(%"PRIu64")", i, i);
}
}
#endif
ATF_REQUIRE(ilog2(0x0000000000000003ULL) == 1);
ATF_REQUIRE(ilog2(0x0000000000000007ULL) == 2);
ATF_REQUIRE(ilog2(0x000000000000000fULL) == 3);
ATF_REQUIRE(ilog2(0x000000000000001fULL) == 4);
ATF_REQUIRE(ilog2(0x000000000000003fULL) == 5);
ATF_REQUIRE(ilog2(0x000000000000007fULL) == 6);
ATF_REQUIRE(ilog2(0x00000000000000ffULL) == 7);
ATF_REQUIRE(ilog2(0x00000000000001ffULL) == 8);
ATF_REQUIRE(ilog2(0x00000000000003ffULL) == 9);
ATF_REQUIRE(ilog2(0x00000000000007ffULL) == 10);
ATF_REQUIRE(ilog2(0x0000000000000fffULL) == 11);
ATF_REQUIRE(ilog2(0x0000000000001fffULL) == 12);
ATF_REQUIRE(ilog2(0x0000000000003fffULL) == 13);
ATF_REQUIRE(ilog2(0x0000000000007fffULL) == 14);
ATF_REQUIRE(ilog2(0x000000000000ffffULL) == 15);
ATF_REQUIRE(ilog2(0x000000000001ffffULL) == 16);
ATF_REQUIRE(ilog2(0x000000000003ffffULL) == 17);
ATF_REQUIRE(ilog2(0x000000000007ffffULL) == 18);
ATF_REQUIRE(ilog2(0x00000000000fffffULL) == 19);
ATF_REQUIRE(ilog2(0x00000000001fffffULL) == 20);
ATF_REQUIRE(ilog2(0x00000000003fffffULL) == 21);
ATF_REQUIRE(ilog2(0x00000000007fffffULL) == 22);
ATF_REQUIRE(ilog2(0x0000000000ffffffULL) == 23);
ATF_REQUIRE(ilog2(0x0000000001ffffffULL) == 24);
ATF_REQUIRE(ilog2(0x0000000003ffffffULL) == 25);
ATF_REQUIRE(ilog2(0x0000000007ffffffULL) == 26);
ATF_REQUIRE(ilog2(0x000000000fffffffULL) == 27);
ATF_REQUIRE(ilog2(0x000000001fffffffULL) == 28);
ATF_REQUIRE(ilog2(0x000000003fffffffULL) == 29);
ATF_REQUIRE(ilog2(0x000000007fffffffULL) == 30);
ATF_REQUIRE(ilog2(0x00000000ffffffffULL) == 31);
ATF_REQUIRE(ilog2(0x00000001ffffffffULL) == 32);
ATF_REQUIRE(ilog2(0x00000003ffffffffULL) == 33);
ATF_REQUIRE(ilog2(0x00000007ffffffffULL) == 34);
ATF_REQUIRE(ilog2(0x0000000fffffffffULL) == 35);
ATF_REQUIRE(ilog2(0x0000001fffffffffULL) == 36);
ATF_REQUIRE(ilog2(0x0000003fffffffffULL) == 37);
ATF_REQUIRE(ilog2(0x0000007fffffffffULL) == 38);
ATF_REQUIRE(ilog2(0x000000ffffffffffULL) == 39);
ATF_REQUIRE(ilog2(0x000001ffffffffffULL) == 40);
ATF_REQUIRE(ilog2(0x000003ffffffffffULL) == 41);
ATF_REQUIRE(ilog2(0x000007ffffffffffULL) == 42);
ATF_REQUIRE(ilog2(0x00000fffffffffffULL) == 43);
ATF_REQUIRE(ilog2(0x00001fffffffffffULL) == 44);
ATF_REQUIRE(ilog2(0x00003fffffffffffULL) == 45);
ATF_REQUIRE(ilog2(0x00007fffffffffffULL) == 46);
ATF_REQUIRE(ilog2(0x0000ffffffffffffULL) == 47);
ATF_REQUIRE(ilog2(0x0001ffffffffffffULL) == 48);
ATF_REQUIRE(ilog2(0x0003ffffffffffffULL) == 49);
ATF_REQUIRE(ilog2(0x0007ffffffffffffULL) == 50);
ATF_REQUIRE(ilog2(0x000fffffffffffffULL) == 51);
ATF_REQUIRE(ilog2(0x001fffffffffffffULL) == 52);
ATF_REQUIRE(ilog2(0x003fffffffffffffULL) == 53);
ATF_REQUIRE(ilog2(0x007fffffffffffffULL) == 54);
ATF_REQUIRE(ilog2(0x00ffffffffffffffULL) == 55);
ATF_REQUIRE(ilog2(0x01ffffffffffffffULL) == 56);
ATF_REQUIRE(ilog2(0x03ffffffffffffffULL) == 57);
ATF_REQUIRE(ilog2(0x07ffffffffffffffULL) == 58);
ATF_REQUIRE(ilog2(0x0fffffffffffffffULL) == 59);
ATF_REQUIRE(ilog2(0x1fffffffffffffffULL) == 60);
ATF_REQUIRE(ilog2(0x3fffffffffffffffULL) == 61);
ATF_REQUIRE(ilog2(0x7fffffffffffffffULL) == 62);
ATF_REQUIRE(ilog2(0xffffffffffffffffULL) == 63);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, bitmap_basic);
ATF_TP_ADD_TC(tp, bitmap_basic);
ATF_TP_ADD_TC(tp, fast_divide32);
ATF_TP_ADD_TC(tp, ffsfls);
ATF_TP_ADD_TC(tp, ilog2_basic);
ATF_TP_ADD_TC(tp, ilog2_log2);
ATF_TP_ADD_TC(tp, ilog2_32bit);
ATF_TP_ADD_TC(tp, ilog2_64bit);
ATF_TP_ADD_TC(tp, ilog2_const);
return atf_no_error();
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_cdefs.c,v 1.3 2013/09/05 09:01:27 gsutre Exp $ */
/* $NetBSD: t_cdefs.c,v 1.4 2016/03/16 07:21:36 mrg Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@ -32,7 +32,7 @@
#include <sys/cdefs.h>
__COPYRIGHT("@(#) Copyright (c) 2008\
The NetBSD Foundation, inc. All rights reserved.");
__RCSID("$NetBSD: t_cdefs.c,v 1.3 2013/09/05 09:01:27 gsutre Exp $");
__RCSID("$NetBSD: t_cdefs.c,v 1.4 2016/03/16 07:21:36 mrg Exp $");
#include <atf-c.h>
#include <sys/types.h>
@ -180,34 +180,34 @@ ATF_TC_HEAD(stypefit, tc)
ATF_TC_BODY(stypefit, tc)
{
#define CHECK(a, b, c) ATF_REQUIRE(!__type_fit(a, b) == c)
#define CHECK(a, b, c) ATF_REQUIRE(__type_fit(a, b) == c)
CHECK(signed char, -1, 0);
CHECK(signed char, 1, 0);
CHECK(signed char, 0x7f, 0);
CHECK(signed char, 0x80, 1);
CHECK(signed char, 0xff, 1);
CHECK(signed char, 0x1ff, 1);
CHECK(signed char, -1, 1);
CHECK(signed char, 1, 1);
CHECK(signed char, 0x7f, 1);
CHECK(signed char, 0x80, 0);
CHECK(signed char, 0xff, 0);
CHECK(signed char, 0x1ff, 0);
CHECK(signed short, -1, 0);
CHECK(signed short, 1, 0);
CHECK(signed short, 0x7fff, 0);
CHECK(signed short, 0x8000, 1);
CHECK(signed short, 0xffff, 1);
CHECK(signed short, 0x1ffff, 1);
CHECK(signed short, -1, 1);
CHECK(signed short, 1, 1);
CHECK(signed short, 0x7fff, 1);
CHECK(signed short, 0x8000, 0);
CHECK(signed short, 0xffff, 0);
CHECK(signed short, 0x1ffff, 0);
CHECK(signed int, -1, 0);
CHECK(signed int, 1, 0);
CHECK(signed int, 0x7fffffff, 0);
CHECK(signed int, 0x80000000, 1);
CHECK(signed int, 0xffffffff, 1);
CHECK(signed int, 0x1ffffffffLL, 1);
CHECK(signed int, -1, 1);
CHECK(signed int, 1, 1);
CHECK(signed int, 0x7fffffff, 1);
CHECK(signed int, 0x80000000, 0);
CHECK(signed int, 0xffffffff, 0);
CHECK(signed int, 0x1ffffffffLL, 0);
CHECK(signed long long, -1, 0);
CHECK(signed long long, 1, 0);
CHECK(signed long long, 0x7fffffffffffffffLL, 0);
CHECK(signed long long, 0x8000000000000000LL, 1);
CHECK(signed long long, 0xffffffffffffffffLL, 1);
CHECK(signed long long, -1, 1);
CHECK(signed long long, 1, 1);
CHECK(signed long long, 0x7fffffffffffffffLL, 1);
CHECK(signed long long, 0x8000000000000000LL, 0);
CHECK(signed long long, 0xffffffffffffffffLL, 0);
#undef CHECK
}
@ -220,34 +220,34 @@ ATF_TC_HEAD(utypefit, tc)
ATF_TC_BODY(utypefit, tc)
{
#define CHECK(a, b, c) ATF_REQUIRE(!__type_fit(a, b) == c)
#define CHECK(a, b, c) ATF_REQUIRE(__type_fit(a, b) == c)
CHECK(unsigned char, -1, 1);
CHECK(unsigned char, 1, 0);
CHECK(unsigned char, 0x7f, 0);
CHECK(unsigned char, 0x80, 0);
CHECK(unsigned char, 0xff, 0);
CHECK(unsigned char, 0x1ff, 1);
CHECK(unsigned char, -1, 0);
CHECK(unsigned char, 1, 1);
CHECK(unsigned char, 0x7f, 1);
CHECK(unsigned char, 0x80, 1);
CHECK(unsigned char, 0xff, 1);
CHECK(unsigned char, 0x1ff, 0);
CHECK(unsigned short, -1, 1);
CHECK(unsigned short, 1, 0);
CHECK(unsigned short, 0x7fff, 0);
CHECK(unsigned short, 0x8000, 0);
CHECK(unsigned short, 0xffff, 0);
CHECK(unsigned short, 0x1ffff, 1);
CHECK(unsigned short, -1, 0);
CHECK(unsigned short, 1, 1);
CHECK(unsigned short, 0x7fff, 1);
CHECK(unsigned short, 0x8000, 1);
CHECK(unsigned short, 0xffff, 1);
CHECK(unsigned short, 0x1ffff, 0);
CHECK(unsigned int, -1, 1);
CHECK(unsigned int, 1, 0);
CHECK(unsigned int, 0x7fffffff, 0);
CHECK(unsigned int, 0x80000000, 0);
CHECK(unsigned int, 0xffffffff, 0);
CHECK(unsigned int, 0x1ffffffffLL, 1);
CHECK(unsigned int, -1, 0);
CHECK(unsigned int, 1, 1);
CHECK(unsigned int, 0x7fffffff, 1);
CHECK(unsigned int, 0x80000000, 1);
CHECK(unsigned int, 0xffffffff, 1);
CHECK(unsigned int, 0x1ffffffffLL, 0);
CHECK(unsigned long long, -1, 1);
CHECK(unsigned long long, 1, 0);
CHECK(unsigned long long, 0x7fffffffffffffffULL, 0);
CHECK(unsigned long long, 0x8000000000000000ULL, 0);
CHECK(unsigned long long, 0xffffffffffffffffULL, 0);
CHECK(unsigned long long, -1, 0);
CHECK(unsigned long long, 1, 1);
CHECK(unsigned long long, 0x7fffffffffffffffULL, 1);
CHECK(unsigned long long, 0x8000000000000000ULL, 1);
CHECK(unsigned long long, 0xffffffffffffffffULL, 1);
#undef CHECK
}

125
include/sys/t_pslist.c Normal file
View file

@ -0,0 +1,125 @@
/* $NetBSD: t_pslist.c,v 1.1 2016/04/09 04:39:47 riastradh Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Taylor R. Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/pslist.h>
#include <atf-c.h>
/*
* XXX This is a limited test to make sure the operations behave as
* described on a sequential machine. It does nothing to test the
* pserialize-safety of any operations.
*/
ATF_TC(misc);
ATF_TC_HEAD(misc, tc)
{
atf_tc_set_md_var(tc, "descr", "pserialize-safe list tests");
}
ATF_TC_BODY(misc, tc)
{
struct pslist_head h = PSLIST_INITIALIZER;
struct element {
unsigned i;
struct pslist_entry entry;
} elements[] = {
{ .i = 0, .entry = PSLIST_ENTRY_INITIALIZER },
{ .i = 1 },
{ .i = 2 },
{ .i = 3 },
{ .i = 4 },
{ .i = 5 },
{ .i = 6 },
{ .i = 7 },
};
struct element *element;
unsigned i;
/* Check PSLIST_INITIALIZER is destroyable. */
PSLIST_DESTROY(&h);
PSLIST_INIT(&h);
/* Check PSLIST_ENTRY_INITIALIZER is destroyable. */
PSLIST_ENTRY_DESTROY(&elements[0], entry);
for (i = 0; i < __arraycount(elements); i++)
PSLIST_ENTRY_INIT(&elements[i], entry);
PSLIST_WRITER_INSERT_HEAD(&h, &elements[4], entry);
PSLIST_WRITER_INSERT_BEFORE(&elements[4], &elements[2], entry);
PSLIST_WRITER_INSERT_BEFORE(&elements[4], &elements[3], entry);
PSLIST_WRITER_INSERT_BEFORE(&elements[2], &elements[1], entry);
PSLIST_WRITER_INSERT_HEAD(&h, &elements[0], entry);
PSLIST_WRITER_INSERT_AFTER(&elements[4], &elements[5], entry);
PSLIST_WRITER_INSERT_AFTER(&elements[5], &elements[7], entry);
PSLIST_WRITER_INSERT_AFTER(&elements[5], &elements[6], entry);
PSLIST_WRITER_REMOVE(&elements[0], entry);
ATF_CHECK(elements[0].entry.ple_next != NULL);
PSLIST_ENTRY_DESTROY(&elements[0], entry);
PSLIST_WRITER_REMOVE(&elements[4], entry);
ATF_CHECK(elements[4].entry.ple_next != NULL);
PSLIST_ENTRY_DESTROY(&elements[4], entry);
PSLIST_ENTRY_INIT(&elements[0], entry);
PSLIST_WRITER_INSERT_HEAD(&h, &elements[0], entry);
PSLIST_ENTRY_INIT(&elements[4], entry);
PSLIST_WRITER_INSERT_AFTER(&elements[3], &elements[4], entry);
i = 0;
PSLIST_WRITER_FOREACH(element, &h, struct element, entry) {
ATF_CHECK_EQ(i, element->i);
i++;
}
i = 0;
PSLIST_READER_FOREACH(element, &h, struct element, entry) {
ATF_CHECK_EQ(i, element->i);
i++;
}
while ((element = PSLIST_WRITER_FIRST(&h, struct element, entry))
!= NULL) {
PSLIST_WRITER_REMOVE(element, entry);
PSLIST_ENTRY_DESTROY(element, entry);
}
PSLIST_DESTROY(&h);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, misc);
return atf_no_error();
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_socket.c,v 1.3 2013/10/19 17:45:00 christos Exp $ */
/* $NetBSD: t_socket.c,v 1.4 2015/02/27 08:30:30 martin Exp $ */
#include <sys/types.h>
#include <sys/mount.h>
@ -74,7 +74,7 @@ ATF_TC(cmsg_sendfd);
ATF_TC_HEAD(cmsg_sendfd, tc)
{
atf_tc_set_md_var(tc, "descr", "Checks that fd passing works");
atf_tc_set_md_var(tc, "timeout", "2");
atf_tc_set_md_var(tc, "timeout", "10");
}
ATF_TC_BODY(cmsg_sendfd, tc)

View file

@ -1,4 +1,4 @@
/* $NetBSD: t_paths.c,v 1.13 2014/02/09 21:26:07 jmmv Exp $ */
/* $NetBSD: t_paths.c,v 1.16 2015/05/07 06:23:23 pgoyette Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_paths.c,v 1.13 2014/02/09 21:26:07 jmmv Exp $");
__RCSID("$NetBSD: t_paths.c,v 1.16 2015/05/07 06:23:23 pgoyette Exp $");
#include <sys/param.h>
#include <sys/stat.h>
@ -42,12 +42,12 @@ __RCSID("$NetBSD: t_paths.c,v 1.13 2014/02/09 21:26:07 jmmv Exp $");
#include <unistd.h>
#include <atf-c.h>
#include <atf-c/config.h>
#define PATH_DEV __BIT(0) /* A device node */
#define PATH_DIR __BIT(1) /* A directory */
#define PATH_FILE __BIT(2) /* A file */
#define PATH_ROOT __BIT(3) /* Access for root only */
#define PATH_OPT __BIT(3) /* Optional, ENODEV if not supported */
static const struct {
const char *path;
@ -83,7 +83,7 @@ static const struct {
{ _PATH_MIXER, PATH_DEV },
{ _PATH_MIXER0, PATH_DEV },
{ _PATH_NOLOGIN, PATH_FILE },
{ _PATH_POWER, PATH_DEV | PATH_ROOT },
{ _PATH_POWER, PATH_DEV | PATH_ROOT | PATH_OPT },
{ _PATH_PRINTCAP, PATH_FILE },
{ _PATH_PUD, PATH_DEV | PATH_ROOT },
{ _PATH_PUFFS, PATH_DEV | PATH_ROOT },
@ -93,12 +93,13 @@ static const struct {
{ _PATH_SKEYKEYS, PATH_FILE | PATH_ROOT },
{ _PATH_SOUND, PATH_DEV },
{ _PATH_SOUND0, PATH_DEV },
{ _PATH_SYSMON, PATH_DEV },
{ _PATH_SYSMON, PATH_DEV | PATH_OPT },
{ _PATH_TTY, PATH_DEV },
{ _PATH_UNIX, PATH_FILE | PATH_ROOT },
{ _PATH_URANDOM, PATH_DEV },
{ _PATH_VIDEO, PATH_DEV },
{ _PATH_VIDEO0, PATH_DEV },
{ _PATH_WATCHDOG, PATH_DEV | PATH_OPT },
{ _PATH_DEV, PATH_DIR },
{ _PATH_DEV_PTS, PATH_DIR },
@ -144,13 +145,22 @@ ATF_TC_BODY(paths, tc)
switch (errno) {
case ENODEV:
if ((paths[i].flags & PATH_OPT) == 0) {
atf_tc_fail("Required path %s does "
"not exist", paths[i].path);
}
break;
case EPERM: /* FALLTHROUGH */
case EACCES: /* FALLTHROUGH */
if ((paths[i].flags & PATH_ROOT) == 0) {
atf_tc_fail("UID %u failed to open %s",
(uint32_t)uid, paths[i].path);
atf_tc_fail("UID %u failed to open %s, "
"error %d", (uint32_t)uid,
paths[i].path, errno);
}
case EBUSY: /* FALLTHROUGH */

View file

@ -11,9 +11,9 @@ RDR 10.1.1.253 80 <- -> 203.1.1.1 80 [10.2.2.6 2000]
RDR 10.1.1.254 80 <- -> 203.1.1.1 80 [10.2.2.5 2000]
Hostmap table:
10.2.2.7,203.1.1.1 -> 254.1.1.10,0.0.0.0 (use = 1)
10.2.2.6,203.1.1.1 -> 253.1.1.10,0.0.0.0 (use = 1)
10.2.2.5,203.1.1.1 -> 254.1.1.10,0.0.0.0 (use = 1)
10.2.2.7,203.1.1.1 -> 10.1.1.254,0.0.0.0 (use = 1)
10.2.2.6,203.1.1.1 -> 10.1.1.253,0.0.0.0 (use = 1)
10.2.2.5,203.1.1.1 -> 10.1.1.254,0.0.0.0 (use = 1)
List of active state sessions:
List of configured pools
List of configured hash tables

Some files were not shown because too many files have changed in this diff Show more