Index: projects/netbsd-tests-update-12/bin/cat/tests/Makefile =================================================================== --- projects/netbsd-tests-update-12/bin/cat/tests/Makefile (revision 304002) +++ projects/netbsd-tests-update-12/bin/cat/tests/Makefile (revision 304003) @@ -1,12 +1,14 @@ # $FreeBSD$ PACKAGE= tests NETBSD_ATF_TESTS_SH= cat_test ${PACKAGE}FILES+= d_align.in ${PACKAGE}FILES+= d_align.out +${PACKAGE}FILES+= d_se_output.in +${PACKAGE}FILES+= d_se_output.out .include .include Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.in =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.in (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.in (revision 304003) @@ -1,3 +1,5 @@ a b c + 1 2 3 + x y z Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.out =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.out (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_align.out (revision 304003) @@ -1,3 +1,5 @@ 1 a b c$ + $ 2 1 2 3$ + $ 3 x y z$ Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.in =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.in (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.in (revision 304003) @@ -0,0 +1,3 @@ + +Of course it runs NetBSD + Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.out =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.out (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/d_se_output.out (revision 304003) @@ -0,0 +1,3 @@ +$ +Of course it runs NetBSD$ +$ Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/t_cat.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/t_cat.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/cat/t_cat.sh (revision 304003) @@ -1,59 +1,71 @@ -# $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. # # This code is derived from software contributed to The NetBSD Foundation # by Jukka Ruohonen. # # 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. # atf_test_case align align_head() { atf_set "descr" "Test that cat(1) aligns the output " \ "right with options '-be' (PR bin/4841)" } align_body() { atf_check -s ignore -o file:$(atf_get_srcdir)/d_align.out \ -x "cat -be $(atf_get_srcdir)/d_align.in" } atf_test_case nonexistent nonexistent_head() { atf_set "descr" "Test that cat(1) doesn't return zero exit " \ "status for a nonexistent file (PR bin/3538)" } nonexistent_body() { atf_check -s not-exit:0 -o empty -e not-empty \ -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 } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_compexit.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_compexit.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_compexit.sh (nonexistent) @@ -1,63 +0,0 @@ -# $NetBSD: t_compexit.sh,v 1.1 2012/03/17 16:33:11 jruoho Exp $ -# -# Copyright (c) 2007 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 standard -# http://www.opengroup.org/onlinepubs/007904975/utilities/set.html -# says: -# -# -e -# -# When this option is on, if a simple command fails for any of the -# reasons listed in Consequences of Shell Errors or returns an exit -# status value >0, and is not part of the compound list following a -# while, until, or if keyword, and is not a part of an AND or OR list, -# and is not a pipeline preceded by the ! reserved word, then the shell -# shall immediately exit. - -crud() { - set -e - for x in a - do - BAR="foo" - false && echo true - echo mumble - done -} - -atf_test_case set_e -set_e_head() { - atf_set "descr" "Tests that 'set -e' turns on error detection" \ - "and that it behaves as defined by the standard" -} -set_e_body() { - foo=`crud` - atf_check_equal 'x$foo' 'xmumble' -} - -atf_init_test_cases() { - atf_add_test_case set_e -} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_compexit.sh ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/dotcmd/scoped_command =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/dotcmd/scoped_command (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/dotcmd/scoped_command (revision 304003) @@ -1,129 +1,150 @@ #!/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. # # This code is derived from software contributed to The NetBSD Foundation # by Jarmo Jaakkola. # # 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. # +: ${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: # scoped_command scope cmd msg var_suffix # # Write to stdout a piece of Bourne Shell script with _cmd_ in specific # _scope_. The execution of _cmd_ is bracketed by prints of "before _msg_" # and "after _msg_, return value ${?}". If the generated script uses # variables, __var_suffix_ is appended to their names to allow nesting of # scripts generated this way. # # _scope_ should be one of: case, compound, file, for, func, subshell, # until, while. # _cmd_ is the command line to execute. Remember proper quoting! # _msg_ is text that will be used inside single quotes. # _var_suffix_ is a syntactically valid identifier name. # don't rely on command lists (';') cmd="echo 'before ${3}' ${2} echo 'after ${3}, return value:' ${?}" -echo "#!/bin/sh" +echo "#!${TEST_SH}" [ 'func' = "${1}" ] && cat </dev/null + then + # 16 bits or less, or hex unsupported, just give up... + return + fi + test $( ${TEST_SH} -c 'echo $(( 0x1FFFF ))' ) = 131071 || return + + # when attempting to exceed the number of available bits + # the shell may react in any of 3 (rational) ways + # 1. syntax error (maybe even core dump...) and fail + # 2. represent a positive number input as negative value + # 3. keep the number positive, but not the value expected + # (perhaps pegged at the max possible value) + # any of those may be accompanied by a message to stderr + + # Must check all 3 possibilities for each plausible size + # Tests do not use 0x8000... because that value can have weird + # other side effects that are not relevant to discover here. + # But we do want to try and force the sign bit set. + + if ! ${TEST_SH} -c ': $(( 0xC0000000 ))' 2>/dev/null + then + # proobably shell detected overflow and complained + ARITH_BITS=32 + return + fi + if ${TEST_SH} 2>/dev/null \ + -c 'case $(( 0xC0000000 )); in (-*) exit 0;; esac; exit 1' + then + ARITH_BITS=32 + return + fi + if ${TEST_SH} -c '[ $(( 0xC0000000 )) != 3221225472 ]' 2>/dev/null + then + ARITH_BITS=32 + return + fi + + if ! ${TEST_SH} -c ': $(( 0xC000000000000000 ))' 2>/dev/null + then + ARITH_BITS=64 + return + fi + if ${TEST_SH} 2>/dev/null \ + -c 'case $(( 0xC000000000000000 )); in (-*) exit 0;; esac; exit 1' + then + ARITH_BITS=64 + return + fi + if ${TEST_SH} 2>/dev/null \ + -c '[ $((0xC000000000000000)) != 13835058055282163712 ]' + then + ARITH_BITS=64 + return + fi + + if ${TEST_SH} 2>/dev/null -c \ + '[ $((0x123456781234567812345678)) = 5634002657842756053938493048 ]' + then + # just assume... (for now anyway, revisit when it happens...) + ARITH_BITS=96 + return + fi +} + +atf_test_case constants +constants_head() +{ + atf_set "descr" "Tests that arithmetic expansion can handle constants" +} +constants_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $((0x0))' + + # atf_expect_fail "PR bin/50959" + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $((0X0))' + # atf_expect_pass + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $((000))' + + atf_check -s exit:0 -o inline:'1\n' -e empty \ + ${TEST_SH} -c 'echo $(( 000000001 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty \ + ${TEST_SH} -c 'echo $(( 0x000000 ))' + + atf_check -s exit:0 -o inline:'99999\n' -e empty \ + ${TEST_SH} -c 'echo $((99999))' + + [ ${ARITH_BITS} -gt 44 ] && + atf_check -s exit:0 -o inline:'9191919191919\n' -e empty \ + ${TEST_SH} -c 'echo $((9191919191919))' + + atf_check -s exit:0 -o inline:'13\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xD ))' + atf_check -s exit:0 -o inline:'11\n' -e empty ${TEST_SH} -c \ + 'echo $(( 013 ))' + atf_check -s exit:0 -o inline:'7\n' -e empty ${TEST_SH} -c \ + 'x=7;echo $(($x))' + atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \ + 'x=9;echo $((x))' + + atf_check -s exit:0 -o inline:'11\n' -e empty \ + ${TEST_SH} -c 'x=0xB; echo $(( $x ))' + atf_check -s exit:0 -o inline:'27\n' -e empty \ + ${TEST_SH} -c 'x=0X1B; echo $(( x ))' + atf_check -s exit:0 -o inline:'27\n' -e empty \ + ${TEST_SH} -c 'X=033; echo $(( $X ))' + atf_check -s exit:0 -o inline:'219\n' -e empty \ + ${TEST_SH} -c 'X=0333; echo $(( X ))' + atf_check -s exit:0 -o inline:'0\n' -e empty \ + ${TEST_SH} -c 'NULL=; echo $(( NULL ))' + + # Not clear if this is 0, nothing, or an error, so omit for now + # atf_check -s exit:0 -o inline:'0\n' -e empty \ + # ${TEST_SH} -c 'echo $(( ))' + + # not clear whether this should return 0 or an error, so omit for now + # atf_check -s exit:0 -o inline:'0\n' -e empty \ + # ${TEST_SH} -c 'echo $(( UNDEFINED_VAR ))' +} + + +atf_test_case do_unary_plus +do_unary_plus_head() +{ + atf_set "descr" "Tests that unary plus works as expected" +} +do_unary_plus_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( +0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( +1 ))' + atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \ + 'echo $(( + 6 ))' + atf_check -s exit:0 -o inline:'4321\n' -e empty ${TEST_SH} -c \ + 'echo $(( + 4321 ))' + atf_check -s exit:0 -o inline:'17185\n' -e empty ${TEST_SH} -c \ + 'echo $(( + 0x4321 ))' +} + +atf_test_case do_unary_minus +do_unary_minus_head() +{ + atf_set "descr" "Tests that unary minus works as expected" +} +do_unary_minus_body() +{ + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 0 ))' + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 1 ))' + atf_check -s exit:0 -o inline:'-6\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 6 ))' + atf_check -s exit:0 -o inline:'-4321\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 4321 ))' + atf_check -s exit:0 -o inline:'-2257\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 04321 ))' + atf_check -s exit:0 -o inline:'-7\n' -e empty ${TEST_SH} -c \ + 'echo $((-7))' +} + +atf_test_case do_unary_not +do_unary_not_head() +{ + atf_set "descr" "Tests that unary not (boolean) works as expected" +} +do_unary_not_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( ! 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( ! 0 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( !1234 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( !0xFFFF ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( ! 000000 ))' +} + +atf_test_case do_unary_tilde +do_unary_tilde_head() +{ + atf_set "descr" "Tests that unary not (bitwise) works as expected" +} +do_unary_tilde_body() +{ + # definitely 2's complement arithmetic here... + + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( ~ 0 ))' + atf_check -s exit:0 -o inline:'-2\n' -e empty ${TEST_SH} -c \ + 'echo $(( ~ 1 ))' + + atf_check -s exit:0 -o inline:'-1235\n' -e empty ${TEST_SH} -c \ + 'echo $(( ~1234 ))' + atf_check -s exit:0 -o inline:'-256\n' -e empty ${TEST_SH} -c \ + 'echo $(( ~0xFF ))' +} + +atf_test_case elementary_add +elementary_add_head() +{ + atf_set "descr" "Tests that simple addition works as expected" +} +elementary_add_body() +{ + # some of these tests actually test unary ops & op precedence... + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 + 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 + 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 + 1 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 + 1 ))' + atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \ + 'echo $(( 4 + 6 ))' + atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \ + 'echo $(( 6 + 4 ))' + atf_check -s exit:0 -o inline:'5555\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1234 + 4321 ))' + atf_check -s exit:0 -o inline:'3333\n' -e empty ${TEST_SH} -c \ + 'echo $((1111+2222))' + atf_check -s exit:0 -o inline:'5555\n' -e empty ${TEST_SH} -c \ + 'echo $((+3333+2222))' + atf_check -s exit:0 -o inline:'7777\n' -e empty ${TEST_SH} -c \ + 'echo $((+3333 + +4444))' + atf_check -s exit:0 -o inline:'-7777\n' -e empty ${TEST_SH} -c \ + 'echo -$((+4125+ +3652))' +} + +atf_test_case elementary_sub +elementary_sub_head() +{ + atf_set "descr" "Tests that simple subtraction works as expected" +} +elementary_sub_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 - 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 - 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 - 1 ))' + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 - 1 ))' + atf_check -s exit:0 -o inline:'488\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1066 - 578 ))' + atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2016-5678 ))' + atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2016+-5678 ))' + atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2016-+5678 ))' + atf_check -s exit:0 -o inline:'-7694\n' -e empty ${TEST_SH} -c \ + 'echo $(( -2016-5678 ))' + atf_check -s exit:0 -o inline:'--1\n' -e empty ${TEST_SH} -c \ + 'echo -$(( -1018 - -1017 ))' +} + +atf_test_case elementary_mul +elementary_mul_head() +{ + atf_set "descr" "Tests that simple multiplication works as expected" +} +elementary_mul_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 * 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 * 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 * 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 * 1 ))' + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 * 1 ))' + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 * -1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 * -1 ))' + atf_check -s exit:0 -o inline:'391\n' -e empty ${TEST_SH} -c \ + 'echo $(( 17 * 23 ))' + atf_check -s exit:0 -o inline:'169\n' -e empty ${TEST_SH} -c \ + 'echo $(( 13*13 ))' + atf_check -s exit:0 -o inline:'-11264\n' -e empty ${TEST_SH} -c \ + 'echo $(( -11 *1024 ))' + atf_check -s exit:0 -o inline:'-16983\n' -e empty ${TEST_SH} -c \ + 'echo $(( 17* -999 ))' + atf_check -s exit:0 -o inline:'9309\n' -e empty ${TEST_SH} -c \ + 'echo $(( -29*-321 ))' +} + +atf_test_case elementary_div +elementary_div_head() +{ + atf_set "descr" "Tests that simple division works as expected" +} +elementary_div_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 / 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 / 1 ))' + test ${ARITH_BITS} -ge 38 && + atf_check -s exit:0 -o inline:'99999999999\n' -e empty \ + ${TEST_SH} -c 'echo $(( 99999999999 / 1 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 / 1 ))' + + atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 / 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 / 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 / 3 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 / 4 ))' + + atf_check -s exit:0 -o inline:'173\n' -e empty ${TEST_SH} -c \ + 'echo $(( 123456 / 713 ))' + atf_check -s exit:0 -o inline:'13\n' -e empty ${TEST_SH} -c \ + 'echo $(( 169 / 13 ))' +} + +atf_test_case elementary_rem +elementary_rem_head() +{ + atf_set "descr" "Tests that simple modulus works as expected" +} +elementary_rem_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 % 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 % 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 % 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9999 % 1 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 % 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 % 2 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 % 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xFFFF % 2 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 % 3 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 % 3 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 % 3 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 % 3 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3123 % 3 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9999 % 2 ))' + + atf_check -s exit:0 -o inline:'107\n' -e empty ${TEST_SH} -c \ + 'echo $(( 123456%173 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $((169%13))' +} + +atf_test_case elementary_shl +elementary_shl_head() +{ + atf_set "descr" "Tests that simple shift left works as expected" +} +elementary_shl_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 << 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 << 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 << 17 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 << 0 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 << 1 ))' + atf_check -s exit:0 -o inline:'131072\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 << 17 ))' + + atf_check -s exit:0 -o inline:'2021161080\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x3C3C3C3C << 1 ))' + + test "${ARITH_BITS}" -ge 40 && + atf_check -s exit:0 -o inline:'129354309120\n' -e empty \ + ${TEST_SH} -c 'echo $(( 0x3C3C3C3C << 7 ))' + test "${ARITH_BITS}" -ge 72 && + atf_check -s exit:0 -o inline:'1111145054534149079040\n' \ + -e empty ${TEST_SH} -c 'echo $(( 0x3C3C3C3C << 40 ))' + + return 0 +} + +atf_test_case elementary_shr +elementary_shr_head() +{ + atf_set "descr" "Tests that simple shift right works as expected" +} +elementary_shr_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 >> 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 >> 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 >> 17 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 >> 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 >> 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 >> 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 >> 1 ))' + + atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x10 >> 2 ))' + atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \ + 'echo $(( 022 >> 2 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 131072 >> 17 ))' + + test ${ARITH_BITS} -ge 40 && + atf_check -s exit:0 -o inline:'8\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x4000000000 >> 35 ))' + test ${ARITH_BITS} -ge 80 && + atf_check -s exit:0 -o inline:'4464\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x93400FACE005C871000 >> 64 ))' + + return 0 +} + +atf_test_case elementary_eq +elementary_eq_head() +{ + atf_set "descr" "Tests that simple equality test works as expected" +} +elementary_eq_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 0000 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 0x00 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 == 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'X=30; Y=0x1E; echo $(( X == Y ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1234 == 4660 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1234 == 011064 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 0000000000000001 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 == 0x10000000000000 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 == 2 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'X=3; Y=7; echo $(( X == Y ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1234 == 0x4660 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 01234 == 0x11064 ))' +} +atf_test_case elementary_ne +elementary_ne_head() +{ + atf_set "descr" "Tests that simple inequality test works as expected" +} +elementary_ne_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 != 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x71 != 17 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1234 != 01234 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1234 != 01234 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'X=3; echo $(( X != 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'X=3; Y=0x11; echo $(( X != Y ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 != 3 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 != 0x0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xA != 012 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'X=1; echo $(( X != 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'X=0xC; Y=014; echo $(( X != Y ))' +} +atf_test_case elementary_lt +elementary_lt_head() +{ + atf_set "descr" "Tests that simple less than test works as expected" +} +elementary_lt_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 < 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 < 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 < 10 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 100 < 101 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xA1 < 200 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 < 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 < 0 ))' + + test ${ARITH_BITS} -ge 40 && + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1BEEFF00D < 0x1FACECAFE ))' + + return 0 +} +atf_test_case elementary_le +elementary_le_head() +{ + atf_set "descr" "Tests that simple less or equal test works as expected" +} +elementary_le_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 <= 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 <= 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 <= 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 <= 10 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 100 <= 101 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xA1 <= 161 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 <= 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( -100 <= -200 ))' + + test ${ARITH_BITS} -ge 40 && + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'cost=; AUD=; echo $(( $cost 0x2FEEDBABE <= $AUD 12866927294 ))' + + return 0 +} +atf_test_case elementary_gt +elementary_gt_head() +{ + atf_set "descr" "Tests that simple greater than works as expected" +} +elementary_gt_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 > 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 > -1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 11 > 012 ))' + + # atf_expect_fail "PR bin/50959" + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2147483647 > 0X7FFFFF0 ))' + # atf_expect_pass + + test ${ARITH_BITS} -gt 32 && + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x80000000 > 0x7FFFFFFF ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 > 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 > 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 > 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 > 10 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2015 > 2016 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xA1 > 200 ))' + + test ${ARITH_BITS} -ge 44 && + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x7F07F07F0 > 34099628014 ))' + + return 0 +} +atf_test_case elementary_ge +elementary_ge_head() +{ + atf_set "descr" "Tests that simple greater or equal works as expected" +} +elementary_ge_body() +{ + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 >= 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 >= 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( -100 >= -101 ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( -1 >= 0 ))' +} + +atf_test_case fiddle_bits_and +fiddle_bits_and_head() +{ + atf_set "descr" "Test bitwise and operations in arithmetic expressions" +} +fiddle_bits_and_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 & 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 & 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 & 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 & 1 ))' + + atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xFF & 0xFF ))' + atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xFFFF & 0377 ))' + + test "${ARITH_BITS}" -ge 48 && + atf_check -s exit:0 -o inline:'70377641607203\n' -e empty \ + ${TEST_SH} -c 'echo $(( 0x5432FEDC0123 & 0x42871357BAB3 ))' + + return 0 +} +atf_test_case fiddle_bits_or +fiddle_bits_or_head() +{ + atf_set "descr" "Test bitwise or operations in arithmetic expressions" +} +fiddle_bits_or_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 | 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 | 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 | 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 | 1 ))' + + atf_check -s exit:0 -o inline:'4369\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1111 | 0x1111 ))' + atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xAA | 0125 ))' + + test "${ARITH_BITS}" -ge 48 && + atf_check -s exit:0 -o inline:'95348271856563\n' -e empty \ + ${TEST_SH} -c 'echo $(( 0x5432FEDC0123 | 0x42871357BAB3 ))' + + return 0 +} +atf_test_case fiddle_bits_xor +fiddle_bits_xor_head() +{ + atf_set "descr" "Test bitwise xor operations in arithmetic expressions" +} +fiddle_bits_xor_body() +{ + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 ^ 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 ^ 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 ^ 1 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 ^ 1 ))' + + atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xF0 ^ 0x0F ))' + atf_check -s exit:0 -o inline:'15\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xF0 ^ 0xFF ))' + + test "${ARITH_BITS}" -ge 48 && + atf_check -s exit:0 -o inline:'24970630249360\n' -e empty \ + ${TEST_SH} -c 'echo $(( 0x5432FEDC0123 ^ 0x42871357BAB3 ))' + + return 0 +} + +atf_test_case logical_and +logical_and_head() +{ + atf_set "descr" "Test logical and operations in arithmetic expressions" +} +logical_and_body() +{ + # cannot test short-circuit eval until sh implements side effects... + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 && 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 && 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 && 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 && 1 ))' + + # atf_expect_fail "PR bin/50960" + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1111 && 01234 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xFFFF && 0xF0F0 ))' +} +atf_test_case logical_or +logical_or_head() +{ + atf_set "descr" "Test logical or operations in arithmetic expressions" +} +logical_or_body() +{ + # cannot test short-circuit eval until sh implements side effects... + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 || 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 || 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 || 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 || 1 ))' + + # atf_expect_fail "PR bin/50960" + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1111 || 01234 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x33 || 0xF0F0 ))' +} + +atf_test_case make_selection +make_selection_head() +{ + atf_set "descr" "Test ?: operator in arithmetic expressions" +} +make_selection_body() +{ + # atf_expect_fail "PR bin/50958" + + atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0 ? 2 : 3 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 ? 2 : 3 ))' + + atf_check -s exit:0 -o inline:'111\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0x1234 ? 111 : 222 ))' + + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 < 2 ? -1 : 1 > 2 ? 1 : 0 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 < 1 ? -1 : 1 > 1 ? 1 : 0 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 < 1 ? -1 : 2 > 1 ? 1 : 0 ))' +} + +atf_test_case operator_precedence +operator_precedence_head() +{ + atf_set "descr" "Test operator precedence without parentheses" +} +operator_precedence_body() +{ + # NB: apart from $(( )) ** NO ** parentheses in the expressions. + + atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 + 2 + 3 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 - 2 + 3 ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 - 2 - 1 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 - 2 + 1 ))' + + atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \ + 'echo $(( - 2 + 1 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 + -1 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( ! 2 + 1 ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 + !1 ))' + + atf_check -s exit:0 -o inline:'8\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 * 2 + 2 ))' + atf_check -s exit:0 -o inline:'7\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 + 2 * 2 ))' + atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 * 2 * 2 ))' + + atf_check -s exit:0 -o inline:'5\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 / 3 + 2 ))' + atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 + 3 / 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 / 3 / 2 ))' + + atf_check -s exit:0 -o inline:'72\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 << 1 + 2 ))' + atf_check -s exit:0 -o inline:'48\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 + 3 << 2 ))' + atf_check -s exit:0 -o inline:'288\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 << 3 << 2 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 >> 1 + 2 ))' + atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 + 3 >> 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 >> 3 >> 1 ))' + + atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 >> 3 << 1 ))' + atf_check -s exit:0 -o inline:'76\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 << 3 >> 1 ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 + 3 < 3 * 2 ))' + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 << 3 >= 3 << 2 ))' + + # sh inherits C's crazy operator precedence... + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 0xfD & 0xF == 0xF ))' +} + +parentheses_head() +{ + atf_set "descr" "Test use of () to group sub-expressions" +} +parentheses_body() +{ + atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \ + 'echo $(( (1 + 2) + 3 ))' + atf_check -s exit:0 -o inline:'-4\n' -e empty ${TEST_SH} -c \ + 'echo $(( 1 - (2 + 3) ))' + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 - (2 - 1) ))' + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 - ( 2 + 1 ) ))' + + atf_check -s exit:0 -o inline:'-3\n' -e empty ${TEST_SH} -c \ + 'echo $(( - (2 + 1) ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( ! (2 + 1) ))' + + atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 * (2 + 2) ))' + atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \ + 'echo $(( (3 + 2) * 2 ))' + atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \ + 'echo $(( 3 * (2 * 2) ))' + + atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 / (3 + 2) ))' + atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \ + 'echo $(( ( 9 + 3 ) / 2 ))' + atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 / ( 3 / 2 ) ))' + + atf_check -s exit:0 -o inline:'20\n' -e empty ${TEST_SH} -c \ + 'echo $(( ( 9 << 1 ) + 2 ))' + atf_check -s exit:0 -o inline:'21\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 + (3 << 2) ))' + atf_check -s exit:0 -o inline:'36864\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 << (3 << 2) ))' + + atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \ + 'echo $(( (9 >> 1) + 2 ))' + atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \ + 'echo $(( 9 + (3 >> 2) ))' + atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 >> (3 >> 1) ))' + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 >> (3 << 1) ))' + atf_check -s exit:0 -o inline:'38\n' -e empty ${TEST_SH} -c \ + 'echo $(( 19 << (3 >> 1) ))' + + atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 + (3 < 3) * 2 ))' + atf_check -s exit:0 -o inline:'32\n' -e empty ${TEST_SH} -c \ + 'echo $(( 2 << ((3 >= 3) << 2) ))' + + # sh inherits C's crazy operator precedence... + + atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \ + 'echo $(( (0xfD & 0xF) == 0xF ))' +} + +atf_test_case arithmetic_fails +arithmetic_fails_head() +{ + atf_set "descr" "Dummy test to force failure" +} +arithmetic_fails_body() +{ + atf_fail "Cannot estimate number of bits supported by $(( ))" +} + +atf_init_test_cases() { + + discover_range + + test "${ARITH_BITS}" = '?' && { + atf_add_test_case arithmetic_fails + return 0 + } + + # odd names are to get atf's sort order semi-rational + + atf_add_test_case constants + atf_add_test_case do_unary_plus + atf_add_test_case do_unary_minus + atf_add_test_case do_unary_not + atf_add_test_case do_unary_tilde + atf_add_test_case elementary_add + atf_add_test_case elementary_sub + atf_add_test_case elementary_mul + atf_add_test_case elementary_div + atf_add_test_case elementary_rem + atf_add_test_case elementary_shl + atf_add_test_case elementary_shr + atf_add_test_case elementary_eq + atf_add_test_case elementary_ne + atf_add_test_case elementary_lt + atf_add_test_case elementary_le + atf_add_test_case elementary_gt + atf_add_test_case elementary_ge + atf_add_test_case fiddle_bits_and + atf_add_test_case fiddle_bits_or + atf_add_test_case fiddle_bits_xor + atf_add_test_case logical_and + atf_add_test_case logical_or + atf_add_test_case make_selection + atf_add_test_case operator_precedence + atf_add_test_case parentheses + # atf_add_test_case progressive # build up big expr + # atf_add_test_case test_errors # erroneous input + # atf_add_test_case torture # hard stuff (if there is any) + # atf_add_test_case var_assign # assignment ops + # atf_add_test_case vulgarity # truly evil inputs (syntax in vars...) +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_arith.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_cmdsub.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_cmdsub.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_cmdsub.sh (revision 304003) @@ -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< helper.sh << EOF set -e if eval false then echo "'eval false' returned true" exit 1 fi echo "passed" exit 0 EOF - output="$(/bin/sh helper.sh)" + output="$($TEST_SH helper.sh)" [ $? = 0 ] && return if [ -n "$output" ] then atf_fail "$output" else atf_fail "'eval false' exited from a tested context" fi } atf_init_test_cases() { atf_add_test_case evaltested } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_exit.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_exit.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_exit.sh (revision 304003) @@ -1,105 +1,157 @@ -# $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. # # 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"} -crud() { - test yes = no - cat <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() { atf_add_test_case background atf_add_test_case function atf_add_test_case readout 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 } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_expand.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_expand.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_expand.sh (revision 304003) @@ -1,142 +1,380 @@ -# $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. # # 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 the functions in expand.c. # delim_argv() { str= while [ $# -gt 0 ]; do if [ -z "${str}" ]; then str=">$1<" else str="${str} >$1<" fi shift done echo ${str} } atf_test_case dollar_at dollar_at_head() { atf_set "descr" "Somewhere between 2.0.2 and 3.0 the expansion" \ "of the \$@ variable had been broken. Check for" \ "this behavior." } 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 dollar_at_with_text_head() { atf_set "descr" "Test \$@ expansion when it is surrounded by text" \ "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 strip_head() { atf_set "descr" "Checks that the %% operator works and strips" \ "the contents of a variable from the given point" \ "to the end" } 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 varpattern_backslashes_head() { atf_set "descr" "Tests that protecting wildcards with backslashes" \ "works in variable patterns." } 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 arithmetic_head() { atf_set "descr" "POSIX requires shell arithmetic to use signed" \ "long or a wider type. We use intmax_t, so at" \ "least 64 bits should be available. Make sure" \ "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 iteration_on_null_parameter_head() { atf_set "descr" "Check iteration of \$@ in for loop when set to null;" \ "the error \"sh: @: parameter not set\" is incorrect." \ "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() { atf_add_test_case dollar_at atf_add_test_case dollar_at_with_text atf_add_test_case strip 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 } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_fsplit.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_fsplit.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_fsplit.sh (revision 304003) @@ -1,186 +1,360 @@ -# $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 # 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 standard # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html # explains (section 2.6) that Field splitting should be performed on the # result of variable expansions. # In particular this means that in ${x-word}, 'word' must be expanded as if # 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 } atf_test_case for for_head() { atf_set "descr" "Checks field splitting in for loops" } 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' '' } atf_test_case default_val 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 ifs_alpha_head() { atf_set "descr" "Checks that field splitting works with alphabetic" \ "characters" } 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 quote_head() { atf_set "descr" "Checks that field splitting works with multi-word" \ "fields" } 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' check 'for i in "${x-a b c}"; do echo "z${i}z"; done' 'za b cz' } atf_test_case dollar_at dollar_at_head() { atf_set "descr" "Checks that field splitting works when expanding" \ "\$@" } 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 ifs_head() { atf_set "descr" "Checks that IFS correctly configures field" \ "splitting behavior" } 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' check 't=" x "; IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1' check 't=axb; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '2 a:b' check 't="a x b"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '2 a : b' check 't="a xx b"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '3 a :: b' check 't="a xx b"; IFS="x "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '3 a::b' # A recent 'clarification' means that a single trailing IFS non-whitespace # doesn't generate an empty parameter check 't="xax"; IFS="x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '2 :a' check 't="xax "; IFS="x "; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '2 :a' # Verify that IFS isn't being applied where it shouldn't be. check 'IFS="x"; set axb; IFS=":"; r="$*"; IFS=; echo $# $r' '1 axb' } atf_test_case var_length var_length_head() { atf_set "descr" "Checks that field splitting works when expanding" \ "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 atf_add_test_case ifs atf_add_test_case var_length } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_here.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_here.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_here.sh (revision 304003) @@ -1,73 +1,565 @@ -# $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. # # 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"} 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 < + 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 < script + prefix() { sed -e "s/^/$1:/"; } + DASH_CODE() { :; } + + prefix A <&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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_option.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redir.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redir.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redir.sh (revision 304003) @@ -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 <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 /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/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 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 ${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 <output-file + + ( printf "hello\n" >&6 ) + + exec 8&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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redir.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redircloexec.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redircloexec.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redircloexec.sh (revision 304003) @@ -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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_redircloexec.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_set_e.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_set_e.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_set_e.sh (revision 304003) @@ -1,289 +1,305 @@ -# $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. # # 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. # # references: # http://www.opengroup.org/onlinepubs/009695399/utilities/set.html # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html # the implementation of "sh" to test -: ${TEST_SH:="sh"} +: ${TEST_SH:="/bin/sh"} failwith() { case "$SH_FAILS" in "") SH_FAILS=`echo "$1"`;; *) SH_FAILS="$SH_FAILS"`echo; echo "$1"`;; esac } check1() { #echo "$TEST_SH -c $1" result=`$TEST_SH -c "$1" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//'` if [ "$result" != "$2" ]; then MSG=`printf "%-56s %-8s %s" "$3" "$result" "$2"` failwith "$MSG" failcount=`expr $failcount + 1` fi count=`expr $count + 1` } # direct check: try the given expression. dcheck() { check1 "$1" "$2" "$1" } # eval check: indirect through eval. # as of this writing, this changes the behavior pretty drastically and # 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 all_head() { atf_set "descr" "Tests that 'set -e' works correctly" } all_body() { count=0 failcount=0 # make sure exiting from a subshell behaves as expected dcheck '(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1' echeck '(set -e; exit 1; echo ERR$?); echo OK$?' 'OK1' # 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' echeck '(set -e; /nonexistent; echo ERR); echo OK' 'OK' dcheck '(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK' echeck '(set -e; nonexistent-program-on-path; echo ERR); echo OK' 'OK' dcheck 'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK' echeck 'f() { false; }; (set -e; f; echo ERR); echo OK' 'OK' dcheck 'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK' echeck 'f() { return 1; }; (set -e; f; echo ERR); echo OK' 'OK' # but! with set -e, the false should cause an *immediate* exit. # The return form should not, as such, but there's no way to # distinguish it. dcheck 'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK' echeck 'f() { false; echo ERR; }; (set -e; f); echo OK' 'OK' # set is not scoped, so these should not exit at all. dcheck 'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK' echeck 'f() { set +e; false; echo OK; }; (set -e; f); echo OK' 'OK OK' # according to the standard, only failing *simple* commands # cause an exit under -e. () is not a simple command. # Correct (per POSIX): #dcheck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK' #echeck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK OK' # Wrong current behavior: dcheck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK' echeck '(set -e; (set +e; false; echo OK; false); echo OK)' 'OK' # make sure an inner nested shell does exit though. dcheck '(set -e; (false; echo ERR)); echo OK' 'OK' # The left hand side of an || or && is explicitly tested and # thus should not cause an exit. Furthermore, because a || or # && expression is not a simple command, there should be no # exit even if the overall result is false. dcheck '(set -e; false || true; echo OK); echo OK' 'OK OK' echeck '(set -e; false || true; echo OK); echo OK' 'OK OK' dcheck '(set -e; false && true; echo OK); echo OK' 'OK OK' echeck '(set -e; false && true; echo OK); echo OK' 'OK OK' # However, the right hand side is not tested, so a failure # there *should* cause an exit, regardless of whether it # appears inside a non-simple command. # # Note that in at least one place the standard does not # distinguish between the left and right hand sides of # logical operators. It is possible that for strict # compliance these need to not exit; however, if so that # should probably be limited to when some strict-posix setting # is in effect and tested accordingly. # dcheck '(set -e; false || false; echo ERR); echo OK' 'OK' dcheck '(set -e; true && false; echo ERR); echo OK' 'OK' echeck '(set -e; false || false; echo ERR); echo OK' 'OK' echeck '(set -e; true && false; echo ERR); echo OK' 'OK' # correct: #dcheck '(set -e; false && false; echo ERR); echo OK' 'OK' #echeck '(set -e; false && false; echo ERR); echo OK' 'OK' # wrong current behavior: dcheck '(set -e; false && false; echo ERR); echo OK' 'ERR OK' echeck '(set -e; false && false; echo ERR); echo OK' 'ERR OK' # A failure that is not reached because of short-circuit # evaluation should not cause an exit, however. dcheck '(set -e; true || false; echo OK); echo OK' 'OK OK' echeck '(set -e; true || false; echo OK); echo OK' 'OK OK' # For completeness, test the other two combinations. dcheck '(set -e; true || true; echo OK); echo OK' 'OK OK' dcheck '(set -e; true && true; echo OK); echo OK' 'OK OK' echeck '(set -e; true || true; echo OK); echo OK' 'OK OK' echeck '(set -e; true && true; echo OK); echo OK' 'OK OK' # likewise, none of these should exit. dcheck '(set -e; while false; do :; done; echo OK); echo OK' 'OK OK' dcheck '(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK' # problematic :-) #dcheck '(set -e; until false; do :; done; echo OK); echo OK' 'OK OK' dcheck '(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \ 'OK OK' echeck '(set -e; while false; do :; done; echo OK); echo OK' 'OK OK' echeck '(set -e; if false; then :; fi; echo OK); echo OK' 'OK OK' echeck '(set -e; until [ "$t" = 1 ]; do t=1; done; echo OK); echo OK' \ 'OK OK' # the bang operator tests its argument and thus the argument # should not cause an exit. it is also not a simple command (I # believe) so it also shouldn't exit even if it yields a false # result. dcheck '(set -e; ! false; echo OK); echo OK' 'OK OK' dcheck '(set -e; ! true; echo OK); echo OK' 'OK OK' echeck '(set -e; ! false; echo OK); echo OK' 'OK OK' echeck '(set -e; ! true; echo OK); echo OK' 'OK OK' # combined case with () and &&; the inner expression is false # but does not itself exit, and the () should not cause an # exit even when failing. # correct: #dcheck '(set -e; (false && true); echo OK); echo OK' 'OK OK' #echeck '(set -e; (false && true); echo OK); echo OK' 'OK OK' # wrong current behavior: dcheck '(set -e; (false && true); echo OK); echo OK' 'OK' echeck '(set -e; (false && true); echo OK); echo OK' 'OK' # pipelines. only the right-hand end is significant. dcheck '(set -e; false | true; echo OK); echo OK' 'OK OK' echeck '(set -e; false | true; echo OK); echo OK' 'OK OK' dcheck '(set -e; true | false; echo ERR); echo OK' 'OK' echeck '(set -e; true | false; echo ERR); echo OK' 'OK' dcheck '(set -e; while true | false; do :; done; echo OK); echo OK' \ 'OK OK' dcheck '(set -e; if true | false; then :; fi; echo OK); echo OK' \ 'OK OK' # 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 # would break all the above test logic, which relies on being # able to isolate set -e behavior inside ().) However, I'm # going to put these tests here to make sure the issue gets # dealt with sometime. # # 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) #dcheck 'echo OK; (set -e; false); echo ERR' 'OK' #echeck 'echo OK; (set -e; false); echo ERR' 'OK' # The current behavior of the shell is that it exits out as # far as -e is set and then stops. This is probably a # consequence of it handling () wrong, but it's a somewhat # curious compromise position between 1. and 2. above. dcheck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK' echeck '(set -e; (false; echo ERR); echo ERR); echo OK' 'OK' # 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' echeck '(set -e; echo ERR $(exit 3); echo ERR); echo OK' 'ERR ERR OK' echeck '(set -e; x=`false`; echo ERR); echo OK' 'OK' echeck '(set -e; x=$(false); echo ERR); echo OK' 'OK' echeck '(set -e; x=`exit 3`; echo ERR); echo OK' 'OK' echeck '(set -e; x=$(exit 3); echo ERR); echo OK' 'OK' # 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. if [ "x$SH_FAILS" != x ]; then printf '%-56s %-8s %s\n' "Expression" "Result" "Should be" echo "$SH_FAILS" atf_fail "$failcount of $count failed cases" else atf_pass fi } atf_init_test_cases() { atf_add_test_case all } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_shift.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_shift.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_shift.sh (revision 304003) @@ -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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_shift.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_ulimit.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_ulimit.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_ulimit.sh (revision 304003) @@ -1,46 +1,57 @@ -# $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. # # 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"} # ulimit builtin test. 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 } atf_init_test_cases() { atf_add_test_case limits } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varquote.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varquote.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varquote.sh (revision 304003) @@ -1,81 +1,134 @@ -# $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. # # 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"} # Variable quoting test. check() { if [ "$1" != "$2" ] then atf_fail "expected [$2], found [$1]" 1>&2 fi } atf_test_case all 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 nested_quotes_multiword_head() { atf_set "descr" "Tests that having nested quoting in a multi-word" \ "string works (PR bin/43597)" } 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 } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varval.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varval.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varval.sh (revision 304003) @@ -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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_varval.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_wait.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_wait.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/bin/sh/t_wait.sh (revision 304003) @@ -1,59 +1,195 @@ -# $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. # # 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_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_require_prog sleep + + 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 ${P2} +S=$? +if [ $? -ne 0 ]; then + echo "Waiting for second process failed" + exit 1 +fi + +exit 0 +EOF + output=$(${TEST_SH} individualhelper.sh 2>&1) + [ $? -eq 0 ] || atf_fail "${output}" +} + +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. - cat >helper.sh </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 of first job failed" +if [ $? -ne 0 ]; then + echo "Waiting for first job failed" exit 1 fi wait %2 -if [ \$? -ne 0 ]; then - echo "Waiting of second job failed" +if [ $? -ne 0 ]; then + echo "Waiting for second job failed" exit 1 fi exit 0 EOF - output=$(/bin/sh helper.sh) + 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 } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/crypto/opencrypto/t_opencrypto.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/crypto/opencrypto/t_opencrypto.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/crypto/opencrypto/t_opencrypto.sh (revision 304003) @@ -1,272 +1,276 @@ -# $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. # # 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. # # Start a rumpserver, load required modules, and set requires sysctl vars start_rump() { rump_libs="-l rumpvfs -l rumpdev -l rumpdev_opencrypto" rump_libs="${rump_libs} -l rumpkern_z -l rumpkern_crypto" rump_server ${rump_libs} ${RUMP_SERVER} || \ return 1 rump.sysctl -w kern.cryptodevallowsoft=-1 && \ return 0 rump.halt return 1 } common_head() { atf_set descr "$1" atf_set timeout 10 atf_set require.progs rump_server rump.sysctl rump.halt } common_body() { local status start_rump || atf_skip "Cannot set-up rump environment" LD_PRELOAD="/usr/lib/librumphijack.so" ; export LD_PRELOAD RUMPHIJACK="blanket=/dev/crypto" ; export RUMPHIJACK $(atf_get_srcdir)/$1 status=$? unset RUMPHIJACK unset LD_PRELOAD if [ $status -ne 0 ] ; then atf_fail "$1 returned non-zero status, check output/error" fi } common_cleanup() { unset RUMPHIJACK unset LD_PRELOAD rump.halt } atf_test_case arc4 cleanup arc4_head() { common_head "Test ARC4 crypto" } arc4_body() { atf_skip "ARC4 not implemented by swcrypto" common_body h_arc4 } 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 camellia_head() { common_head "Test CAMELLIA_CBC crypto" } camellia_body() { common_body h_camellia } camellia_cleanup() { common_cleanup } atf_test_case cbcdes cleanup cbcdes_head() { - common_head "Test ARC4 crypto" + common_head "Test DES_CBC crypto" } cbcdes_body() { common_body h_cbcdes } cbcdes_cleanup() { common_cleanup } atf_test_case comp cleanup comp_head() { common_head "Test GZIP_COMP Compression" } comp_body() { common_body h_comp } comp_cleanup() { common_cleanup } atf_test_case comp_deflate cleanup comp_deflate_head() { common_head "Test DEFLATE_COMP Compression" } comp_deflate_body() { common_body h_comp_zlib } comp_deflate_cleanup() { common_cleanup } atf_test_case comp_zlib_rnd cleanup comp_zlib_rnd_head() { common_head "Test DEFLATE_COMP Compression with random data" } comp_zlib_rnd_body() { common_body h_comp_zlib_rnd } comp_zlib_rnd_cleanup() { common_cleanup } atf_test_case aesctr1 cleanup aesctr1_head() { common_head "Test AES_CTR crypto" } aesctr1_body() { common_body h_aesctr1 } aesctr1_cleanup() { common_cleanup } atf_test_case aesctr2 cleanup aesctr2_head() { common_head "Test AES_CTR crypto" } aesctr2_body() { common_body h_aesctr2 } aesctr2_cleanup() { common_cleanup } atf_test_case gcm cleanup gcm_head() { common_head "Test AES_GCM_16 crypto" } gcm_body() { common_body h_gcm } gcm_cleanup() { common_cleanup } atf_test_case md5 cleanup md5_head() { common_head "Test MD5 crypto" } md5_body() { common_body h_md5 } md5_cleanup() { common_cleanup } atf_test_case md5_hmac cleanup md5_hmac_head() { common_head "Test MD5_HMAC crypto" } md5_hmac_body() { common_body h_md5hmac } md5_hmac_cleanup() { common_cleanup } atf_test_case null cleanup null_head() { common_head "Test NULL_CBC crypto" } null_body() { common_body h_null } null_cleanup() { common_cleanup } atf_test_case sha1_hmac cleanup sha1_hmac_head() { common_head "Test SHA1_HMAC crypto" } sha1_hmac_body() { common_body h_sha1hmac } sha1_hmac_cleanup() { common_cleanup } atf_test_case xcbcmac cleanup xcbcmac_head() { common_head "Test XCBC_MAC_96 crypto" } xcbcmac_body() { common_body h_xcbcmac } xcbcmac_cleanup() { common_cleanup } atf_init_test_cases() { RUMP_SERVER="unix://t_opencrypto_socket" ; export RUMP_SERVER atf_add_test_case arc4 atf_add_test_case camellia atf_add_test_case cbcdes atf_add_test_case comp atf_add_test_case comp_deflate atf_add_test_case comp_zlib_rnd atf_add_test_case aesctr1 atf_add_test_case aesctr2 atf_add_test_case gcm atf_add_test_case md5 atf_add_test_case md5_hmac atf_add_test_case null atf_add_test_case sha1_hmac atf_add_test_case xcbcmac } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/audio/t_pad_output.bz2.uue =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/audio/t_pad_output.bz2.uue (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/audio/t_pad_output.bz2.uue (revision 304003) @@ -1,998 +1,1035 @@ begin 644 t_pad_output.bz2 -M0EIH.3%!629368,\S/H`A(]_____________________________________ -M________X)/JWW=]LJ1DQ(V-I-I+:VTPD*VTAK31))5F;9)60#$TK+5K#:U* -M-:*D!0Q6EMLA*CJG75+322@`44*+KJ[*:U%`=]N\V@VVF]YP#E5K*A78P,S# -MZT/(+W<.M[>RM[LO9>]N>KVVVVU[MVU7+6MC5M6U%;5E -ML)MD:LTBI`6RBM)!"VL!D))"-@4VJM56U;9JFF@VK`!M@#+8S0%3:-K6VU,V -MQK&@`*!FV;6S9MLU5K8:M9K62MA;`J:+:(V9I2W6NUFUK,VJ:NMVZVSK;O96 -M[N]W=W=>WO>;6M[W;W=[WO>\Y]SN]#??>>'&P/6$RM"O;IU+34 -MFG(=*=!IK(YZ=U(J4%`]!0#1IC5NTN.DU1;44FHUEELQ;`VK&UJE(JJ:8 -MYP:41,@3``T!,"::&F!`9#3)@33331IH-``TT9`U,&@TR&0R833`$T,F$Q#$ -M8`$T9&C1IDR,F(--&3330#0(-)(1H`!H``````````"8`3`3(P3$P$8!!HT$ -MP#(TT:$P``)@$G@)HTP)IZ$QI,$,`%!II*(3``P8":::!&`F@$P308@3$-4\ -MP1-3]3$CR9$8;4U/*&T;4F3$S2:>IDR9#!&0T,U`:`&AZ)Y)ZC0QJ;4]0S4> -MIH9&@"34E*2)E&R>I[;8$CTH8"3!)X4]-,30:!&3)J>BGDP*::-I,AC*:-#0 -M-&F@`!IH`:::!D>H````````#3(``!E2@3Q(T8--#0F@D],U3\03830Q4_$: -M3,)B9-3T:,"(]&IL29Z5/3PDS331H:$\*83::9)ZGHTR>B8JG^FC0&3$T4_1 -M,FT9&2;:FAJ;)I,:&BH)-2DH04]-4_9MJHQGFI--$,F@9)DRC:;5,T%-E-JF -M]4;PIZI^H:GIFHU/TU0\DV(RGE&F9-BIY30]3)^J-/4_4TC0S1I-!ZGJ9-,0 -M\4T9/4:>H/:D>H'E&0>IH>HVD_P'^!QBM$WZH/L1P,O'$"(@>"7Z["OJJJC@L[DDKWX>; -M.I?\7_4S95A_"B0(B%P@`M:^O>ZN;N>U[CV8\/P,*1D\ -M7FF6F$[Y:6L3:\[_+_H\CA[6TL6?19]ONV3@J2HH`B+%I;W -M(>S39[Z?/-HJX`Q!(#:_XGN6K[U>EW4[>PI':-BK]?0U_-QOB$O00%%Q](-)Q'ARFMZF:4`2*C^K!H/K3RKK] -M-!9O<*COJ&H>OZ>?,I"7:06C:]$#!7=16YRM^YR+4QSHV:?UYS-:GS>'Q=RQ -MJZ,5W7X32SQ$BH3;@MD0(9(:S=IYT\NE&+^6.SB+>\:ITL]=6UAGJM2M)W:( -MJL&O*9A]EW6N7E -MT$1*_C_D\Z#.K+*R1LK?8&:X&741@Y7;2OI4^=RX&FBJO1*H5P0`W[?B=1S] -MJXQJ3RQ_#P1&\SW>R<6MHC1*ME4`1/!DV<`FG!NU#,,JP_VGKDJ-W'7A.6-2 -MH`@6BQ/H[0!?G+3#@BKUE&XG'87&!\'ZM:%FJ1+QPCSS0J$0`\ZO.D@Y?+5F -MJA&]I_8/'_YW56@=6IBWCI<93`!/!(_%C%.;ZLRBTGM4?'A=G=<>6D:!@&N; -M=TH@$3>I<;'M)5'3VR4VAD/M+707S3Z(2YR*8E+3FF@$7C[M0Q!NV;BJ(CE2 -M-&U^="FV54K:M?GT>6J*KZ3/ -MO_/9:G327;0T03)*,[RJK)$0%5,/RR65<-0YN"ITIRPN^UD^_^(W,^WOR/(4 -MVI*`3A>M3S""->70*,S":;ARXQSC5TV0X50Z)=GTWO9TS"0#C_CGU`UFBHF3 -M+;]/P;'"@*G:SJH4G4W"\"1=+^O,/M-XO^%*VYMJ>?VUL)0`1G[M:"=>*)G"?50.UXBV(=QK'_H -M^S&@@09*)H!`;`RL74"ZY1NUEI&<@6?):>8W*IZFE5UI/ -M1R(YCJ,..G[%050`52\01%GW-7V6N6VY)^\7"N;]\_OL/L^^W#5EN352!#:Z -M9Z$:0G406)N$S-QB*V?YG;RFPMG)`H#IT^ZPV[#EX/X[HHMB4''<*2RS(K.B -MH*9$"IDAYG.-6D+G2KB34-#K?6CJ_S/ -ML+"GC(B(AYESJ5[#I"'8+FV9)N83_1DF::W>MV<51?SO>O^6'\9+L^UVR&?3 -MD$VR$H2IG/^-,G_SHI&;*/,GEHV@[VK:/2F0+4G@$.&F)A`'<)WDV:A<-ZHC -MV;TU1BO%#Z15\%HR\!^%,8GZ#GP)J`@18-;CR`L\T>D)YM&Q)B:0`_ILC@";7*VII!'K'N_LIANE -M:[1]QOVP<_1HM?;=\.;VT^SL_5UOT9HAI!)BL-@ZP*U@6K=5WR1XFY5YK+N7 -MX.ZBJ)B75\@BJGB*%?!%I]3CC6.TB[8+O*9QXU-IH;F;O;=B\_!G-MV_VU3G -M9R$ZX -M&N25R7JKAWA;W_,$/KZ]1 -M`!:>@T8(OG%LS"]ZJ`'"B-K/PU/HK6&U+#G%\>%L9'7I.*YS9);!$-9U_-HY -M.O!%_0W\5+LF:SK"(O%HM@IMD_MA?A,O&G*MR@1%P:$$*E0\6FL)>74^?E(5 -MTS_S=,8R'-MY^=7NN)A"VO(GG*@(%U<`RJ`#/<@QUHM:YZO@<"*UO.HKR]K> -M;DPH*5+;*`!!OI-N"G'',0\WP<2=5HB'TBO>A;P*KK-&S4NO>:O?5RN"(=O? -M5(!3:2.+`>V(H(AR<(^)5PMK5/Y<6OXD].Z&J8R2$4E3!,!-82,ZN.&UR*ZNXQ'SQI[EH=,#^6*">)R"MTI!&IX -ML6"=@QS3A&ZZ5>KMRS+ZKI29EHO,]GI*G76AU_?.-=L2C%NZAHE#I):\G`BA-\1,:"_GFZDY4OT^U5:S5:8=J3O>9]N[2J@(A7( -M+"?@`"1L:*6!;?\TO*],-NG:>"I]*4]UATF[$G6E2``UOB<"(E21ZG0]6%62 -M4?'\1N5Y3B;O1UQBS6`XT6"KR%(`!X^:Y.D.$IJ&5X6=SO_1;NG%W>Y9TUC, -M["W_2#@*!$0I.!@Z-[V7D("$\ZPS/T*'#=1WV_O@T -M$-1*H(B;IL$.9"./.-O5G+\)Q<7Y5V;3(6,WFN7U%2TU2B1`7<[<86JV5T`! -MYQ5;+_4NRDMY)27_;Y@LGM@>=!E$C7+OB5OKYQ_JVZ^#:KA`AF][SYKE@$Z. -MKL+!<"V'J/;-CB/-+M6!@:8J?=5,$7*87[_H;V;D$6;\'&B':[GERN[CL[)C -M'Z\:.7UY$N#3O/&[;;P:US6P0&FMP0]7YK.Q'-ZHJ+N8GF6IANBI@R@ZVKW] -M/[?A94->@!$*<$2HS*@9*CR,JJW84EL86668I9DIC$0U3R@9(&/XISJ;O<,K]U%BU -MSZ1W7VY;)\*DBH@`6(!9-550K(H$-2JAIS(J=J1!$\T;+@I!$.5]6T@4[H97 -MLKD='QVHK%;I1^Y>)2=K'"=PC=]3*WF\Z`B`NY-GO"%@.XJNS)Q8IWM< -M['Z*7@RNX/$:/SYG6YN\O1LH)#9?\NSQ)BUG34?L$;J9V=:>I.]>RT66G\VN=KW*?VY"J0`L>-A] -MD$.KY:H;B-Q<6ZKG#LK>VLXM`Y>3CT-TG@`2_8(ICBUL6QR:8RTY4#7/[N'D -M9+/?KZ6RD$\B(,]UW<1J>P"7,XXK(?KJJ"'B32W=5.RE-ROA4@LY+>NU500$ -M)[_KYKSL`@-0%SIJ6R*XIS2RZN8:/J[80?PJ*:VT,+G?5^ZJ"+M=KQ63:">: -M00LGQX?8;#OBE5(N'U/?^4KO_1(IP("^B\&D]OE($J)6^%GG@KVU7H:;GJMTH`B%P"+/VUMXL -MM`H,JWO;._<,SA?!GAWG%^ZSS@?9_%%2J``!C22`U&2;6U1TD[T/.R3%R]S: -M@RN_';NSQT%-!1HF?S@Q\DWM``,9R&4@SO;;91IS&.J^E3UD5C\=.CH)\\T= -M[BL)(Y-;*^$`W/S8+'<8*#\UW']]%D7*MF9%5]`]&4HWJ!Q,I,1*INU8`%[T -M\@7KRUFYK"PYH&:`?>L^_O.'+TSL8[V,`R[MEXL,$]<3JV1`?UHY'7@%;BVZ -MG-]Z^PL"[P$-'N'6AU)/(A*O(!*-=Y>-`[JY&EV>FY2S;U*BV:C7T6/:\C?MO@:-<^W5=.T\`Z8W:;BLFE'.9B2X>+.=!JVI!QUO>XT--O) -M[=ZS2&L>69P3_>8&HD]YO%24B+%7M0?K2(N"%2TTXV+,IH&$\O)OB1_A(8AQ -M7A.!:]I_@Y;%1``'K9:V!B,NF``:OPF?!9S[A/3>LS%+Z!5TNL;^]CFCD_Y, -M3R`?(A$J`1!1BZH]R,&XRWJJ?G_NP2M(=YJ*0=,,S+98/\?O7S>7'U$XXV.XW%N\;-Q,`T0'+$5Z;F&ZZA]@V(D"BD?:`; -M=S>)A-.=D9J8S\+(1K\R/P?E6O!"J^?\W-1#\S?1>Q -MS[PV>Z9M[RE3)>NX2DF%GF5JR+.Z(2BI22 -MB;KN%RX7I/]0D`$N8K5Q9'"!?I>K'$_TQ9Q@_U<,':[%6RYA^"9RM.@_+>*:ZQB]?$?ZJ -M,QBKG_)*"7KO7P(&T^/P$'#"=8\Y)3C)).KOW;W#$ZK#8%*U7=U2QQ_[_V-5 -MB("08I,$3D/,Y_O.X$G?;WRZ%R:T#1V%)+(O3#@@-#DZK[!]4DU,=5X&GCA;22225I!AS0\_.D/@*J67P1?`GX4NB -MM+WX?[#5IV$U5-6;8B#`3/Z/GTC>E4``\&WQR(?:\Y+T'VG?%7$].V>IA\5= -MWKZ?7J0(/?8[MN@DR(>-$T'IC@M)FG]4#LE7.O&OWT77(2(.6D``T&_GMEE4 -M8R)HJY%Y##J,/(N>"Q9#JM*QF?E1*9`LGG>[R\*P(`/47`4QF\_/L\4-TL60 -MH'?1"-Z>'882<1"DIK($5)0"A?U((?& -MB[RFPV#OB!Q:W`H6^(/^ZR")'HZ-`0`X_!Z,WXI&U#7P8%4V[YE\Y=UE^M5W?QW-TQ5[_UNM`@,QV -M:($!,;*%[OR&35=\:Z;3E4+'CK]55]XX5K>J?Y1(%P_?;;.&KB(E]NE$7Z/4 -MA^KG)K4,F'5#[X'??SK)UDVI3R(5]D`0MK5=V=GT;@W=;7>OF39G]ED7^XQ7 -M/S"*A?84/HU@@7>T2CQ@"O6S4*QPQ9BGF512;):"I=E5_#QA_J%,$4^1$%)G -MN)[OT@KO'UL_]22:=PV&TYH\?N6X9[;YBINKW3^#4+8!:1YLP1;6DY*P)968 -MT!52)%K7@9,9.4]4UDRN52/\Z@1`=S:."8`0YW@B&9YL,7@R69XDD(!Y2##/ -M`K'9/WK+RW(9`2IV[`+LULJG_2*#%4S>=T?OXZ$PI!"5WUHS7Y`#)\B!38#$ -MXJ]FWZDII/45>LKFO(A)*BDPT/G,\'@/+0`"*^;E3A:S53A$-1VD##4S_,7< -MKO7Y^ED$4'[&)0`;HOP8Y-K0S-6^7W`D]'6U3&QYO@LG)#+I\#8Z]3 -M``[6+`$CT2?-=6_NMD:G#_R=:F#$ECZW]O/]S`25;1]0D9S!URG"8]HVP'8H -ML>U>A79$N1B)RG[]8E!+]9V9!O&!B]M,&]8%+P8^(J=-:MDHV;Y:#:-]SO=0 -MU>-O%,`AE^1!SNJ!%?8L6>;%:1U\^]ST%C^I_VT5[J2EM52T>V))!8/8!`8LCK?SQG!%$DQ"H4&C=77246E/XR:!1 -M\N^XK%W@"&)^K?!K]QBL-P/N)+CY!!1XYZ4K91D+;ZJ)`6_*(A6T6JG'01$Q -M%;/;.^]B.%WHD=)CB*S?IX!>*9;'H@0\3YW=O%3JLIOBMLU?)Z2/Y.-=>U\+ -MN_M(U:&-DE0B'?Y,FT4Q$66G?[7-W0J=-C=G=S^G05M:S)9"WR=THUP`+XSR -MB]P' -MV?/-X,(,J`@5Y5;[Q[Q(8`0$BGM]Z^;56<(B/=W%D5XF@/9*^KWZ^6@?;5AD -M4R(1T^YH^20+*X4W_<:[4RZT.KJO72BYYV(4?)6XRH1#!^620);6EKH5JH(@ -MG$.O-G1RZU_$?\T\`F*$UK\`6QSW$V+/W5-H?;P="7=KV]5_0K?%2!#8WSZ" -M(=K95/UB]E:=K.[Z?_P(]LL[+D.P4K<9$`L-.$K$!FNLV<"/]0`$"4VO1[// -M>Q`R!4#K+OXX'N4OI>T@085=/J`(N<@A=H0(0L+U+WF17Z0=1NV+?R9C2T.] -MH>[SM%:5>@6O',,S,K$0RCGRR!"M0OU\5W^[VI?^V-4L=%);).JFEF^G`J`$J_#?2-UI01;`(L -M-=>0(O\4]73WL6T*MO4MX4[VKM-RH$"OO?[IF%(@,TJ<;/A.4^.S\O;L203& -M];U^M>4]\7+,)-UYX#]20,""YW*\4W)0EXQ,B<S+6[81RMJ&.OA1/=]B`, -MQ<6E>`!44N1]'2Z.G'FCO,Y1R"AS?2CMUJ=M^V_X;7.9Y``4UZW3N``/?$^? -MUN/WV[YVI%W`C3/%YYPZK2T'5PZ2(B$%^>5(@':XR/PB*=]VG'"W$7>EFRXRN66F&E5(A5Y^Z`(=968%Y=U46D3>'NMI+*4#&[/5[>-6E8@-: -M0((WTR>U@0]*7X;X>$H7Q22X4:BT/K?R3@(1J:^""+%'UFZ[:_&!#7DD_X)" -MVV\79J=PO$U\-Y99Y)`:M7ZKG#2CT=MSUV=X;)MV2PB-4S)G24Z^0=,5F&FN -M%3I;C\.>V/^47`1#$T.'W.41%]'S3=Q04:A'W[AUY/T+#E9*)$ -M$K]7^?<^<`!D(_N.G.P#%3;:O3EN@\LE(+S[E^JL&733?-`( -M0K/ED]OP79,C@"%NF-_]V^0-< -MZ6P@N3OB9%8B*VZG;UX[_,`(9/M0F?<$`)]!48ENTNK1J^KT:U"\EAHNTZU1>;F7">""]QN?,1NV$AYO$"( -M5>4W_9\Q_&MNY_L/;TOCP:Q@D>G'1RZO=95!14Q1?J"(+L\]YGY^=@4J0*\7 -M63I,2.G69B> -MTL]SD\HK-A--A.>K:/^F2CCL:V\!3;6)L/$`@P8]>H(L@"@>\R0S*(MDGMZXR -MNFE08'-''9/U][FBFF@1G!9VSW&/T/=9$)I*W@7.-LFNT($$[TT=#=^=5;>1?N-PJ -MJFE9Z55TBG"PVD;;OJ'X*W6B`S\]S]^"(3'0I;'JO06]92\N*V0-++C9,=I. -MI.5%=>A\UE,JY`.EIMPF&9]RUF-"LR^8#?@1\JN -M+M_!=WR_A.7Y=8`*:UE?ZR(#_EOJV$8T^YLU&',YJSTJYF[1IY76J%AW"B1< -M'/\JC(@/TS<1.$8SXL99,WI%.R8IN[O;UFI5(Q.!!K!$*GWP,3M=S2IO>Y&6 -MJUO'MQ\9M/;&J\84\&J7&ZG((W4OW*;R0?*C/?`]GNLF=LMUQF>-]-!_#PM= -M]M8R8"B((DLK@VWRS-7YRD9WX,BCZ\LB5#8RLF(%;A5D!$*_(==E[/0B -MKEDZY=*VF3[:GY#QQN*@01^UU23@#VJ@(9;E-_-JR!">Z-M1]_CO79T,UVOJ -M<7CV -MXZWE)8`H-MD'M_"<`%3HL+K2``4$ -M?O=[_II043;+9ORML+!YX$&K>%2(HB4WE;4`BIFK1*W."MU%%GU[,J.]`S\2 -M.J[57M!#(B!9R"(@5'U[_OUNQSF)@[?AXOFBQQFU"D+C?9KN-C=I$B!BX;+X -M.R5P03;Z>!$%Q>XEHY,]-E:^M_6<7T[,<[2KU,Q/;N]R&I>E@$_<3@;E13B( -M$MAE[74'7JYBNHW(C,%5"N`/?!*OU^=6ED""&;>W -MC)\7"9C9."X330W+=+#MUJ+#\M_=40`N\#O8F3($+&OW&CKUN655SEJD;OF^ -M;2=\A>DX0!Q0QUT_+<'&A#`#NX*RZ`0O'[IWGQZ^)^-;WZ'I,SDYM++,JI`6FEZNG2"("QW,EX^%EDBQL`Z;.2V\C884:S:]`G%$4'YO: -MPB`4?B\\6/IEC!D8%B\2/H&@U-KQ,MRB$,\1*^<]/;M=XL@@6I9V^"QT93W: -M[Y#=#Y8V'6.*LY99X?+U$U&^W@J*`AZTNST47H01%_STWZ+R+B9X5<=S[4WD -M?EJU@,.27;_&QCI<.DG$A><76W7UBJ,6B!.;YH[C;K"OOB(@B9C\NZ#`KZQ^ -M69US2F5&@UQI^BYQ(`SFVR6UK-(@("H@&>\4*.`Z9$0SGGB_/H?#H/K>>I66 -M#E(<^*_!I1=]$W[&C?OJ@$&/M\F4GE;P?*@75*KC'"?H.:Z-U;HU0AY4*?/8 -M>K(B"=G-&K;!HW&#@?LWSW^&AX-N-)3,P&16?[11`'^B)[6D0&M??UVX_#2I -MK;JFEY2#3S,DH)8;<_VOSS\1[VF<7[BA!`JRUDN;I?1O8ZXOK<_KJ'?5W3\G -M.G=XJTRT:DSV"F^]XQ-!T[-65E( -M%OV#6B]38E!_T -M[][;B&\7VG,9()1_78^$U:"JX"6K]K6K#&J@O5I-4P?GV%F:!,;CD&F+^I*[ -M?U+\C)H]6FIKBSW"Z0/ZH*30$`UE!"IK`6-'ZY?%0/NGGA3I`IUET[1"?*L0 -M'5[?=5MQ1,`!`F9-L^NSRM[V>;(/3[@/?`][C<_/2U>PSF1HWU\"Q1RD.AJ7 -M'?V>.!PN1E]%3SO1H""7K[9E0'6;QN7C*E.FZ+I,X]I&-ND28M7(^//T"ZF\-+V#*H]#2,D+D$\@G=3=D"*&O.0_1ZM],YS.Q@^I -M>GU#)EM2@RY5/EYAW6I-!!GK(QE)\JEPQA)#)$6SA:<>B:=/L;&EO$I]$"G% -M>KMQ3/Y$`Q('#C)7IU7^4>TI(AE:>@U.U8X3`U$MW5!(-IOT*K=^[%/.B45/UV -MD8G]4>N-[+F&FF82)^JF$ZBO:UU&2!]W#QC&_>F^R<;%S5)N-2VN*>&V0\'R -M]:1$`$6-Z.PQ0@/&\;>RK#'X=-,545(]M[V'E:.IDNC^YG/^O85GX+$MQ+E7JQZ%RJZF`75RX/'6^\;T0`!%S]%C.FZ^75]SC -MXEYF,*DVJC,KC-D7R!TTY/SSED5C$Y+-,X-/&7[5'$DXSZID6&Q06J_U[]&W -M%C#Z74[B+JA5N4&Q6:\O*Q6:+TY;[TX`*?QO+T;JRJ>!L]<`!<95:[2_\ZC#>1U -MG6#4F]Y+.@3#<7>86G%3(//9]+>@`(3<8QL_\;QA=;)-RE\AY)5=Y!IY52EG -MA\*'55#J1`!=I85^WU.;G_Q=VG79*G89%1_>3]SN\J4%AS(L;-R$O8LJX"L, -MSW>P]@B+3H6M7TEE<4Z/^EC!&BL?5(U6K.:@LD#)SWGSPF?;_'\I#Z0(G3!R -M]@O=M$IY*I_V4?VE*CN>JOZSG3"DD4"(EMR5/R_/VQ*DHD`3;"]JXZCK4_-2 -M[S%W>S;K2VM)*DK9PQ5"4#AY/!:_Q:J_^.4/_X&`@0ED9\LU>$KH.-X!LWV\ -M3H-&`W.UH??+DTZE;Q85P,:8#'!!.[.CZ5[E;')_BCSXHY9)($$Y_=8G[_#3 -MR*"BEF;+!77`[!<4"\YAP.9V9EZE$H@`&A*"E47\5_E\M,H^GVR[NT9Y>M[U -ME9:M?@UTE,%A,=+WM2;S!$Y/K=W&5+1:PU+16%-<'\HL7V;A9/]'JTUKS=)R -M%%..\LU+2LL@//Y$1/[(\UQOT_>`],HX\:-;SV4;T5))ZUJ"FC&!J(X"S,"' -M`CIKC4ZZNLJ61`AA3*:)MCRL'/LQM"?B]C'K6DF&% -M<,8&,8P,8B*#WED'1U^222>@K]314[E`^,R`?L^WD%L]1H*,B -MM.AP#P5)X!%)J3;E3X*9,V^S8K"A24(*Y\:12`!>4=,H004(7YH?=8`\A:&J8L9\J -M2)!?['A8I7(2(RD=4:NL(4B!#FK\V%.+#=G>)6/7M62!')**!';IM9SW141@ -M7YZ[.XF5%@_(#>_`@>;HX$W -MJ%^S_TX15?":L&/-'I>"?5GA2YT0VWV06#"L=^)R;F//*`K -MKKT@\%''`1=\QHF0@[W^2H`\[R'?RQWH0]2>('^+TV?16WU,0<64_'0RC:4$ -MW+(Q`,&0!M(*PM^4_8>Z7T!`7--Z$UDMY9`0@*K2+48SF#RMR>^UO.!1'E?P -M*:^[C-WI-4WB$@ML0$P\6FQZ$7ZP.AM<1:BJ\%(1RPSKR] -MV.H>!"$U#*]%8(@GI^U*86WRM#VN$N9_?U!T$RTHA\1K>;M"`5)K2BQQ'I4FL< -M\'R#S4CQ>-1S^+Y2GJ$PAXZ?RY(76 -MJN1N1'O"Y(H9$M,6V':I)0X3=FS\$)\P]5B$J.N2_.#VYU>TER!M&9E2BKC.\80#LZO71W]\UGP!L'5L-\^B^^JYW`!:/WT6D -M.D[:L<;PHF"=(6&XC<7]&@1('A[1P'9TUNOU`%I%YOM'P/EHLKS++Q>$B2X- -MRO\:_73A5A4=*L\71_*4PSBZ,O:%FF6V/$WXS&A`K:'X\4^,)_IUK[`;9&W^ -M@U$8>!6[5;@OGLZ+Y1%^]\O:T:*03K8>#>]4X6!HYL>I6B[_I=7XB*&21)'EG27&A/%_YZ1^2"$/H5(Y9U59^QKW1R:=20X -MG-[/RQ.O$`3T$^G"OXC2)48<'^S$N7NVQW*'7E]`]>ICVZC0BU^XZ//49DIQ -MIYMK/9@\69A':D^H*E^EI)EVUGQ[A'A3Q,?Y;@-_IU*#B'L"5_/;X&M0A#)G -M2'",.?/->/YMS]2=?1_$^`(NOZ$KQ">,*[.<;HDEC&V[7T2B9'4'++,W4:L4 -MAP2+/:!QT`S?1NZ7V:XS+$'19_9P#[WQ3N[=_:=`E"W#^M2$>,U<] -MCCDJ=`R3&9M^P=)%8(_^@5,0,YLS1D+VX -MB"0NBQG*CR40N(B>@&CHB;7EHX(/7IP&WYKXA4"$7M<@2SQWSINR$O67IRIG -MI:FI`0QZ<;SY;K`2K+\CB=U:E;7L`HCZ=8X,:Q'[#3WIS?@+?ZO3GTS*N?DM -MH1=PQ/Y:7,AQW1H1-S729BK:J#01*W`K:R50HJA`WF(DH(L.F";C=WYDT9#T -M\V%:D(KI6OAU+&*U!T@JE2VN.BCH]S+L`7PO^HW+2%-;.%]@HG9\.`,$VKQX -M%WAH)LR2+J+7XM5?GG"R@F=U\OAQR&[-;[!]Q*_VEW -MG%6O0&4QVV!U'G`3_\GVR/B'1._WPDEQ8)B;NB76D[B3501)7:A8FMO4:#P0 -M5UK?R/#HZ[12_W)A73Q\T0KX/S0\NA9P*#^V93Z%H]A!'*>W)BX]:T$ -M)"RPZ3IOQXHT%9];7_;@[!<2[?VA1K3>9-^,-&Y(-,KS^OGG+5GPYVU3^=^/ -MC:Y(<@O:Q?)6'*):@C<>B86)XP+++-0%GX?UY3OA`;TJBLL.1`];EA:W@H1+ -MFWQ5ZU`:XQ%.6NQLI4$I:K4M#-L2$#E5Z;6I0+N:(;UTWG4H$"@G>EW>CAFS -M_^,1KGV^^Y%EU#_RT6R!;+P)O%.C-5:D0>N8CNIV?H&92%D0E=99K'J0@OH? -MI\:R:MSFH(?'=7OF^4T=-3NOPN<)?F+9SG9I^Z_N6P7&Y#GKT[S$* -M#A++4^(1<1P\C&0UAU,I>8Q9PG1B]C\VRX_ -M9JP&[6SYP*.V0ZX%@]2T.SX`E+EY077*6$]FQM##@K7Y^@X/DM@>A:G;@^^, -M?+U1N8;'*;2@U<"6C=+]Z1-?OE1`";C],MJ!.!?`>K&8CP= -M7GAO3D05MC\5$_,&%";AV0@3.M4`-U.S7;E%@7WT?:25M]7NAS"Y^2QISKK_ -MH+]&5V?3?+NMH0W/UW6_SN"]37@2Z08YSF']P'%`B'?]G#$6DR<\UQ8#SI%P -MXI&$\FD%Y<1U;;N9SV@=UE@D=&B#P3DR6`U+3FMA"(LR?%(B3Q#D'3YP#&^? -M0'2B5'(?Q&$T1*+CY?^/I)C&`1J3>1P+1+W_D)\(3`#J)](_A+&"!^?SU]8? -M"28QC`P0W\UV'Z[,B!_B].@W[(>E_JH(=DP6$^DB0XQ`&!&'[J;T?/OQ!I>C -M@FZA5`_UVSAXP`X;H>/?"S,,UT2QS.WVRQ9XI>\PSRYGIL(SI+`G`KU8F,M/ -MAT)KJZ;9$_UNX)_DCN4$`:?,W=.O+I5?V`,N3W)IW?CA/[UBW`DB,/4PA/2SF6H -M6+7S$O]DOWX,NM7A:Z`\>&))AA*C==8X=24JS!`LTMRD[S.*EF8-D,-DD@:* -M`=3P-VF4A^B/=RWXI2,+*T63O'5DW0&>5S"4AHZ*0BCHZ==]0M4G;VF*!^\6 -MPI&[M#O6T.[KGZ-`2N*L9%E,#CYF@>0P%A[&%'8/X#;[+,FRA\YXGS!E"^M= -MLO"?+QDY1*I8:/L"]I[_"ZTI('ALL45>)ON$!V>$]5WBOO08KW`%3&$IT7'/ -M"N:MRTF!W]L>04)N8(4:*$5SZ_2-3?X_/QI&'&"72U5M^'KU[)`^T7ZB":X] -M6&@+NJ5@NS;>@E'L?9ECR1IJ?\_++8Q@A%-8W^,W.!"2V5WK3.[4['`*427> -MHF4\&/2?"P@9<34N<%"UBGHT/VD[8<2Y%W!T+\^3@]G0\M(&IG-':+K?%:-# -M_6F.RN0LWE@_X,-IJRT>..QNN(95O?[+9B2F$^L)*^2V_`<_ -M'.S&Z9DGXB5FAUZ1J.!Z*),WD5X,^@?69UOAHIO?"HH$7W'1HAOS/35PGO.J -M@_5A7?%5="PEW1M":87D>>X!)63T;%S@K,'#117&"AR\MWQWE,E(R&YN`-"I -MEP=CNPU'S0=8^1F!;.^4F2%A]Y;F>&=+&A]5S>_/W=`;W\N4@916C.7A[DD< -M$9E"P=Q701:G,KG:^YK2JZ8*]D/U-M -M':[)`D!W-"7GH-T(C06CQWKDTP'MPAZ7]^BV>C-`V9P1C2;&V&3[`M)CW>#U -M8#VWB[FYG])/?#='&KTI#9V.`^5/I<,=?M4UFV%50VUL:CPLU=$5%MF"O*+3 -M&`^'DSEED>LQ')8!5V1O/]DDM]R6%TTL#55QA;M@`QEHE=5L1X^ML58"4]C-\(S0W0H7C0:G\!\T`P>P(+95&J83^.,;[;ZWB2XME-9^4*HZ5_*" -M%I7$49.OATU(>X][?>OL+>]]T.`O1/H?M[KCGT%GQ.#R,[>!G/M)RHX&'UY& -M$"[,Y*#!=N7AM-$8"*:^[CJ:A.,RO4H`'GR7[.=,(7[$;U#'8;4TV^9:P*_>LI)"I.8%>;`/J`\#T$0ES"FT.H7 -MJ\Y)^XP[;^-2UJ1M2?3!JS#";.9]Z*L=37:E=EP`@^GCB!Y]2,-8@RZV3_+P -MW4.$)`2=)\).D`F*<4MV'YX0^3H7X&U)A[->$]HTP-*9]_R\]'&L]'V3+K9K -M\&0S2PV+A%J@W2,.Y2=276YF0T-:`YK7?H:/Z,5;GC<&?O#]V8;?M/#6EVF( -M#5TE8'F_LIMC[/-WTW)?<44-@K/E3)BDH/L??^?.7X0ORS*;M3B'9_ -MZKVX<)B3!K#%#=`DYC]#6<-7/1!IV.&D,[=KE7/`H^7W_O@:BGFPUNJ[)\@X4MTZT -M&X:T%J2&/X3C%C3_OSFO5+GAA&<#?.`RP_@8E/9%(O6%H8N'0S&L:;A&]P:% -M4+V_2D^;+C1WILVC6MMP^0<(.4)[Q!B_KW7`JS -M_>-=3-"A0FA6Z=^/]FTX;_.]LX&S$,P7=@+BSC(<_I-1I[HT.TLMW3O -MAB$T+!`&6.8@-2LBY,*1//D4\"$7`L:W"Y-@S<_K?*=2]2.]G(DX%#J=4VN7 -M2?(Z7.!02!QS$K]NWLB)LWG*/-S`OW4TH.8/[HX.XL:].'N5>X69DX*=A$%, -MS9V%#T_\P&K5G@=;.BHI[+EO)B;5O_^YWFK^B.+-13E0N+)2T^VDA7+A -MW'"`VRG35`ILVT7YS%;Z`!Z4!_[NZZ2&&">8UT<[`?OU&5+.S],$3<<@YG>$>7'@CCPKCB7)GX%3YJ -M>2S\^[M[J>`E3KT`[@A_+^-==!5@C(*$/GL):0B"2",A%16+`%6+%@`"H*R! -M]F@65A#^T)]]]%8+?WZYE0`PJ(PC?MK/)=LL>"NMJ'4S6"+/#H5)^N:8KG$# -M+3FFWEX'6&1PV?K`";@&G`-89]<*,JCW/&=WZ&AQ1*),G3DZOV!YSOS.G:@) -MQEI+Z(LGU^EGW/@3L)0M_.)#07V_K/%Q#O;'PIV$32-Y]])>_;=JVR+"8.MB -MHNE6*WQX'O@,O^@PP5_O>7E^++)E./$O8#?GFAZI>V:-K1V8/8G1NB&P]+;D -M-J_/VLR'5.#U>JE"JEY446",M2K:(Y8_S'_:+&8A\`G_=60]0WHGW357C&:_ -MXQUA#0D=>U'%V-K[V[(>PB%IC_@P>W@:^\[GESH8WT3N.Q\B_&RV;D4;_1F! -M^N!C<=^@>H\R*OK4M6V#0AS]>FT[4.687DP=GYYF(CXEE-#3'K_#,C[SG:7$ -M77R'I/!R=B8-9+%T78&8P=/(FAP5U^*874P2@^B#FY?X1SC&4O"-4N61PQ3* -M1?'8X&F4EN.PF -M+U2A3L"0WJ3J//YDC\4K68=*=@8M?F2J-E4'A@VNX:2JFR$6O&]?]/\2.G=M$ST6JF\[ -M1"K1\[XW?4!YZB(9TJPU,'/2/\%XGK'4KT&K836D=73KH"6[?O;(X"8%N%'2 -M1>KFL_CI&<#GMQHY30BCNV2+UHG3Q71@?$4@.!Q!XCN(JGQR6MQX@/F`DS&(QD0G&0%`18P%(*=QD(?J$/;D -M/YZ#GX[E%W#`D;EMZ-"GC@8@LVFFK[D$X)@>LBNE+2W'FAOUVI,2O'MF76=X6S4][D -ME#K,,EU[!EY&![\='&Q:CE^]S7B];DHF7N\$I[,S87TCA_['[:?^_/X0F>6] -M6[RV?"38Z5_0V%N\02$L??^&N]1<+7ZNWAJ\PHGJ7N"6!IF?V["%X5F$E_"T -MDVB;9?NV#Q9F)DE-?4H]`;!T`D88=7\,.1>CSK_+:LWHHY/*T6!?ZQK"CTZ$ -M7,*=R$+B/E-/#/E-MR`G1KITJNSC'49,W3O26+.`ZTC(!OLURMI$KIP'J8)VI09<-K1PM%Y -M9Z%KC"Q@0(Z)^VH=)IB'%28NV@*SWQ\-EF_5\9\PT:S?[^,SM4.3S#AR-)G] -M#7X.MJ[V]SM[;ZYXDBTC'),',6>1+.+W%H-+S.'PN6Q-VDDS)4WM#48(/4AT -MX]Y^D*:HW0R+F6R96QTC(\P,^ZQ:UT2'"II,\(_7U%5L;$B/;HBVXVY@#$6W -M!@8P,-28XP)4/O/_E7,1,C*%&0\]@?O$@?DO3ZZ(?%ESHB/=;E'#01P^8?:# -MP>V:3T_SB3Q@'B,<0#PH3*`!^=Z`5="Q=9[$08RKR88_T/[A]ZNIV@R5ZBT. -MQUY$%=SF9][:FJ&W.^0)^U0DRG[!;#!A%BD$YU0J9I1^%EMW(*GQ.VF_2FAE8-+_F[X6N^$ -M>U+.=P-_^0K:]M<%;\I',I'SVRB&H+/NX& -MY38=6B]^ -M^G?]C,NU^F. -MTTUH+=F9*#'G1..67TN#F;)Q8X^_J'W?WS#69C#DG%3NS=SW:-Y;94J3;!]!8,.QADJ -M.@Q5D(9:W?0'8-D.B*JL#I==_^"*/:DQ];FN,FYO&>='RYE):\)PT;EO[>0@ -MD=^Z"1%=W&_D-'4Q_I^>L1]K"N=MLD[QF^7/^&[6DHSRA[AOV8E7=@.,'#!" -MDJJMULZVQX=5-&^F^YS>^]WXY/?Q,""<&_JWTQNH5J@WF@C[FQY4?A1_` -M_4IMFN(1:D:,.GTGU$)3IO6HF8]4'Y1FMLQ%A'28([*+E!M9>(;Q'B.B9>A? -M'!W:L5U*@G5?.N\UT4-G&UJ[&B;T7]YNOTL6(_7/S$Y*K[&I<564J2^T^;TR -MG>OU=*364D10/3"S-)K7JIRZSE4EG9&AFGI%(F2O3KP.]K>G62P=^[W?KQI6 -M/"`W@!X0!!0`=%$NE%8?5,4DH`?,0(@8$,W6`?A('BO3/%R=G!G#QKE[LZ+K -M3Y1USS[F8:,K9A8-]EA;UNVV]]F(.A4[AGW&A.4#G[%_V>>":UB%T7`@=T]A -M(I:GC!@1(*H6Q+7DOL90\29`HY`A].GJ?58A<'9SJ1H_C!24(]>3L+/7@WSV -M!W8_+.^X*:>JZ981ZACHJT7JX\L2JZ(W:<6!0)^;K@TF[K3=FU%ZE.Q"^/YL -MW=01W'S*@I"CC4,K&;G_!M';W1]QPWMKG5(^\&3XY$(S?Q.]1BZ+7N(#KR!> -M+XS$_[YS3V<&*`P3D:(45+1PKJSGI^,E4N@2`P/ZY."=I5 -MR@HW-L#:^3["SRD#3.!Y.4@CO4:93H#F-K^7Y9\9^HKV?E?./"^)\Z?._`G, -M>X'UTZJI^XJ3YJBGS:J0H4144160_B(2=#YU?$YEI\)A8.5NGU/SCYWA^LJ# -M!Z,#A;R$T-[7V!O((RHW2M^GKDYU8'6IQ_'OW&>@USA6X31S>1C==W-.^'K/ -MOF:'"4_F\&(B7MMI -M-?01",'5/Y3FDI[N9)][S@)(>EB"2S.M\V^N-ZZXKJ(I.GUT`:WG&AN7S#)B -MCXGE^^%[!*'7:WN$?\LH_Q+I=.@1!0LHR#IT]^BQ,3+9NGU9$''G2;8GQO^- -MKNU3#O*1,_/TT>G\%[*#A817^$RXOL8\,D6CR\Q-;KV952D7)6GTP0N7#'+4 -MQZH$[E\N3\;+F04'R.D>C]542>YGU2';JE0]\'TMJL,DL'V"!H6IC%*HYETD -MET]G3==\MA<>;D/`1)7YGDUV2]HJ%M]V^?OPO-6E-4 -M!.U2:%Y+8$2;T/'?.Z6/FO?:^AONRI&<]J)T5I#ZP<09]5QMS**@^.,('PSE -MK8V#4W)GWH@M[&'G1F!QH00UU&N@^L="L=^(2#B(&"9J)GH;U!!U;0Q9*E%K -MWZ^E??%\0/XQ,G`2%M(6,6K*3.M**8Y2$6'N65?U33-BZ^0\*\U8Z@J*RJK& -MI3>,I+Q]2=-9;+4X.9*>G,8%+&,#&,8%3BG...-2U4(R#112Q11*82'P?^_I -M4?,E>L^E\P^P-1+AM=35*`W5/%"G9>.>GQ@R6F2.=`CZXYCZ3X!,+99G%;M&2'?XMC_<3;:^(RO6W:3H\ -MRCIZ0T?O.:243'^KO&[@*3WG?(U',;O^^W;YU,^Y%V=NU!'TYFQPV_JU!XQH -M?&MVQHS89&VV*S^M7-]N<)0?,56;0^GG2$2JF,>HE:-20HCHMY7H;5F -M"=#LL''.$[^!^;G1.B:G)M_KXTLB!J//U^O;4*-53%060*`44!8>DD)\^CXZ -M1D8SQDGQY!$)9#[WG>T?(GLT8!K-8*FZ-JH1IU\./AK]B5)@I%V\!3Y1@,Z, -MH&3_2':#WC8VT?=A:)5@(E9QC@=UX(PVLV-3^_XPJ*3P$'K/I -M[`L*0_AC%**F(Y3'=9O=@P<#P<2B\+USU.;1_XF%S"JNZF9 -M,PK/'?TIV3FV=C*']')LVF7M73R8&#A<4C1'(TK,(\ -MP8927*$.764Q@)([*%E)4$#Y@)%A-P#V>*K"(Q8$+1063M^R>5[)RU^L,&B& -M$;I4+'8RYTM,\G9+VY.5//>!?*D?2(:)K/7L\PB9,@$2H&?I4BD3TF>:KFVG -MPD&OOTH/1`0,^K6'82:#X5@;1*./%3N+T%1)[/YKJ#5MK*V)?W94]P@%Q41C -MX3E8^OK;=V6QA9&?1H+-?5NKTGLYV'8A6MJ;6I+8W1/9VVYZAO2HRDG(N,C( -M,ZI$(3QZ./`C/5]6"J'J@Q6>K9J`,@JL6U2F>K5`!0C%D_QLGK?D(>LR?0BS -MRK:I_6JO6]>)Z_N!FGR#T/>!D:%N#V.J"'HZKG2FQK.*W7>5UKNEI%==OOPA -M-4AI%-]_G\)5&=$153PP/NM3FC=J*VC,?X(.IO%WP-"[;]LSA._&=?#N=WD< -M-2VT[>31V)+@DQH1FZQ94YN85,3L9J7(YE2KV%[.J]817+ZAOCU@!:W@)FB5 -M(#"=&/09NL3=W4)#T@IGI`P9#TC_XDH].I41BJM-$D*BC``QC:HQ1;U%_8Q' -M`T9&1FS-;8F*)`[#U='5::S9IK@K&!TM#YW'^)\7C]LC[ -M5?1$Z134@8E.L=SV-J<;D4BI6^3\N,N,:^M)SLF)JN$U(MW_)_:\3T(\G/YN -M=)7PYF'\_-Q.?X4K+;K2+F5?TH2>HP4*'[5I`U,A\XXB(`XP,0#;81A^-(+CR?,;F.X!XQAQ?B -M@<-+'W,C'"0M_TUW5$H8J?/^2UQF -MKQ:#(,"B8FV")YF1X2F'PKJ2R2?#5\I\H"I9(9('K8%>D@EG^8:M5L$;BI_& -M2F3.LB.FC@,^9YUG\.[\C0;-K._$J6X;<_!JB_RN!!D5'V\IVCA4LZMZ,' -M7^%V-3,?#]I;\M5=B/W%4?:'HM\AO^&H^FY&1.PLG&RLG@=O^*X1VTI+=SJ79*BY<1Y$%:V -MI)!MHEL%"EM`+8*G.(OBB(D@G-*6PE)>DG('CYHD^CU!\:2F-26*-TX6K:=6 -MFJM'YX/&J^(ZGE2P,.JBB]1ZK=3/JRO<>Q7V4JDZ1*/J*R?8%1Q2YOJ)?._N -M8U0#TUY[0^@"\?5X]'1SW3H\W2&@HTA6TI&D55*^8$%&1V.OJ.T+9AVE5%$A -MVB"(=%*%5\2J(!T5%&)"X7HQ0Y_''P^X^M]]=YWB=EZ7_*I^&]3]KMO0\7Y8 -M1C-:-CRWBVZ-M;'^N1\I9`D)Z5VF/>K+FK)Z>GIR)/2'=143B=<\F'.SF>=@ -M[!=]Y,>F=6Z=;"C;U>J(G5"JZMJ5@5(H*=5"D58B+`:H@'W+`*!0ZR2F@ZO6 -ME)P#BXF#>*0&DN@H'CSF$OS\MU#K24)E(._\7N6I4L#Y:9\/>-[4`>/6I_WQ -M`T2+H-^Q,"9I%=2L[/++2>H)OW35%CN!+?9*5!Q5A`I'9;4G:LZ#YB>E*JB= -M4>_]B_;'Q.9WO!X`YVJ>U@=UM0=[?G=G=3F45W6I*@HTU(6)$13RJJ+`#NRP -M>3W3NIW:FK46]F?5]WO]\W-Y-J>VKAFO2A> -M*9Y`ST"9X%U0J!,])$04`+AC)N!SY-TW>UW3V?C_3YMW.^P^IC\SV7LOVCT_ -MI^^RAUX?U+DH?^18E?LYI0KPB>1"[R+:I"77J:BGI"BA*"JBUZGE-@J)YQ6Y -M6%550T'WZ_VO:_$GM>U.OV4['SNQV47X1VE#M':@IV@4&JD.U`$8BI`.G -M!JJ8':4/A?W>W+=OMGP_AOPY\VWS3.XF7RO$IN/;\^$UU67U[;Z($:Y=<$GV -M!;Z!R@F'):4H)R9.N6XS9E?J#J]7C]835WK-C=*<;=M$"V+8MVE6V0"Q`BIU4(P1'JU) -M&`+(*'59"=5I$B.!!P$2/J8.-(Y#Q,KJ-6'*VYG\)<7_S?>&KVC_5M'@M_2* -M3HR[!,1**?^.5E#)W\HX.'?X^-E8V1ZBM5[2I(K`+6G5`E05154,540HI15- -M"K(+A>7VV(,7,W?C\;%ZGMMZT0;%=A6U9 -M",3>LIB65(LH"0ED5>95$G4DC!%BH]-IA`ZD+5TZAU)TP$WD0;XIP_>+B_7: -M?[R\;88GAZ^[X&'+]*;35!*7]D'`RHEI"<@2DI"F)F)%&%OZG0XN(]'Q:U3C -M05.,./A18#QG#:H%@AQL*6ZH4DDN8),@'(JJAR`V.0<>N_/='/YVT;/Q_,]' -M['S\7V,CT_;^Z/CU_E[.)D+)O_M<`X^'BX^%CN8L8C3K2DY_/J;&PE:HHK*A -M-4.0Y/=RAA7V%AXN'W^QP=BORZ=4#*JTF5!595%.JP% -M*J,1&%2$%5$0$8<;"`BS9R03N4A9[W1GJE>7/;4=+EY>C1Q_F_4]4'3]=ZJ_ -M][?7]/`\![Z.X/L7TB1P,7#[+%P,'&]L(Z5_AB&*%4!BB9$H(YZ0Z$@VHH9) -M8@(P%"'/(LZ!MHJ;4$40)2);X:@BTQV8WQ[;WVEQCZ7_[W:S/1_!\S@7RQ2< -M+RL,X%Z#$(P^OS%#:9K)FM4J7':U2K`S0%`-\`6=^W((BA)F%8AD4,VZZI1@ -M][3;_G=N_J>;K?$[KY_Y!ON!U\"3?,K\SF_%_VWI/-6Y<@N8,]TVS:M;5-I%FV6K;:4.IA -M+2"BFUA*$4"%05S4`PS&J=/\$[AR_"[GK9>4]++!-F5$SBT@L84A-4(L@=+907(I%(!0JR -M8"U@3`=O&8T=[ZI/K.9S"R.3KY$=E19'&8+ZXOO\CZ^[Q[[[S7VIILT--!2PVTLQ3> -MTH&JKF51"P&C(4HJHL"4"P,PN9!(4(%ND6Z6AHC2H,#+VIY8N_A<>]Q!!!!7 -M=O%X/$(ZC""7@\22""`Q(8B083!D"YA;W9TO,7'CX\;;XZ;:4%6<"FQA:I:BZHEI%L@,@BJPEI(6<46YBP -M,C(2X0B02`^!4=?7.=XOB8/CVAJD69S51N5ES)R%)H$B:A54DB:R,#W24))1 -M(+`6$+XJDOOJ@JZ<7#.'L=+BCT/SLYG-+,N6<+2I"H*&D%,H2&D!I,D@R:20 -M:0TGA:2HNT:M^4,M\\0X_J4_I'+S<):UIX:#32S&P8TF-4+`H!C -M%A-PA%C&$F,4`-%H!6J;>K9()%GUMAR\00Z%5770"X! -MAQ:"5(."M#&`5)!%933(3"*0R"S`6834<)=V^03DXO/Z_N.E;I>+W?-_.^GU -MN7:V/1S%/::K;MVU5+-#0-"14$DT)"Y%`I(B*!*)F$3&,$MFNK,=RTT8F.'Y -MOZ>[Y&[J=:MG=Y]CNINU -MT2GKG)QZ5Y!P=W7P:[A"J)<-U1ET%)=(.MH"Z$1%@L4N0JJ*0)0L-?,JM=MP -MZ?-[7F^KZ&TWO+^CW)N%;B;@;A>0O4%$OH(R$4(J(2%X7LI6!0-53#FFYO37 -M#=A#>OZ.F)!2@+,\)#TSP^KZOU?PO"Y>W;'"C:EQ5UUU*6LU1C9,6E86)<$6 -M`B$+$BDC50A:62A)0"PL%LYS3O<'[$^X-\]S[WEX:;D2X=;5774%UQ<>YUAJ -M9="*%@A=^DZO>]$X>IGD7X7%%Y>)A9J2T6 -M(S`%BF#5JD+0BR3K),6$0PHJ3#&F:C'4>WL468SI(Y6H*/'^D/D=;EZ/`?`+ -MBYUEUI05+J5H2JHGBA="YK54+$AKDFXP*15LR!K)J8(ZVI4W-9X]PC<:;?&/ -M&[_-.`W$=SQMQYNYN`%122\@I%(Q"DDO)+P%O!;S+?>I?&47$.Y_/U>5SL;H -M[>QV!IN6K0<`;"..$(0V2'$#"`,4`*+)&"0F:,SF>:J3(S<%_2\?L<(CG1E61D0RD%4)D!@PE#!2$RBC$F39DA0C8):#8C -MI.UWAO5WZ?)6?JUZ;P@*(#;("$4S/#MVJ0VZM*XCG:>=S3/=ANY9N5.\B_ENY5OUXISC!3`P#!D2:V2 -M)`%!0)A+\+6E6%TOTTZ6/'Y-W:UZ]9PFO6E5KLFNU5KAK09#<*HAK)&U!"E8 -M$HULFNHZ5:Q;;P\//,0ZV?.-SA\.KR\OEZR\O"\BD4A>0%A#+?0$J(R@X30A -M?+JO;I5ZY>2O&R\RW.ZNW7X'3Z.[T<-3:T'-UTLVI%EFU1+60$%D"P`I(*$+ -M`L#$B(8W75,2TT5KZ>CQ_<]7]_M:?A[NZ;KIAI]##%,8H8R8H#`P:%9"I`%` -MF!,$:11FE%,X*6!M36N9M.I5&MK]CF[I;:(SVVQ4N`Z1!K![&+#'&JJ+%,0F -M-%0"B$60F,,$@EY2'G721I9^<&'6V-2QJ*PRIEUIEGW,SR>7=./C]KC\GXO=TV.]O;W#I-'0TT!8:0!$-2$ -MT`BR%D*%9`TAO52PHF@Z4*G";71RS[O!YWF^7X.[AQN>6O#&JF)E4J9"Y`H* -M90%DR0$"(PBQ2$R@JF654U,C(Q-_B.+KGG?9W\^["\O+]RZXM11+")<187$E -MTD52`JB)2`:U4+E)H&IJ*:QG-S1;:MN%NX.H<;EO>V%LZ9@X.H&`8(H"3!@4HA*A!9(BL@;`V) -M0PHF>RHRJ0QV9F9P9Y>GCZ'M>O[\ZAL,^'+/I!F9NQ2IL1,G9-@TRH68U4A4 -M)-B`I"DDH14-2G43"5-@6:ARK8NQQKJMFML6WN;ZGI]YACC;#E9CE%QF#-J9 -MJB9FF2H126`BBA#0%YE-4(:):4III-XX]M5EEP\/#V.+L8X#EV'/C,9?C,84 -M06&),$)BV0E226:0E`B"(8%YK-#P<[K_;];7[\ZW4N+]?0PW^#62:X10-<`U -MH0C'@J`RZU0H>"F[?PX.KE\?DN]7Q?%.<\WG!G+UEPCNTFS9G,A,Z!$%AF18"R8D! -M29I)0P4"5)FTE1S,[8!EPYT]7I[N9U^_Z_Q.,PPW^;KH+J"YD3514H%`1@7` -M`7!*"4)@ES):T(NUY=[+AXD-#5V2RZ.)9V@W9<%,N!P$DN($SJB4D9(9JP*0 -M"G)HS0',U=38\=<;QUNG%IV.8E'G'P/)R,CK]ASRZJ')LV&Q8O)30FZ(F,Q1 -M"8U1*DF*$N80H`Q8(8.+14-4/@,5I^PUGV>AUM/GO#?T"0P$A]5 -M4/A\J91BLF-KKBI)2%TD%"69(Q1990L'@'JBU8#`%D51N:D"[,/"T;FR"0[F -MNO5GWP\CKS[`I8%+%*54J2U5)4@I+2`H!9"4,DJ$$$A'T?*JJ$$O"L\^I"O6 -MK7;>?R=#0IM-3M!C;3;85'*DRDR2,'&BDR`LR#"+D@08*-@EL$HVK;;=(%MN -MH;@J4]/G=AZ1Z,6*2O"?/@@?$`@)@(+I-$2!HJL!DB@32J*9`=VJH0""2(!` -M'`Z:1U'1L[@L[EZQ8#3E758VZ"Z0)9#K;:+E"LJ9/$8(B@@"P`Q!568Y5EPY -M]2JZQUR^5U-7EULU_1@I5"\Z^\]2?IA8`#`PI`00@@"!8$S!(+`AB"B@VAFF -M1SY^/Y7K?)_'>_^/YAM\$ZFWJ<[>TW3>4-#0TFZB!HEFY@H:F -M25("@9$6-5"%$6+F8A;-AMX^"VY)Z'@Z^&')@7SR6-W/?X/>>>F9\7Y/#E>I>:]S74I2B(+KJ@J'-044 -M!)!1UU)$!$E@F.61+$PWC-6:*6:T%TK?0X0BFZXH3:\42$AL*J-L(R$8IE!8 -M9)$A)E!5#(14,K9-0!6FT:;BKZRYPXHZ':2HA66=,S)H6:)+%FB:$EE00+]$ -M199!"*!>WMD)8BHEI>RR%%Y5Q0Z[VKZY+WO-W]SJUT2Y-XK>WF88 -MBXWU6*AB19JD%4(L#$@*$%),06"E),9BA`:55:#0:,R::T8GFQ2Y5GB:L73L -M#5WG8#`JP&`/H]`H@A8AO$1AHA$`4-&18I*8!2.FB)H;NFE+R3N=7QVNR:^W -M=[SE+KQB:[]+DR\/.ZMQTL> -MM.GSL,2BE,3%'&"F.-$HBK"H$IQ2+(A>56"G:.:=3J75VSP^AT?:Z'=E^QL' -M:EY,I"]D2`982"A,I+TO&FJV*4CC,3$HA29TRI9S[N+CWSXIQG6P= -M_FFX[A>+#*7C%)>12*$.TA`O24DE-]`!1#M^9AT -M,7J3DN-SZ/;W?)YVYH[=RZXNNNJC75!8N99DHFID@P!9K2DE,DN5"'T95424V:&M -MQUE"7&Z7[R<\X6GI&KGRTM]+?>E]!EOI`J%Z4R4$&(2]IDO0!@IPLF6Z\H;Y -M5;XRX;E-:QNLZ-ZO>/:#H]K>&A:>&HXF,N1#"J"A!"&#"(04@8(181 -M@IC!Q*$Q:HJ*Y$QG52P[^X[KZ[K>%SCNLO0R[.YM&YN#MUMFGB>'EZ/O?2N-P/&`W!W*+ -M-F%@1FXC`4DW`(2@1!*,H!2F9*S)69F+11@#)8=KW_AQR, -MNEF=+$$5Q,[49!D*&5-$0,JI$*0B2"DR3)`I`LP*++CE54AR9X9=_#+I7G-N -M-=QO:7E^$P55,,`O0,"+"F,`4`PA>TX4TH85-142J+@WK]ZY>3'O\>^7&-U] -M:[V7M\+S6WR7T4!4(VJ`D"]*2$6`42^K[00#!-0$$!Y]II&@<[.<&O:Y78V] -M3;VZNAHK#3?@GP,4SP2)])M5V^)8J3;50VLEI*011B2+)#:!?GHR>I`84*OV -M8!(,`VQEX..D66N-DY"!550F04(2_QE"*`B9!0$HBE``H!*,&0!C"ADX]"@M -M`T]&K'M<;H]#O^LZ^NX5RC6MHPK&XR:FBM^6@I+$LR4PF_)+DLTPBD!#>8F] -M2'2WZ"C5;;:C:[=_>>KMV\_9V\)W.%?MLI3>G:WWB@L+P+T)A%0IB(11$")2(E("DD1&)`J!0 -MD%@I!A(I-$T(.BI4JM:M%$1`9U#.4KG74T:5Z[JS[3S@<Z_!>>-STX-\RWI+Q;FZZ%$+U2F% -M((0WRMS(BE``0DH',R@PC+54E2J$)-!),>+]%XIXHI]$GBE12>*K[MLR -M%I`6187)."/!H+I4X)VAP:L7&U2;6UXWC:YQ,O"RY8T&4RS*D6"!E$BR#"3+ -M50@I?KN.? -M-2Y.G7&4;@MC8.YMQ;SP;#0SF\Y6*Q(U<5U#(601(`1TQ@.PM5B%H04ADR"+ -MF9UL.`,]W.4[N64]/LYK=^KKI_+^1CP8Y9<\Y_0KH&>6<;59S)#("8" -M2"PC)C12E!9LS(O,,7*Q1CJR\?5XECE/-ZW;?D_3^C\CK[,"_(9@8!B<`&+3 -M6-%$E$#)`%("$AL@HI;28@+2F;.G::V!=; -M=NU".FVD*)M8,)M':P%D0AHP-K"&HI8-IQPY!/>>\V;MU]W2.QAQ=C*M6)B] -M3*Q13E,IE,D8Y3)$#(5(A#U$*9#)(4PF9FQ,L^/CW1>/>XGX?E?#Y.QMWMW( -M,2\W'"84)=J:E0*0@D"]A`9+V4E[8E%TZ=,OM:NG=TZ\&'@]7X./AY;CD,#@ -MX1R.#A-F/2 -MY5X<(TC2FDB&E(:0R1(32JIOT."Q$$@#+)`6$#,((&0F8;]3EK#(J2-K*&IJ -M1V+%N>)Z3VE$Q,;Z*AB8:K2P"ZG%C)@RD)00\1).*A*8"0XIQ1&<7,(@"/HTT$S1"*#)!5`DR$B=6*"!8$5T/AXH^$4&8)4)0R`A"RL@+ -M)$+-%BBQRLPCQ.GR#LNS36.Q[,I#LX'9ID2Y)<2X$C)#J^HJ060B'NJ]V/,H -M]WJ>).A-^W:L6:.YP[YXW"G7/6/E=QQN%V%V]5V!&:=)E,*126%*%"06$!AH -M`@@$T`04`S(-7:N0,DJJI"DE0)G:2$K.D3.HO..`Y_#54:&W3;PSV?+F9Q_! -MZ.S8XF&-54<#&S)>XHD;4LU)C).8(',M4@6D@*$,2]QMCJM2K4J50I5H&==F -M8.SR^&.*+X-T;.]`^X`XVJN`"TRSJ"2HQ8`P@4D,V`,SJJ4S -M,TAIR<+]R5Q=_IU[MC;J`SILVX+E05$L@55>#Q>12Z20"(+C$5083M@8I321 -M""R`8P,4%2'@\ZCP=%5\*2JV:U45&'>B&UOP4ALU+3;SH===4IL%FRFA(9HQ -M(,`S=B+)(U1144T^+A7; -MIG5FJU9'*JN!75`*8$K"HF`&$9&!@,!D#!BDD0,$*2I@C!,*!W-I-K:.1M<_ -MG]3ZOH=#R_G6U>9JV+%FUK3=TJVB6AHM6&Q0MH#I30T`D-%C)&$F9(`DS+5" -MT%FF[-D#-,P[F[CMZKF/5[V#Q]-NS9L%S53' -M/.IF&:JQ"9F=%(1)"D$5@I20J&21QYGF^1Z'+T<>3Q#9-K9V3"L" -M[`PF$K`P)A304A4'"HDF$84R5"3BJP1(4DH,&,.0[-%KF[,]F69LLF=BJ-5DS-@FQ8[`-C55"NJA!O/ -M2:M6Y>T\[C=&S>@&V^\\CR../.AQCK"C`CJ.JBI)2L+(5))L&$B138D3";.+ -MB,>WQX^9X3X!Y?GW\>'':K\,!;@OOHHDJ0O!581(`7@7L1KBM>8/"8S%,.'+ -MO=KWVO6.O2YN+II=S+%I>:I"\JJ"7+?02@)2L",N1O:3EN2[<[R06]>Y3\7S_P7PSWATY#/Z!S0CTX&8&ET_(/\7ZM\KBM?=><)A,,)?A!00#`5(,D,$@L( -M,.;@%P\*486PQKQ,)VN$R\JU9>I^2.=Z7I'@\SJE=;AZVUVAM-KMK;M#;`7: -MK!DAM0+,E20VH(R4A)4=M33=1-._Y&CZ'8]#R_+._\3O'_XX&?UO4._U>AJV -MQM'$P#!F,"HU1#%%EU4*`P@;$:=VT"R%F4R2@MU*HHMT^H.\9]GE\WH6MW?E -M][_=Y2]_IZ9-O;Y5)B8!@LP1F1,"82<5%@(28,IDDH!<##;97*+9"DH6SW9I -M\3N[V;G=KKR_,'9T04D9*JJ,!<.''?UCP_7__33SZ>>='P,*Q,<&L7'( -MFG-.DXNG24HNF$TQ@I!`,D50(R/0HS*9GF9U113Y7:U'G^9CKQKP&YUM9T-> -M_OX8$PDP$88#!@8(B09)@TE,`$F$5,)@?5XE7[_F=8ZIT_*[?]#T1^J]9^5^ -MY_;9.OY'(MB6QM&TLV"S!`4+(P+)$(&(K%)(DLP;"F,<:;3U+FW.F9'5S[NM -MM[>OR?&]C7(V;6Z_&:A@B8&!,,*)1*9(P`P8I`0Z4(#JE22`Z07%(;#;D[>_ -M[\@8>W]UN9_)O[M_GKH:#S[[N]54G)RZ&C$'0J)-$:J@-"'NXR,"&C)NH0K1 -M$L#5:!RTM:;W*\9Z_X3S_?_&X^D_H#_]]X.[W7;ECM[8RZK#:&-@<6D+K29( -MP$DLL&#(3%6]DER0NC8,+6JCUAS7'F:F&'"\JO7UZSNCU7E;$CTUYF`+I%H6 -MK5JE006@2,D481$!$1(5%$2`4"203/&1`FLB@03.9S.KGG<'.'J>MU^GL&@\ -MGR?-/TO>_ZSTO79,EV&[C3CP-P*2V(#J82*(!A&`(@1'41VVK+]0&()`5UUZ -M0MM\ZNMK7?]?S>\Y:^A(_\UV'88?5Z>I_<[?K;NC>->G7FCGQ=&OG#7D->)! -M8"P2&O$"Y"@)H9`0-=IH=;7US7-T];N[G/JC=W.]-WG^OKO:O=]8\\^5]`?- -M'9<^GTL#<%3E;E6J*LF15IBI54;B52"2!6((#E:HARQDUI1()B[NW -M>$4:)#5QLY8_09!4CE3&JH3Z%@@&4112:F0J0#38+IL/*20W["9(9$49J'.- -MR877489,.\W!PKL19QJG?>NF6'V;%_(77&%J\_@\!(A%AB%]%@#Q0@`O!8$) -M4$D2$68I"DD+!<6;&$N]5F6QFV^^G/WCZSH_N_YS^`KU:<<>C,C+(R0J@QWNB[S -M5AJB'FZW=L<3>V;5K`>3FV4TS% -M0U'`%Q60NQ2H)"ENHA0068HI%D0,:9IH,QE50LZDU'FAS+J]+G9CK>3N_TM5 -M?M[/MOEE]U]>I*PY''##$!5C),%(L8)"8VJ4K`]VP-2$M,2D,)CR/)R&.2][ -MTSZWY?6ZPK?3D8'2\SY.$O`P9/#]T>[PL/[WN?2\VU101T4C&5$!1)-$44,2 -ME8!K(JK&!-#(L%)$#0IGI-`:#0'&%H45ASK2VC9'L/]/@>)[!E63Y7C45P), -MB1@8'!ZG<4]41ZQ%&BD471**FN:&:[<-$N60-=@BLC"&BYNN((J"B"@(H%*( -M"I%H`B@:)UMS!Y/K_4>X^#Q_J[PZ'%,B1SXL#2[KTF^JX*8WJ=6/'-'42E1C -M2.DP)192(-)@`-(JJ('4*4B"4$G[])+(>RA"C^GR'B:J.24UR!Y2\L[GP?E9 -M>^^+6K>U>]W\'`^E_*]*]=\'!@PL#Z5\;YS!BBX`H8B0O,H,AH`%"@*`22!3 -M4`VBBL,65("ASHR`S:QV\Y!AB'>'#NR'0TFS,C(P>G/Y+UGSD"#WYY!H?0K' -MWU)/HZ-ILXF(\L^L\L30&=G!F_/]#2[R+^IDCH^>;^_ONG@7WY;/#[S=\&C7?Z^N:_3.QV#8 -M38V$UZ1-@V&(!L,&,61(0X&0668?4VH@,)PBSR5X>`^DXN+_E]-Y0]WD*XQ. -MAXD<&[C=>=DIACVSJ4:MW.UI$ILH9L34VVT,X`XS;E.'$X$VF;6X\#C&(Z3` -M.G(V2I#I)#4%:JZ;8A2,$8!TT48K%@DDY:"@C(ZU22I.6*Z30&XQH$,YFYN@ -M3-L#0R::E\'B=LWY:3`0&^>:-)^-'<>4C*"`^DK+=N59/6@RIK-P^ZX/,.'? -M.'A!X;(<)#Q8(HR!PHH,Z:$-U+,(5#B1%XH<*;G?MW^(XZ^O/F_8^#F%B7^%N6<'&GC8VAMC;6P+6U:/.& -M;7KD3DKH'2(@A'I5%I*A`Z3%1D(PZ21*Z0$B8`Q-C=:G$WO<&3?^.KFYUN/'D"7AX%]A8F#1CC7$R>D-E*24A+*1BDA0 -MTE(`)%)2%*(*)D4I@5(3C*B(J8W7$+@XTH=A]MO6\3[#VO$B("'S6/TM\L=Z -MJWY__<1V5\M8A#1<7&):3]D--^Z:F)!S#2$>:65-,ZQ_EJHTI#,"95 -MRFG?OANL^[$"/Y^Z#TT8BFZ!GW4NC&)1+I)(%PH42V20@(")<()%LHB*%-S> -M[_?K]+CZ(*]3J01(\^RYCV -M+F81;Y'4GKKG5_3DS[X7]AS7Z.PM# -M`V.CL#9E$%X[/0()V;&TB;3`NHI4W@F]O)`8*K(P"]%`ZK%`8Q`C$!`F"L<# -MJDX_KX"!*!,Z\=_O7V\LQ]I[8[7AQM1NV5.=X5,ZIG9,2N9#)]]?-_%_?.AA -M\L!FB4A,A78\D0JWU/\CIZXL(RI2&C92NS75;=I48KYE31%3(6WJ.+I\?(KV -M\;8KQQO^36PFW1EU+[=S!2Z_N+'LAK`;\BJ6;V_;CF\1#1WO"%%'BOA/#/"L -M\(3PKYJ`4RD5!^HHDEC`H8&!GOSF>V\UR?/;I;/88"BI'T@R%U[XFV<[ZOR8&A45^=I,9=[U13ED^ -MCH$16\CO2FIF,_BY-Z'=^F79U\/7UP:VJ -M-4PZJ!O'0(+22HC&,@?Y&=QD^F2E&"3R5?:2@,>.#X'T:5X`J3/QG\_K&2Z" -MP=.)MRD=6;BT?3S9^VP9B6Z/V3$@,BXG_[&)*/+2^6A0C)$DF^EO>]<@V&XP -ME=*[>=E&:Y0Y%I75I".K=NC"%%.6T*'!T,Q$Z#++QLM$-)LM"M9&(0<*")V93T6AIE/?,J!"Y`B(G6ZV\G -M?8M+$ZK?/E^=9&9"9[:-TW0H5G\+T)*2T(G+V*&7QN'!J4-#(\+I9?PX/ -MG5,O$P]G$'G^\R>Y:Q'8(]P'[YQX<)^#^!F?1=S6U7ET29M.JLL?17H):RW-RP7 -M_AN\)44@?F#EOV,/_TSZ=1I[%I8?-H9%CFZDNA,I4Z3>'XLK"MXTVG#/P)`G -M5:53;VZNUM;+03O57>QU!WULR,JI1)WT1%(R`=_O411&?(0"I<@DW(=T_-WC -M[3C&/E[W\WT.+^@;SWGL_C>9O?HGY9Y'ZJ$XJAW;56,H[&'_#)PTQ^.U=@?H -M/^0-?-Z2#Y)JM*1>]4`I(J7)G>M19'#1.>H]6)6IO@>+S,,X`E8V7@S9N,+K -MD7)Q\M;^LR_U_J[TMW -MS4B61\"8MVZFYZ-+^GFGT]FP]JDXQ@L4^B5ORJXW,JND]#0=ZOMT05L:<1_Z -M>7E;.I.-JEJ=5H^=F2A_!5L_C/97>5_BBCQO:?$SK&%=UZ=V.5I8]X/U,>9[ -M@=[E`7]N?QM[0(/3]*>F=?4P]-<^*H>F`*>V?3449!A`]-D6;PDP;E&#)]6* -M7/H5^L]R>#OZGP,G@GA#[7ZP^C[KY6J?)R0OIZXEZP=/3A6L=P[6#ASE(>3) -MW#:JJO/Q_T.I$*HIZ@Q$.JBM5WW`^/HP][\J^A4H+'4TZ?JTFDQO`7[A1.;# -MH^$Q-O/"V+>I;O5$]Y\H<'/%&CDGS_A'M+YO0#7P;6&*"W,H-1)&1.?SY\`XQ@>-:R8.- -MO#"5((70P-%W'SO5F)C^[Y$8'@Z1>-.>AO..PW"'G>OT1O7YH7HJ;0 -MZISSV0Q<#L9PD!]6^9B(/R,.YUUI(I;?Z>JY:V(9)!?1)LUEK.@9M@HA_-_E -MHP4K)2^.=S*`K9Y;3IZ+;0F.["`\GA8A@9':L-^,'BX%K-P$# -M-TNVZ8!Z8%8$%!J=)-@D`5B.D#VZ`IM"2OC4Q1$121`"WQJ@(R")P.)S$>)M -M(/452SI[UFG9WASW'OL]Q[8_A-]4U8$E/3#!S^6;J;%E[ -M#QK(.J:5VU=<1_M,3AQ`?O?#:>O@;<,]C^+0*O(Q&. -M/'B(%I(2PJJ@L"$$8060$5061D(B$8D!9(08'EI^[1C(D^J$)X2`$8@$$`,H -M@*!`$*ZZ@HOY'%H*`/V/E<)%EYFRP\&2&V\3HE^K9&S>L6C)KR)JZZ.V^J$] -M;,!Z;&R?Q@P84,RMM0L[/5\6B@WXN&]]N]UBB)VX3MT8&%F$Z>C%&PO,BOOO -MHJZ_IT,0P-PX5C([/KA%QTV$0X/:HXC2?K^K['$BK]VT@L`0\X3[1GY#=YZ,//3\N>@>ADJLW@^XK\I/<_YIJ[WV -MO\YR$8M`2:C;T9IW#YXI+A(K8_:>$ICD[BO?TRD:U%2&GC\P<<&90?KV9I.S -MXM1H*+Q)W-_).SB$,>8%"A)X43[[@I_R*83!:4>WM/)9\[^M>Y6.)OYY1Y[U -MH.R=T14/ML/V3XM\;5&QLFB(V'%;$9EV`J[#G/T9#8?)D71ZT,5!_&+C#"]; -M6>'E=@N!.-I)^!82HG?2YK\TJ6]!^I[U`O>&,^WC"%D$YSH8?!X#SX324!1_W+I6,TG1GX$M,^P1! -M+S[]WL`&1=4AF\[PH)95Y-2;9+!UDE>?5K%&H5X399N=1M?SS]?VJ[*`Z[J< -M-CZ.X\`CT,OQ%)OT<)[W88NE&3,(#?^E"@[3&-GCLLMS>A4U1UYX^NWU[.LK -M;6FC0>?'FNMG)(F[50M?/XTRYU]I49?/C'.YN5]][@LM0W\8)"ZW".RAF*@Q -M!'R;4JBBW-$&EGO\=0LS5+(AF6S.SO<=E&G'C+DZ0[]M:)9T%+G3#+ON1NI2 -MPD'O,1&X=VQ$DGP-*X0;;<-'X]27@!H%X:A.H[%WBG[:ULQ(B4L)2EF($Z,A -MS3[G\YQ,%(IDLB><#VJ(!)C!+9F4B8"=&`ROHS65RG26Q0,NPE*G-X=M$S$. -M'6UZ4&!L?F&):[T1KD:WK8\4`G:67B77+O$)F6$QU7YGO2?WO!7C[&Y[E -MGW'VQ_%\"Z>_$9ZRO+)/O8JFFR![\%8"'J$!20]^BQ$/:)*8""PVH?(ACAP' -M7`T\A`W*PQ5$/N+4T&G8*C/!F?]310_2Y548:[99]-4K6&[I8#_S3JXU5%3M -M(U:.&S^`*W$WL+S-7G*+T:#[YX?,G+BWSU7X$;+):PJM_>$:>'XK/8C+'$D`]J'O4G -M6PY*J'E&"68MBV2;MJ&8.N",STQ@?F:F:9YGU.EVL]Y871^T7RJP]?K6G!MV -M%+'^M)UFJ4>4CI0O8&67O8Q87L\)>(DI:\Z+1L>QJ&LO]6CO*FU0U6J\*#?A -M[E6C?;[):YL:=N*=0-Y@WT9^%=F+COK:RCYGX-AS -ML&H9KI*G`#DQ3O>OEM1:[M66\93RNK:120N4;ZIMWA_-A6?B1*MNA3@_Y*IY -MK#-QLB-V@;XI(/PV6I9G'NSQ\A#^?V>3C7`?#%!9#S_O_;\`R, -M1`.R3X9+J"@AZA@4R'O6*2)#Z'H'PT^3Z40'SJ\X=#%V*SPZL]J!!:$[*G`> -M16AW/%-+[(:"&P\;4Y92L>?LXJ*Z,Y(%1\)GP+`H=8HCKL64K:0"L&LQ -MF<;#2M"KUKIVD_AA1J7H)>26C`+X/.L@L=9@5BB)*XWPHZ9RY!@U82YU$,,Q -MWBWN\ZN%N%F2P$!C!D>0DR2DK^J$WJEK:H1";Z3`+;4-"@H.6"'A-^K!VG_9 -MFCPYC(4-A[!:J%UJ\H]M<0Q].]#A:O+`'E"^VY0=S'['?4YH -M;CA$SJ=7\8)'$K.ZG:+A"K;J@)/NI*C*5^(Q]V>V%#?B^>\SZ`A?JU&J,VCV -M_QMS87?=\KH*Y#6+))D$0A6/B:=BKLL;DCTY=4%->L.F;KC@\Y/UTE -ML4+:T"]DQ?!0J#F`-G. -M+=J[&%>-#O07N>OX31K="'0M!QK&:-JMJ -M@H9``=NQAZ'5'`]$[$[3WIB>RCYZ=:@^I]S/5^?3^7JI -M\\5-@H'P?BC.B,#W_42;XSP25C:X>_PCTV>%,I\`"Z3'V<1;\W?R!`<$LBU[ -MD0S-4]KMHM8G%[:9_W`PCA-G@+]>H?NSGKDDWD[D2&=Z6M4D'OHWCQ%>WXAV -M+*BKES1"]#>!WW4UHKK(^6XPB&MZ=#?/Y(U@,6Q'N?TC:"X)S],$W6N<_S7M -M#SNN;WMYJU+3^")NLFZ[E.B`+/.]I"M-3:"L9&^;D#Q"RD,M:.K10TA(0L#, -M^]84EAOGMA=8T_1N-#N[2"IVMM'!^GZ7I*K'A<&%^>__MF6E-'9N0GD`VN)P -M.]W(74:'RLZ:W'RBLX_CZN8F)F9G3%VL*%I."FX1AXLU/&]LX7H,$O;]VT>R -MA354>J<*(7S>Z5@9VFP3AF>F9QIL6KP2K+TXF6PA-W<()S)_W37^O333C3@: -M&2@=#TTZ"YM'K5@0`:D/S\5[T(41"#X/Q<0CZ]E@Q=V-M=_A\^7XS`RGN&9= -MOBZ.I=4.W`A0AUH9Y+F-MTZ2G[4HW+_'G"9_Y:JT!J#Z0W9TNF&_ROBLV?:^ -M+Q"BQZ^CO*Y>+<09(65'F!M-$6N\G!.337V(QLRIA$-A>"C09?=6-?&UG4X0 -MAD,L1(-%2?5B[,!;G`RU^:?$'5@0-0EB!6]+5<1Z^TIPGZ3.B(?P;7$&RVQK -M>4%U8,-D?`V4Z=+);$=',HWY\X1>@).V=(:!>)WH_@*/O@]R=1G3,Y(C78S* -MH(N+5U4^,85FLX./@BY^IV!`3`KV'$[X0%$1:MWDZFX2H96&[/',$(5/#+^% -M:I22A55W9OAKR$!K26&L1'1R62+?,*J;&_)N?'C>.\-I\XU\]"0BK/F1VA4) -MP2`-,'5KC2&TK\H8'C(;LDX570PSB>3$#Z1K^J.#L"Z]J8#.@W7.`M% -M!(/`/!C":0AZY.`K&",#L!DA3/(5BP_42>VNWR=_/(50,\B9TX*XP<*T#CQH -M+LBGC3QP2,;,K@&;V.NOO)T37^G6T(@W[.K>74Y=90'6M*W2SEKQ\:J+@.K$ -M&;06$``Y.*L=-B,P_$'9OB0)$"1]#,#>>:Y=@W!-4$AM\IHMN4TW9A:6%VKP>'RJP>*DVOU-@52EF&] -M';+'4QG&,]NFH/:&9CR!:$/0]<7PD',:+.]5>QM.;W-A60ER;:U5N]!CMF7Q[D==POQR!1+#BLCJO.$>O>O,^_5P<\)/BJCMKM><`[ -MNX_`V/EGZ0.#15Y(?,F_L\FVW_E6O'!3>#1[-P -M5D[-IBQ&F;(T8ZI_0N_9_Q-+9&NOCK=Y_WJ#G$=`P.;&N]CN[8*M]6C](,XY -MYH8VD<+^7_?\8?;U"P!%/ND6D%VML;.2MT`+),IDS4<-E4+F8^35'>\N)3"V -M:XDX);1<&-89YIFC1G`)`R'&AZ,ZUEE4?*1B-CVS!1`1&QRBZRNU./^AL,9C:5'#E!T=?;V.:'%DRES -M'OJ8`>N6K4FZE#1U:N/,TOU+.K9N2SV, -MM+;)T#WT.YD#`=;F$$R926# -M/U70PT51@%D+"U*W>HP\C>9%)=\`XCIS%9!R!/YA' -M4SA\]RVUD-0&.`J_PX>_MO``SY+!YAQKZ)K#B[N&!/MCS-TZK=DL;U++>F3* -M@Y=[6U:Z(>J-_F'_.WX!;Z3[X9=96F;V$JM%XCA"VPU,.06#06CZ!X-MWN96/.`WS]P)E0J`-HA- -M7D!_AX)E5"OQ@?\NC7Y/F"![\.$T=VO;354>S-"_.=S9FAPJG:,-%3Z&AZ4= -M:V%#?W:[7>(12,WZOR_4E7C3!T:?@&-5E!!_,)KH1[=*[-N!USQ#02O-Y+>I -MY"-2%54K2?^0;Y<&4L%2&!>7Q'#A]XS^)`:J/O[NCZF*LT`]MMEU>0:..IV/ -MU*(T/FTP1L]KWS5'`Y7X="#BXUG=5.&:+7'>L"FS).6)'+_40@+/WTW]%F@T -M@2/B&O^,OV',!R`?3@"5R"WCW,3?LIS24M,GCR&9G["]==T:&>Q*$A1J,FS' -M"&9^6Y#_V#1'-(MZ[RQ?J@K94FA$ -M2QI77=Z@^*/8?#$0X7P6L:!JO/MS@A!^^&;.A/RIH>-1Y1?:(UXF+NE,M?#T -M+[:;,>E'C&R@A`?,&^@Z7;SY_/>CP(YGO2RH-)]HRRM7-/V="\W9PX]T)RM) -M^WGFXX"08N2H?S1FR9("PS)PS?.Z"IZF+^[M\.'<3MT/+KSL%3EQM(,?3EF] -M!(=B[="R_MK*LD#1,<+>@=OR>G0G1:+VX?J[I%@7ZBZ'7\P -M[2QH)3F*"D$KYQRRB*W`23H@N$DR@4*E>LL$QUO]!P0(0P**ZZL]."YT'_?K -M6UDU/D\8[KWF^R(2"5&#;%:@O$:L3]MDQ\O8^8!,1[?5#1MAWHD"+OO!PX5^SG!.6 -M,0#(,YM1"V*N[643BA]L=Q;7S4]WL?"MEZ39S5'/1,B]C3A-ZLF#C/]LX>*M -MT?N+4HIO/\X:KBVNC/I%W>S+N*3PGJ9@"31/],=MNS<^FF$3HRP?$2+-X)@+ -M"2TA_M^OD40AT>GOG$;,!`]8Y)$0Z#B&$&1JR&Y]5W(T)I%F.4[)T08`6V=- -MS.'2("&MC"`OG&WO#0*>YB#2@*0`;4_[>AZN@]@ -MA^>;YD/8,GYHJ?'6J]VU(0/D_%_TW$F_0!8""21?B(`$E(L6*HC`!8",)!44 -M545&,1545&$`%06(!%('QO@W'7158HJ*J"R+`_@,GP7]%NJI2'IH:$[WT_FO -MNJF_8C@@PQS@N*CDI*!@8Q@#(?[/&,./RTO7'P6@2R^B$BUF?.(P,P+V0.`E -M]IT&W0R0ED.R&=)JW\K;GT+SNYPEC/7_[G\+P`EY4W)CVHV:U#>T@X\B)5NY -M6HV=E-J?).P['@?O;+G^'@2/=?R\I=*D`3/@B'1>O@>!*[SBU]U@)$SL30`C -M:&/VCU4*:3`*6/+.V'[K?)2`%K<+^X754U( -M=;.Z_)(Y$'+'?(M+T,:>(GVGK6>G&@VUV;VGP'@0,0^Y2>VP*@I,/E30?Z'L -M6Q\)R[/>.T^WQ)2@V2GTZU2_$B<47FU2J.;X;FC!\$N7Z_&L5/AY>Z^-_F=O -MAHY$&N3Z4PPCUD`W<1T)SE!W#@:$$_H3V@S!OFWE4>(O389=DZ,K)BY"PFGB -M169)&!(BC?SB09SY5PC(KR'BVW"JUOSZRNELQO05-VN1+!U>6BH1N0>(!FUB -MCBCC]RBYE)H"TJ2:!JGN.;6?;21TBN]D_H\-VP(??L4/=,]:P5`#^Q`N)+R> -M(=+Q6#NW%0N?N='/Z'B'=QK>."M\B;S7\@3Y$Y>./]C0P\HBA]I^B/$@FL:F7>8>!*L1`_Y^(`GDS*]1@);R'=J/I$\@ -M^"N-]@:8:;W?Y>_83GQ/"'+DLO'V[9TM@*;Y7%\"6OS50;DZ=+`0@(:X=]YH -M[;;?8X.Y"3F@[/[R_A.%LNE@2)5B[V3A:RAP]F3#GK%M.@=-U('I`7/\XO`> -MCY)FDI/8'87D\OI9T+K#XWCZR;%V#0*+&:V*R-8V_ -MBUWC,BOX0[.;+8_?@U^N1O4!?] -M(;\\&/DU3SHX][0$/X>RSK]ED+BMRZ."8'W;[KI=&:.`P+CRXIB`/VYH+ZM& -M3I*WT_4T0$+6'`20G=K*"]O32[%YX:.*2W0Z0C6)N+D-9S?]G<9X^0W,JAGN -M$R>3&Q9\%\UZ,XY!N:]>NI%*C?5#!!"HE_:4J+5`0$'V#V3!.SNO:JWX+$.D]7RE`PY84M+Z'G(1#:4=/Z*$PJ39?+J!T,W?J@HDT,+SXE$"1/\ -MHX-*;`IJ_!S8&/U6G^+U%G@-JR.H$WY*4X)[U-YH\Q;?C&R$EF^M,[:@0@*2 -M&'`AC?^ZI\OE`;*W.C:>/P^/Z%[$=3XS'DNZ7@_6P.%V+SI84&:.52EU[X;H -MX!WD;S-6L0'"+*R30&+9X^:.E0?BN8>'GO5&/7Y(Q+&`9M-UNU.C$9P,?\!H<[9([*?`7XFQ$?2?LZ=(7\ -M!P[+,]8':?6U1TG5XF@+A!X1U-FF/?-?DTO1JFPBC*K`7#($6%/8A -M*_@K)X:=2-Q$4<.]S'&$DL6?;6#6R+(>68FZ;NE+_H\M(S<>(E\LYZ=/8'1, -M_]S04FV/QPK)\QW/*'JJ=)X2F>`6[3G!67(LX'#\$FQ[$[G=2[<[YKNM-*>*\E#=)3$*BI;[, -M:5J/%VJ-/B8=(_P"CCN3LP%KN&K7_%@Y?3]55AM,?*N?R+" -MP[SXHS_('QIW8BRK%181UQY0&MP._*MR$(\1K2:X?(9LP93H0M64RA"`F`!DOJ$6Z#A.+=0A@:G0^@*F0-[Z+%D#TN;ZZ8BM -MO2V+`>:6`/E]*0A]EF7VYT8,,ID7FQWBH=9C;L^3Y=T(`M8Y(V5;USQ).SFX -M0%M5R@A3HLZ@"6U9XX$D_RBMIRW.!+7D>&(#8J&!JY+P'BE?3VD4E8S/]+Y? -M\`)\*4KDL;;GB3*,%/^_2\,^FX#36$6&K6E?F8)&'DL^:"NLG^,MIDRE@:I( -M!(Z?;[2T(:MUL4E)0%9O_((D'RDNTQK9X@X>B(>N2!SK-V.88'8N,^<#QBOI -M!N<(:GE`!,T>.V9TNCOX:*D]2;@4)!P;S1 -M-+/SF,T`&B5J];J:\=J&"(P%'=O%38F?[O8=_&/"EZFR(LEK09Y8K9DGP=_& -ML.]WJULB(.#QW!?D(26%T@%C<,:^HM@)@\_9:=3S3Q?6I(N#.]ZH!&B$Y!%3 -MZ]C.`@FF$!IS`%]T;B'-OE+.,;4">J[K1QV]K5S$GJ<9-N>#@9V^F!+.NSE- -M^MUQ"VKD((]_$-59OXCD''42L"%M=-U-0H,N^@!?"29/KE//86TH!*/C+RQ[Q:?:HS9!?N>A@P+!IFJ#157@%L;S!FB3DY+?O -MF=J`3,?,_=CG,)!PY[R`5&0IY4_06_LUIO^K@(!V -M2!N(;\E<@D$0,.K9=`@@1R!()VJ!!!'\2&WQC':;KY'R(>SS)789D*;5*W0[ -M_P8AT@$=.[NHMQ\O0:0!XR$[W+W?YE^?@4:*4-'N/1^AQ@]A^)1)],7I=M[S -M[G('0TJ#TE/CI)J.CZ%TGW7\K_RKDCXH('$3?H;?Z6EHD!AZ3GH_L.V -MJ4RF2@?X?TOHOY/ZOD_*X$)MV[-_D5?%E<00*"`$M92^:,/8<&7VRFC@@ -MLU/-IYKCOU$]==0E?>>[*`B",EWWY;>AMTL@UM^:^4!Z.S2W&4:^RE@BPI?= -M+_]1]9ZZSB.]9"\X`DF8,%GG3ZC]*+,`AK4.ZU6):Z/YXD.3.+ST?M+?-<44 -M((;6%M='K):S?%FBD.\[V:,1!7K'&VDO-MVR545@/_*5:;%;Y$.J&1`9*>QZ -M_(,GZ?Z*5SNP0D+M@@WP.-K83>]V0@=)G^A\_G'I!$26\FSU(\)%O`VT3L1@ -M'R`Q$ISR4L]V.[_M<;-QB9:<2,/@#N3SK$CQ-GJ77JHWV/3)``>U:`--&OX. -M#S-4[F;>S-HD(!=6897[+_$Q=2#@\GL'XZ0"A*>E'X%A(Y<;MSN=P:=`!DDZ -M8SU\F3NI"81\TSO=V\\ZV/@A(3KC7;/<;F*57`S@1J9/A>%\Z7QZB,P,&-^6QF$A(Y<4[=GV4J*$S<6ZNZBKX*,`L^GT;8 -MZ"L98KT1^4YN()"WR6O`M>51.^,R3F_,/F(@RP:2.FR=/_)D2YWC97@!5?/Q -MNQ83BYM-S87.\VN$M:9'``0.&5A?&C%K[,Y2WZ+$U2(`=."QI;N@%3=H]VO4 -M.RP^8MD%C%E,G[AT67L.*[DH-W#&B@AI'SZ\&%)V"2_">XW]FCX(>R4KX+JO -MY?]2[AHS4RF6&4LEO;HX!0=[X^!<[`LZD[2RFOLKGP0EI34W:YP1U-_E]&_? -MO(R,O=$THQ`#)7/,=NF';*I6]W]Y(Q"&`6;4WKH@1[+\US21L6J[R;SW+1R( -M=O[XGC_R+':MS]5.V5-X1#'5_C2J7%T=FA]BW7$$"=B(!T=$MT]G?9MP>&[@ -M+0*$O*1V#UGJ<]X+OT_#T%'(R\U09F#]3?N?,`(;]F/@;:/YA2]UFJH'1M7] -M$<`4R:^9&@5@3/BS06I#GI[XA(AD&'W+M&++I-G&$SC7^9]/910"F?W]]V!. -M2DE'->YP$<(9`>2#98/T`(^D-1/>VO>$=6(0`DX/A8^V$RM@-UGDMN#[MZU) -M(%_ZFSBN0J7AY6<9\]F/(]*D1B`>6#V!(FN*@LL9E3X`]@/C8OU):W1X`&6- -M%);EL8DTQ$^I^ZI6T8@&PY4SAGYOKV%?%(0`RQ#UB-':?K -M$6+EQ+T*YFZ*Z42%I83OWZZ01$C>.M(>00;UHM3Y-(?`7J&_MJ\J)\D=_M\I -M/'CX(9RM;P7!'ZHX6QWFE@6.F12'U>,W%5XFY-)E8?-3<.AD2A/!/67G\A"`PJNM)D -MUJ&PK6W=C/<)J2001,\=X7PBJ\_X`D(*AX#,GCQ;M*(AUEB)#\]5Q7J>YUNL -MOCR,1?#B_K1P1X\@^V$$LD/?`:AO] -M2Q*^U#$V`I$9`D,'JJ@-_Q&155;VJ>>BC(&]4`>GX0MUK8WBU&HS=O+2N*`, -MWY`.EKI<6?PK5H!2W$\+[56/G_RB8/].OP^W:]OH8LD>"X5>77@Y353MO>\* -M"#>V2J*14K]+_:?+^Q>_XF6HY`^`L-&OY/(%:0[)9&F[5MC#P`_Z"\E'ZBQ/ -M@IT9TG6D_OGZ)`7\]_<+D3!X$(_@+IP3FG-``"J9Z-.22VN@S[5\JA#(NU;$7:Y/EP. -M>=XW?8K"B])0`=P7G]`EG.82?EFKU(!.'T@S^:!<:[!&^?>;1F]BQ?>%$`R;MZP3FB -M)HPT'8O3Y-5-_\[6;UCA.7\T0BR=31@!P&=IZCA+;EL9K@>J&1P!--T -M[!D5`)M>QO'UQX"$>"`5>_^$507D[\38R@FE*G4SR00$NRO-Z"H>]1-ZJ0J7 -MGO?^C;+X>Z[Q8)M%BZ(R4QVU[3"(=;-4<4XD&Z#5H^% -M20`+=ADJ<@EBTD//@Y5@/@ER*FP/Z[=WF(R-(GR#&E@ANN8X;H=2=7HY91!> -MWSMT0BOR=X,>^'@7\7W@>AC("H66:_@X1]ZG#?TMR.KN62"`;,_=(P*-2-P] -MYQ57<@\1"*1*\%8@?!J@+?KO"*?(O3/XV.02M760^0@$)4`AT!CKM>WO#9J4 -MIHE6`>U"E)A$N;L`<=U1AT]'`+/<:Z7K(T -MV^[&``37:C#LO;JMXP(@,[-N_.)O/9&.?PWH -MGOU9;T;Y;)46EP0FP[/YN/OMM7FD8.&S^$"W>T0PM/8;>,G48)X@.!M*"JSJ -M3[Y/@O"AXFAZ5PD8/PAN20%S[/8X^]G;8OM)09W%'(F7S1LJJ>,A.)@R9P:O -MPD7LRWUC(37JY\#"]7<(!.\0?ES3X>(]0/#22#+;:A41)()K_'R9Z>P5&13M -MM(X['KTT@,G(;%TN.J[@8O>0$&^KB%AR=/Z9JF@OV:P@7KHI`(9HYPN*L$-I -M5ENTV3IZ'!:=:4SV4LB9[=:>2"]Z.6YYL,!*OT0R`N5?8>8AFND_,%`CMV`R -M(']&(J=UW?;(0W`YW>6-+L'FOK@`YRU2VL[$^>;M*DA,WYCCZ;-)!#N1>Z&_2P!@`#VJ>2M"]3;+DS[JG)1%Z=Z`&MN3`_9F@ETS;>HWH(="JK/I@)-XU4Z(3]'$3RJTB&'928F(9?+N,`C@"K(E$. -M&-YOUJI102QXJV(2IL%PVO:J6,47["0P5+%W--4`!KVW07_8*F['9S" -M("_Y;T[_WP/9S_:E!.;$OU(2+Y)NK(1#>SNT-O*:EY:0"N*:@(@E<#*P_19G -M>IAD8'[;2I)I_&U0RO%;YVF7$B-_Q;(.-\``Z,L*T1X>NK?8@+OAX!`3W'F< -M3;;CE'R<>K``%HM;$L/UU"4YI,C?9A'`=JLBT?=IWT1\1X9:"1`+2D!*Z&P3 -M,3L&?8.3Z^4UAC`"H[.,X)$);/\ZT]=_"P?T=^C-Z.S2`+Q>8?$`+G>IC?>Z -M=&/@2A"E]#4WRG4%4]P'N1062HNE/EF<]$2_(#<>`]71!#&"#U=4-I)P.GSF -M;"*14/H(J7ROZ/98AXP>=X]SR&4;QPO$P$GYS.=(B$=X*W-5PR$VEMJO8CB5>*!:+H' -M<1;CI%@3GROAL2RZ?[\TV9_?5`>GGK4;>HD0W>\` -M#9X.L4'53*6CEN77\"&?EM`+")WCF4FA!#FN/'^2[PB1/P.D[3WK\S,V",A; -MMLS2@B^E<+?"DZ:W2(C9=_]Z_:$BFR^?;'+DGH7T3/@^T2`&:IK-_"+O2J,\ -MU(I")8_O%D!.V%YX)2D28IV6TMK6-`_))`1T41#5K20\B'GKS]JR;=(Q8=): -MW'#(F6\1PCH[Y+'R?>&X\@$+F[\Z]/JFX/WB@_'"%9U2+4HW)<%[F>%PR*(3 -M!*Z;&$!2R@WV,2,9M\@_W2*"J/3'D0L/TC.FQ!UV%9%)J20[+VILG+(@L;3' -MJ4ZU&/#+\-9'DHB\D(@+T4/OO"++X5C%.&R_]HT)**=DMC2"`I(QWC -MUFFA^=,:]J1[3&B__-R=8*!";O@"6??F+AZ"\M^A*()`!=W;63[.$ -M"T*4'5]I\],)6QK$4"7UY`/EYW_:TBLUCE?XB8E`LC)Q2`>=Z[CNZ79I3(A* -MR^#N"D(7G;K7XSTCBA5@3-!NRE`+,T'1*2"'<(L/-D_-DRI`3;7U0Z;)>OD9'`J5L@%)4F+Z[H77]D(68S4>S,D06Z.LZRNG:S!S -M]9!9D428`+62>C$"5$6;RR>\')].P3D$$](H$P`+Q$#R9EM],/LF@J(<\D$. -M/5Z&N(%&=::F4A=/.[EPZ3,D0?,TDHW$5#VJ_.+9+T:K@@-AS%F]'`C^0RN6 -M.T3PP8P/*Y'L<'%D6,M?KEX1GTQ[F(9"7L'']09$3[G=+LLC3'M&O\_2D"J. -M-23_-0=UH]+PB_]$2:EHB(LCL+EZ9_L$K.P?_!%C4V@TJGK^RF'5?3&HH#W4<^([=]`GB(* -MD5I(S67Z/>1&OB,!+&4]W!]L15^9&!#?R>\^KRQ1*/45V%@$06[2:O-W1)4; -M5P@K=*ED%_UM9$F,;'O,ZY(K.AE-9\B+4;OV3YR(NU(3Z&/-6M70(BN9+N\' -ML6C@L['=3AH(!OA(W687;HO@OIEU!I<8"+%8DSU=CH3+KG7])+2RW&G9)9!$ -MQ3;ITH2B6!BN`1`O#JF@(/QQ`10C/`7':QDX8,LL'T0#(.-2M,NJR,(=0>`1/&Y[*7J[B?1AG% -M9-1B$-Z+7N*DI('6:N>R8MBAV_Z_7(O.3=5P8[)($D+5KG$;E14J\-D@R_UF -MLF&AA&/2@6)ZJ;TZ"\7E;.)/TN*8W)V^ICH>)^QR\OC]+_7M)4#V.("KGD7? -M9_&Y+>H95?]3-GMO9,YO+``2779/YN6']*5(!!*+T\?CMLH@"7+1>[/ -MD0(#@&)QD)H9/ODAR$DD)/>;%E;NN8`?8H>.\=GM&$A]>FMMU]R]\GP4Z;Z? -M&K\1"`'8'_&H29W967@\S[B@0/F@@@$"@$$$" -M[H'M:I>M='#:"WN/&D).V0(?^EY+-1M?,[Z5E14BV`0Q$FYY5JF1__B[DBG" -&A(09YF?0 +M0EIH.3%!629369%IQ#X`MT#FU'+1O7<;MT;NYNNYW<[N[OO;K>W7+>^Y[M;[LV]??=M] +MYZ[MMMO>WO;6=W.KIOKNUF:EFEJVK5I"+:J;8:B5K1JJIJVUJV,K6IK5MJJ6 +M--%5FJLS55K158M5K:U5FU4RVMJ(K0BK-6Q0-L+6JVLJ6MK559M5556*M54J +MJMIMFS-"U6LJRUBRJJRV;55::M6U[G=0JI5-4W66J=KVZ]LNW=]W=FW=S;YM +MDO<]LW>Z[WW%E@WUOD-[G!SN<'=W$CD8@[KN<36:PVO=W;*I*E%4SC +MV]XE)5!54*"@*JJMH)J0H*`4&V4`!11(``!4BJI27O>Z(]5()`22)**%4``I +M0`!*B5`D(DB*5@:5``AH`"8F3"8`F0#3(Q,FF@#1H&(&C)H-#3330!ID,C`C +M!-,F)IIA`TQ-,!,33$831@@R9&$T`!,`@TD@FC$``````&@```:-`3`F$P0T +M,$!@`$``#03T!H-`U,`33$TTQJ-,$P$P%/$R8",!-02FDI"!$QJ>S,`0`$!H +M:!#":$Q-,28$V@0-`34]$:;*:>D]1I[0H'HGDRC:AD&@]0&@/4`]0R`R,AH- +M!H`VHS2`:`(4E)*)&R>J-^GBGL!2,:::2;48GI$IO%)Y)Y)[3TE/U1^FFC*C +MQ&H>IZC$T,AIZAZF31H>4``'J!DTTT---```#U```-`9#0T``T!(I((28-)B +M>A3TTF>14]3VT&IJ>R,@F$TQ'DT3&@FU3\4GFDT>J>333&IBFTPF$T]$-,32 +MGM-4]IDTR)ZI^1I3V332;(93-4_5/R>D#":GDU-D:FIZ>IM3U-HTH)-25)%1 +MM3:3]L/-2$FWD4S4U-B:::FB;4V3"4_4R4>H>U0;4]JGJ&33T]4T`#(T-&0] +M0!HT-`_5`!Z@T````9!IH:```````_Q$/Z:,D&8X$&L.'B.D00+!M12TQ2"> +MGH4)$$U776'(,NA5T"`@H&+#%`;<'^;2<4$`CK#I>?6\SY]KTOQX,LDD%=#] +M=K=W[.S5.*PD:9EE+#8V,8RRL@"_3]+%\'Y\OE<[XY25)9,&QL(&#!(B3@T. +MCTYNF5=LVA0D0'QD+"T]J]AX/R0)P"P$\13QX$Q,/GR(O5_U5.R7J.DE`0K( +MEC0PL$_ONQ0)A@@60_";^_OE&;Q_:\_3BPGL8?\=O:KUNG!-MF0A03X9PPMX +MF'WE;&SK)O(N2J"`80_J9Y6*=6(?DZ7*_=I%;(JB,Q$/X5S@P$*M6IZ6$>F. +M&L;Y&C($S\KC'O`Q#')%M:;\FTP-4ET5[;UV7JU<$0D7*H[&KC\]MFO+$`\& +MK%L^,?8,8N-=10VF1`%ZT<0V#-6C#OCSQ<+:D1!\*'M+14@>!P\/!T&+LDA` +MM>S!`Y))"PU-A7RRF1#XLD2TAAXFXPES0HB!="\G,MI5;+<6\:#8!?:^9F[% +ME',L8MFO;T)7.GR!;_`/D0:1+;UF7Y[3=J&V"``O/U.NE!"#*9$.X86#N,8I +M`#2>Y2VR.+WM3?[`$7UIE`R.12-/ADE3=;A$1!:]O_:**7`0NS1[]JFWB&;, +M9H]?3J1$29(D`##!T*ZI]K?Y2?W`!+<"-:V[)FM&)64CY`27=R&1(43Q0:.3 +M57.RL\G5'0B!%DUBC6R2:/8GH36'00V/_3FF$$BHG7;+O%I3X!8&S2LK'/>1 +M8OS=Z#;4Y$43X>>W=G@!;JCZJXZ+CG@"_SV[O7ZI=P8DJ:+_5D',I4)`;G=/ +M'LMX@K6`@UZ4;>CQD0!>G1L^>LPH@:>W<=.CS^7@)?+I``+POTESZ]3/ZA2! +M75?3@*BYG9V,AZN4Q4&IJ@(<=6[N*2:B4T)ITB]VC:@%[*8[4SK5EZR_]5WDD@B*BP]Z +MM&`(P"9NX?<(%_4:IX/(`!5M=`Y*J0ALV/=9UEH,?/)])PN4S.3Q*JX(OE@. +M2:Z?"+C-^RQK#(AH^YZF'"(N4H(.K.`QOV&@=HI"`,-P0@1,W5)#ZE916Z/V +MDMCV8^`4YS\-7R*L!D&Y@OT/@[O\HB+8?+K:EP*>6KQIHI#9&]*\I@AOG`B[ +ME!(1^\3.":TV[8($^"X\PV,D"7'@5IA +M_&HS5?4^K5(@17-'D>"%FJ8^%HE-%-GP07=Y"M@$+JL?O=<_H_;+X"$$)/+$ +M(#&Y%>VSVDIS6@!!PH[W&3U(!SXV;RV<\".VZ\"A!%NDZM&LY*JMTR0+GH5% +M-UD0(OWQ1PM=G=;!V2D>(AEP2@)MH6&EBU77QS:R7B0`5P)?N)=]4'"%!``L +M6>;IEY>3]?^J#F8Y((@VJ'9(3=(Y;EL/U*W3_M""&*6LOPA)`2G2\;XHZ?,1 +MN@9?--I!`7BU)`)6&?V2\RV=GPPO_+AI`13_]&!9NI8WF&D8=EAD>=1@A]-M +M2*,@.#^UP_^]`1,'Y@7\>&O=GPWW86]K`46*"9"107H9R&2FIS4QC(C9?S9E +M0`/+,`K\G03>F3F0D&K]O^I"WC##9]90$6;P/K*\,L":#V^TRY\OGS?!Z.>D +M($R4A>S*K^+BN!7^#D(`!):^.YO0(#Y_7L:3*O#7:[G5>S#2DD#:[ZDW8'GX +M2)284[['@*/]+TCLR$C2\R=8*W5,5CI?!P%6`2B(:+04!>;6K6S6]](_;T]*B(`QH.-:D+F0Y(DOX[O8A^D&ZOMFWV'@4'P8^/`G6' +M4MT7D&'K95`"'TM;8HC'LCRM8)T%MM8^D+N/=;2(V#3NCX`4ISMR_2ZY!(<< +MODMH/*.`-_8\FLT9T`6L6N;B +ML+\].#\V8R;3BE920@#2V1+PA(E.R3ONAYKUN//A^GSGB+*OAX\D`:G4 +M:N6A>'`4Q\%%^V;+*\"K@=4D2`OFKMZ-$0*_[`*>S-)N7WOTB9UK:P8!A_-* +M!#IK6Q(LWF_4F>(UJO>>(9:Z7`0D,+EMF0/N3>?#*1()V)O8Z86&8^!<^ZRS=X!-^V>ZVP;`ZT!\%Z,_M4O]>(!*Q +M%78V.MY[N[_RBAL(JLA?)W_"-+S/ZED0 +M;/3I;2@T6N\'?(;S])2EU,C6-+$@`&SZ+)688"[5QVM98;-GB%YN\`AY&9IE +MW6!=**T2J@+$5]."ANQ]8K\>S;J0'=Q541?&&5H]>H.:O/8H/BC(H+5TL-!% +MC&+N0$H<`3/0LN='R;P@R<.!'<-C*;7FPP#W3-Z"8=_X,P_=A +MXHKO&(2"G=D,QU$C((T6%6GP&!#S"XF5-4V6YAT`'5EB!2_H5R+\+"TB'N$` +M+T%X4&3]-]G#I0>*@2%GIH7 +MSW9O]0D`OIGB+^\1)&P36=Y]RD/%JD1%"5@`[_O_LUM7*JV1\K6;+I3/![/Q +M.#`S2;N_U[:(B>+8XRN,SF.'J%WW8:0"&DUMP7D:"XONX&O-1"LFTT^RG +MR+S^5?!8/;3Y9K[##DDM+1(B+E*B/MD%:Y4H%W4-P>!,]+^'3!:;H\PZRRFC +M,*N]1$`Y3OHLIC/@I?18G7MEW5J04*WZE9NVEJCX]O3A@!"*.^XTQR#K_H+B +MK`_GST-]:GHOXGP6;!7_\>WC/V4[-<>[Y"(A'>SUX`+BNS=W40.$/SF;@#%7 +M/G9ZN`.E)(9E.O"`OX'_/=0TANWS\@%ZGZ"Q`@[-KB[#G4C"?(+B9O2!?3V? +MU(RWC7&#H]VG6T@"3_+P0#-+4"/+:-K195`'/]=0!>5EY/E\%"0EO%WYN;I\ +M,!92L^L[-@(=H^*F`-%2+>M'^T?2W +M'C:U,6=Z7MD- +M!S,3Y&RP>BX!RT^M!(O4_R)^"A]\?+TU4;M'@"5;;:ZIS@]DEP@`GW#)=.K] +MO\7W&3'^J?:TH`>FSXA%M?%/2O67]%.K"6EKOD22)U:K(B^/TNND%OAGR,>$A17>EHS;U89'SEZ,TK*[C@G2H>W_/QJP2&S5GGO +MJE2]X=O]U=K22`\/)G.A*\;1D5Y8TB9-1"S]]V@!)?#_OC6ZNP(-L@?M71N) +MF5SY`+]]\X//8((6RI`6'=Q>`,79HH,_*7BDQ5B$ +MF#C;\$,9E\_=O%KQ8180+*XJ:0$1[TM:]]/]?3>UY$I,\SDOR,#I1E=JFS"! +M)D6KO$6H8D4OU,[!)!$>B\C[>U3$!Z^KJW(<\.5K:U&!G41!!%$5_Y/6QC+5MNVCN4"&]Z]DJO`(9_'6]7?*ZF8/$&+R1H`D$,1>.+._G@W*)DDB;]VG`*5YF7 +MWD]IU[X\&5T,-")):A_]LR"]=;MJN5!LX6;D=]@@KQ`@^-G`>;-=H$6+3?0; +MYG3YLP?<=K)H?)5`"JW_5R6!`Q9OZ8Z#_17/+4<,$0*_:]M +M['1B(#.(QC+-;7CH'N\LREOH(>W0-/OY\=&_S[F9)"7_77XA@06;X>OJ&IOK +M]_"/D$]\6"(#S']/.AK:OAKS"CC7-%WN:`*S+_$Q\,^Z5>:9-EA;.ZD`(GSF +MIQ:L*`\3U-]F](KQ2F<&;.+!Y/Y?&`$JI5%RF94'0/-]9,`:CO;'C<7'S6Y/ +MC(IK?C@3Z*)/UJ'6-^%6!`"074SY(^7^GX$0[^K\-)/;:';#_=4R9TB+O0^G +M[]]7D3#&W$Q$WJ'_>WZV-KK`!WGEP^O)3UHKSY6'>%*ZJN$_$'M>40"Y'4TKT[6!UHFC)`&?/)6ALNE4_=YKB+#=*OU0?%/4DSB6RY5I(*1T +MBS_(D<8`16E0,O"KK9W:_/'P9`7LW2]VZ=L6P&CX1W4GLP1+"_P[R>#N[U"/ +M6WJ(6I\K#MUC,*=$& +M1:KI+^\1_-\P/5`$`\H[779:X^25NX"RC<8`-!NW(+E)7#8<-$0NNC.=8%;Y +M""W5''H1A\USP=7IXRZHLP`5SU[KII-+72^YR&2"Z82`/&[YW!C^'UK5S(MO +MW&B.-PG"G%8BH=8XL2#/=7#/E$X>/AR(5Z^AT]%#>CG.$(E5&]2?[<@D>*0/ +MLZ<&PTK&10ST<\S7A0!X<3B>_3^EJE_\RHP"TFVYCEX^77UK9&C9T20A*]99 +M7K6E``:<-TKEE8"N>WK92J@43N+VH+CGZ#],-YHU(37CX]<0)-RJOCFS%/>< +MAQN%3[ZBT6R(:O24[5N6@(0PW=6K8XBYT._;F*0;7N`AGO:TU&>^N%)?1CJ+ +MGA$!F/HR`O_,-OQ]:S+*EE+7F; +M)8:Y8$Z23!0[=.AU<55;Y+G00EZ:%X+;4.QH1$7K^V(=S>;QJF5!%*(66:M6 +M[]<2>?+NA5:@B'.L/3K#D=IF8CCD"I:=]2]C(V:VB`Z +MOS\_5M\P`2K/>9)C:#G,^D1A32(@7>9.&JW(0D0'@NOJ*)ZVW.3&/)46P09QKXZA5D`53`!D=\)LX*R1 +M!$VM(PTC]$J02F,8P,".;C\K*?9X_7%;MH6>P6<2HYV8U=JFL3)L0P;&-M=6 +MQ"QWM=K46:O@8B=]_\<9C+E\'NRM?3;$*AU\"9&FVFFQH!@"],<7:RQP[:(X +M(.&1#:N&(>`2H-SY3E0:Q```RU<;/1R="%-3!('Y%^`@'U3/^:?U'4DDD^2K +M_QSJ>F@<3(!_5_39XX%+[S0)3Q!$2G$(CR,W5,0ALWVR5@^PNW\Z?G(" +M`E5V)'F?/MYL@H'05?I>U/0;5$JNX(9@PLAMWF/]5Y=G2)KZA/W]\6KGP7TW +M=W;`93G$(W[@47APG.]9PXDV619K+/GQ=Y"H#*8MA2K<.U0:]J +M:[P_S0(`0S@3L$R/6W=-GT;+A'"+='OL8`Z36_XSN)T+M;(@*I\0Q$P[W.QU +M75`U^S3T[*WDD"J.S-BXH)4"-NVA`QPE7A^H`7^G#K^Y#]GW?Z@6;MLN!LH;Y8V[TBAUSY!77`-3DZ).?CA%NN(3U]N[8L)PO7=2[[? +MK?+IP4G)+./7E[L39T%%XY?YT$-0U[8TLY4Z3UDGQ6P.(=`BEAE9/#\#15F/ +M`>_ME9OM"".@E3DR84IGAU)L@Y9W1:M_[OX_)?[G)6:Y=`;!--*(GTMVGOC@ +M"M.:85V$\*TYC78\0T]2+KO*6=_-F75H3!"RI[5E%MF-L:((=8,M2&70#ZW- +M$O9J/0@H[BV!#T_DCO-3-M>J1$32[58X'"UIXHV&4I<18I##UHY6XXEJN&P/ +M[+_)I,DH:BVYVQQZ_O,X=!-]/8)XA,][37V[KG"[%TA.S(Y(\1:.1<'+8>P! +MTC2B]U(SYL#9%1^*\-#T-R]I/8`]M.T2RK3'>,$!HM`\3#=>9@\`-?GY`S\] +M'^7GF;T%I/11:4V6BU8@[1!]C9"PV\A^?P9`WL8!?79D"YCUK:`64G<=<^![ +MM#C.5F/_>8BBW!5>]G?,QPK`MOE8>+$X\S@'%B3EB66;K,\3Q-+A\#K:&\@;TVTVP'I=^: +MY=HX3U'3"E-E/-<7;]7*'2RO(T-)_@5+]/#*EW,7;/R1#'2:/\X@06H4X2+? +M`);^=S>ZPX(A-FAP#!KYMMM\W+;4D_I/>>`'+KI;G\$G;W7IKB3!)@6L?=9B +M8*,D]4:LO-(+-(:$GC_"'/22E/38XZ!EYB]IL#7&,F0SV+_9H#_L$NH_NN$; +M`YY;>`WRW)2(R_EGS0Y>4R/2%0UT!H>XOSJ#,5UEL#1:S819LJ2Y9YXR$;:* +M+2R9H5&H;4'TW\@&]O?C08ZIYG"M.?O$WF_L;$_+KZ/I@,;.8VO8-DAQLE_@ +M*F+&8>S(8K^[BR.2[.:J/%0B[B^IOZ/H"=7ELT(5Z3P-M%;0Y0'"PW0%B^-L +M^CHCB]9>CRF/0VMBJ084\S(]"?`EVGY&D]WJF)<7_849]9\T%NQU1^_WH&,_ +M5^:^K6L2FR(J\PH/W*3)P.C^9',6$)OO0-%D1.;GY>Z%(/[H^5!\IJCTY>TVV!=^XZ] +M/D?;R_(6)'WW?`>S2].TI:(%$?*%L3XD%Z`_[1*CVU3[S"EBV,S3O&V(D7C? +MCX7#((A-/5OOM."4.=)P3%-$'!ZQ;SBG8+&8(;Y]WO/QB!8>_ +M1`09PN#_L;#77^>^Z%CSS_RF*D%4_LM6Y\0W(7R&+SJ10?Z[!0X^R(2VMM<7 +MZ#@QIZ_ML697.F[D/>_WWC^,Z;,J'`[$<)J(QAJ.R^W['JQ@*YSF!LV#'(0G +MINP0WMHSPE6@)+;2#N0I#RQP\XZOY8'[VWX$,"E;-W,?+W,3.!;[=@838['X +MN'5^;;`/^,,G%+:5H+V&^EX>L`)7RZ=4\T.LI[4M4,2"M_G>?%I`_EHW'7=U +M+'\NP(?YXV&)GD&EZ'@@71ZH48<^!BD^E^U2EAOE3@"A4:9C6">_N/?-+AH: +MV$R>6I6S($%7H_C2_"R$&>,CKU`#E3X^\=.6!@_1^I.?=:Q_$04>S+1J?7[P +MOT8K<\G7.YV1#T(@W_3_Y[^,B6: +MEF)6-335TB(-Y'S(@B&TWK?H@"KS3:49A_AC%$T#$SB3$_&C7A%PGX%@U%E# +MH3OAQ,#V+C%%TJMF6WRU[G>I.+H?NE^<7ZO7[4$JNYWJ7W[J"60W_3]NLWF+ +MRZ7*TDY,V)/9C`GOL=[=+.]8$$0`E5TIH!H:),G*`Y\F'SZ6&"/IHYD84M7- +MB@SK9"-\W8^A%&3A-3T0L_8UBV6.(/_'+6Y_4<_W0:X/95G9K[]6,VW;)RW[BL&"4QI*+FQIL3-;]0MTG,P&5];4I-/<#MZ[$G6F\QXH3/S1?6PP?`?+Q$ +M]R*YE='TQ>X[,Z+H34N>&#L0FK==ON$!U>%8>&^_LQ7N:&03DMT_&/"P/5EL4ZUQPD"B_ +M&<%C2OQET?ZHSC`WFH*3S?D6R3B,6V'?[-W>B$Q@W>M,_N;\<`M2)=NG;C07 +M>9]X%OU`=]09"9P(UX,A^TM<,V7&O82A?MG/#`EKFD#9CS(HRZ_O6S(@.2:6 +M92'[SCA]-D@A0XX!P&6[(P'*M+1[4=/><0R]>^8MH)B>5ZXD?R9(8"OG#+]/ +MXU#^`[.XMGMC-!X*,,;J-L\ZJ[9JT&"-'.[P5%`A]1L53J-Z8O^1B&F(?/F? +MEZ6-.7H;)E,M&+ISG+`U?ZT)VCVXY'G]3\C'Y&&]UV(.+R!'\3#[M"',]^NSG/W!-`R+(=B;KN?>=B0!7YM]TGPN?R]6>&E? +M2\]9^5R5!!-?`^QG\F?HCEEH)^F(2RF_6)I0OS;,8,&8'4?ISN> +M4>5)YWW/\][[2T/#PW\^+!DC(RF'_+C\3NG0WN\FGH(:C?6_:G#U_-QO`]/L +MS0O9V;_2/OARD3*]*Q#?(@?>WP$_1TUJX%51#[8U%HU5L747&5+ST6H,!2 +M$X;-DZ;MV/:X!CJ#M-XM6U]D;/`Z@0PP% +MF8::)8Q5B+;K[!7`EGD7FR+Y68,^N&P?O`G.GY'PAY'?!EACMOFL9%XRW$LB +M2'AGMOZ+&XPU;+URN9\?W'D-6+ZHR5Y\[7_/)CNNL@J\UM&A5Q%+NN]]&.=% +M$U4\8`_>`>'`,HH/SN[`*'XE]#\?44AD&_N:@Q(@E("%]S%59Y!(SB/1:].4 +MW5K]Z+_CFN-\O"ZRF5<<61,*,QBBQXIKL0[ZB\?,S(&W)JZN4#'B-$WN"P)EZU%:7!\\_ +MG(CG+4Z09+L97)['"&1WNL:^#0DW7G*"RRF!3,OP,:)>2;LNA)RV"3ZU,^R* +M4.IG6(!CK#(+B8.'T2_W^NROX2A*1LH=*[VT&VU\\HRN/SG/#=KGH['/O<.# +M:MD,GO^/']`S!X]Q"]Y&MNP8FX^)U,5ME6[+T>)FM#Q2_S3_%VXB)5LUEX +M>+7;'D@[U-(:=6'&SD-&)[Z=DZAX<8/0;,9:/#^/J'9@J"U5#Z%&CSR(T0)V +MS.Y84,1>/W<3VO2T.].F:1;VG!XQH@Z)_,\(KV&\\PX%;;=Y/2.8S_ZS4_/=LX2 +MVN:NW,>H7RAPLCFW?KW"Q0#G0^A/!= +MP<([\FPL?J-D>"ZJB[,K_26\6@VQVD7L_`CR2IQ76S4JX\.6S6#&)2VE,7G+ +M3%:>?-AUK$ZV[*N&],3ZW.J+FV#:*#KV,^YD]6>2I*C$JJL2\7L&MZ:5Y\?> +MFZC=+!FI!PQTM68V@V7$888RN<*)`:TP=[R\]U$&_C;4F:,-':'75;7BZ?)[ +M:->K&P^#J_ZP.M(R$//!/IKX:D:#WJ/O*#T_!J)VF3#.,JZ\9GIRTY"\23IL +M[7GQWV+W#DZXJ?S*:M^Z^94<4.IJO:%]CN=[Q=&N1;J5O3Q6`BS@%]",K!&? +M;D]5YWW9KDY8FPV5)@E1M^=X="Z=95@N+B?B8A2[V.&;T3V!F^:R\7J"K&^5 +M>B4GI=!W*.@Q0$I:WC\K%/[R=-92FE"N;C72E0_U$DRCA%.MAXU7G#%G=*5W +MI'''Q@<"!KUFH=&EX?'G-2+BX\H72GD2#6;J3 +M[M!IO)0^%X\.1R"A\;JB^=/["Q?9"(*5_A_;RO;D:8MIG2$S]>8SN=@NGQZ!RY9'U7`WG;M>";K1[:9B$VB\<#)XCYV; +M=D8C`ZWY0NRS5^#$]6^RGZ#%!X6[A\IPI9-IA:KV)FG'(/%)6F0^4=H#ORE_ +M*0>K[,L;Z_OVL8YXT+^_I!BDS)"A]8R=)C$#HPW9[!%AT8K$*`W/?%^($=7/ +M/-ZT&8!)T'',A*Z_B'#V'B]3DQ^DB%LP^Q@P=[K[VNN&\-&V'3QK#)OQF7R\ +MFB_T=B?K>K6-_0.T;6*KK4E4X#0C.>C4:EL'),%X?6]^.;BY*,:3(RVI;K0V +MI[FDQ7J;,?GN#^M[3F%'KBU\L#)1LG0X1[*W:)RE3#6CW,.?@//J)#2\"S.7 +M\V1XS`6JQ\L>$'K==I'+F\KS.N7_RHPC6R$*9!3;CI.^%Q=1UM%9F-Q?P-S> +M(&DQZ8'4\=.>PAJ9Y&'[81 +MBU!XS]NLQK6PEH;8R@A[%F-;+C15JNUH\4:WSVWW3D58ZQC'T*'*;JUU&XJ] +M#N=&QG:27'&21/0F)\3F"IFV').61IE7[!M*A;^'0B$[B$\*?;3:B4PT!,MM +MV]HA%3>-R?[A1Y@YT&.I$4SEF+:OI;\2-Z= +ML]CLQ!48G=#\+[HFA=8$Z`M'\!.(#Y[H%J!SPR$VV6OSF^<;N#%^;%&+/.9X +M<1/#3.YW.`TMZ^`)[L%G??@EE0P*+I1[JR1HX-+>6VK/.YF!JF1=*7EX2< +M&\7:DPEVSXTW??#PV/G7),\&,=;;=K]5#?].'AT6,RM<:`P/@U)IC%WH198Q +MC8S]Z`=Z<\:7=5](-56M?`RKAS^Z6_U>.S9=BA> +M)FZ)9&HQ^$]0W`M`C@`MH[9.[]RRC`@'1U3UI.T)PQ?1`T>:%K'RVC:S61OF +M96XXV.DU^PY,-S60)MG3"YC3OQ1/0^5!`.$YAEIHL@@R(=G'A:'QT<;8&&6B0)61_[4IJ!K'%5).TB*[WJ(['O&K_"$ +MP$-C#YE/FZP?AHLWGK#.ZO)7=WF;NSUC]+%,.U^W9IENONCJG0L,UFK*QS+I +M%S&LUI;]C3FAE2]T<$T!A,?%YRAGK\H[/*_Q)?;TJN)Q11Z^0ZXM@CO`,Q7B1->Q(S2S3NE6Q,$\^N-[]M +M1#Z^YM_X?!J&J"7*?,7LP:X$1;"MH6LVCJPR95[HKIT&G2N8VCU_J>[:,:=I +MJ#/6K>VTNSHABWO(Z7/Y-";,/35L^NXO69)D49Q#L]CE5QHC(,4+Q,T.9E6@ +M:5,#D!PM!]1[$]'\A\OH^![X>_)[X(P_1H3YA^>2:6T0BP#\<`OX=I&,1(?2 +ML7WQ4]NC\&D])_,[`,]4^F]_R_(,!I-!(`.QYJ5Y<\^:0[1&>5F:=3<86763 +M!N/,2PEV>JAC'AO9<=`8_-=]Z#%(C&5/W9CQ+BE0`- +M.9S0/H5)3M.4S:$9%/._OL]QH;?'^,3RS')<,<\?MF9[#C7.+@:5Z]ZEO,KR +ME&C4<'I%0M]O&,0GL[;V9P,XS?P2[@;&REA!(_8PSB01DFHU7")L([$DQ&<\`-5A(EH'/YZ& +M=,[$\]=\SCN#4*CN^;=T#K3V883?\TMN,R.2\4'>;]@ZS_72Y[?)_"W>'L7< +M6S9N9LKFPQX5>+Q[H."G=U6,'0O>D]RQTDUN/$"'[M9/W[T+`N8A!'?APTSB +MUX-PK>+,MGQ&37<+7?8)Z6O:AA4LBV5&3&998%K7DR'LO32L%#.]P:9?V-WN +M5F"FOXC?#\V_(()7\#XSU)[\7J,M%BE,%9#(/;5&H!5ML6(*M/+*UHXU]<#U(GFTE* +MIAIAV7%BBJF6EJ'QU#M"4C4X343C7D\K6(DS]"^KIX/PIJ;[N]&0_;AO"[MW +M1YGT_YZW*_/\5:_R +M@.?#1+X.-.[U4RU-((0^J_)?%17?S*GO@H5/`-LFI3L]0&&\"&M>> +MK3+DQ&F*>4+\=]-4F,H*JJJBEFR,^VJH-*J&VQ55U?=10H7!N*"'0$E,@8?D +M0<]8&>G6D=/Z?+9K_1DT?J-A(F!@1WXT)R4QD1AT^U7G946<)I]*P]2=QG[4 +M?J*3?,"%^*QR;#>]SV6%A?:S4VEMRJA.W1CV!+^`G?']ZBKBM1MXM7@4U,X7 +M^:-=#C%L<>8VH1\Y*&+2%M12J_`ALFD'S9_^S,=]FY3N?\74R_+_6+D#0K`- +MT996(1ZC!"&>_NE(M;>W#?"*WR<\F;P<:,$==RB8?65C6S-",BY")BF^G<*: +M^01=&:?=^"];C^^CO_V)=K"JHI^[6K87'QF7-<+]9E +MCXU-JIP89K=QN6ZV+HZJ_%\\^ZQ7M^RFI@CRYG!])\`F+C>`TK]HQSK*WYW_ +M>S(4V@?L.P5IF"2+BJF^D/-8"SE.1BXW,+[-XL."9%:OKI%"RDF>VR>>GEH; +MJ-?AXUC\+B)TS7N7IZ#^P-1^*8PYL\([&0QD6L0FR7W80IY-&(ZM/`O,#(,4 +M6$\C/6FHI[\5ZAU=1J\#V.K?;26[DZ>H3IZAJEA3*FI@(S%>X"@T/W6W\/55 +M`'U`*B3[R1_OYH+QC?'/MQM2M +MQ]E>Y&()C1, +M\JZ-O^KYF1&Y,L$N+Z-X3L\`PK+H\0ZT.LH>'D]K/._PL&MQ<:^N;K`\:%B# +MTD?I(+1L#TB/'3T_.P$4R3L[AY8GZWWZ50??!-3]]JQ`@BB;PX*,5L-A_:I(TIALLN=V?KPE63I3Z#68#WDT#*0 +M""I&=IDJE4$?6:_-4$-UWUDY +M*LR^RI'^7TO'-RPH'381J9M:5V>Z9<8O,$<U!QB!YP79`\>/!3-*Q(*#Z09/T@DE/A&J@HD#Z26L< +MOI9`2@,:;2Y+2P6<1@FE7QM7:*,N'"&"P:9@Y8N_>Y[!6`,1X6X5Z>`?TE3R +MY1ZJN(Y7N3UKJF)57>OWMAGD^E4O_?+VRJ+/(,4H!@;)1&PSZRR(6S4(/UPV +M;NN+-;=)77]FW +M85FS>;!F.S)_5")LW'2CW'RZ+IT="*+5:Z.N.'/D1=]'H;B2'AN<37AXKL+T*Z_9KOR7,/I=-+1_+?NCBO&6NVI^-ITR6QVBZC:97@K&2^6_JV +MF(2A@,"Q3<7%_SXJ]:P2%4H0:7CG#')";RDM,^?+9U3#21D':*7=*RJD5"M# +MDON*3<,;#HE^;A9%@<$+2BA7Q_=E_-IH9B+CM%)'22X<(N=-F[]F?L[WOYX^ +MO?%_!^NE$>+PX_@TQ)T?7#W1=_=&I%:&,*DV$-(EQ.[TY7,RU-I&A+".'68<*R6U[G4 +M:5"4/:5=4B@_RNQWM>EV[4%*:3QRUOC+JW@I=MUU#N,:Q'I/Q/FNY@-'+Q_8 +MR6*,8YE^C@U[.O5SL)H='FT^/@HDZ,USGWLF+\^GYGM-#M&W)Y/:@;7M)W/) +M\EH6.PR'"TEJ\TE>8J,\T6"*(0L`QD/,0Q@8XX1YB!HX""!C0XCK0TJ\ON9Y +M\5(R-SU;YR3\Q]Y$JLKBM(_QAL[!@JXPGA2V[E=JERN_#Q'E;N+I]?/:]@6% +MAA1K*L;7+:TJ/M^##4LS[3&8#C4S\$V'J/!ZMGJLQO%\LE/<^6:M2?+JHHA/ +M?6UBQM&TG,"'$F`@EJ)MH;$_K-Y9]34,[\_V#^#G9M7H$N;ZVK=M6JKM3YJO +M!K?P@3RYE3#I+LIJ?3:K9]?8+;UL&UG%32(SZRQ'VE7_&3LJO +M]_Q^4\@4UA'UVW>L;TP*ZNKJR\KZC3+J1_7%PT^@K>'[+8F1;+%/4TVS'*LPR@H4,,L,PQCU0 +M/[63`H)YB@X!.SR@X!/3S+F=\.DWUABBNIU7.WE`4%W[QV(N_'T>2R*0?+4Q +M7AB5@(3UN?\ND$VJ3-H[MZS.LJ_^_[P#2N+JU[UI>>.N%5@A&1?782V0H>K\ +M[?:VO.OZS7J>I.KO+/30Z83I#NT5"=,!G2T+(`J`&(Q`!`1\!Z3!,8)CB/GP +M>ERR"9^?CGUN?*E\M#JG.R/YK_^4Y6WWV[5I+[QQF6NE&L07E;V/:A-($MF3 +M9[U)?V,DI+">K(3JDLIZB;Z0;YC&2-\$D)54AWP[]5$12!1$8I#OC&3X0=^3UCUL4UC;:C\Y,UE'G^ +MKGAV>S_PO?Q#-AO2[I3XQ__(=FP6?24:T(+8Y8(?"E)E:J*2@E*6=HR<[Z]C +M@]B/I0EK2Q19]?G:7RMI;7WAKMKLMA/OU>)K<>WYZD26[Z5M"]ZLHGC[_'QA +MY7:SZEFD_7S'S/BHNK*)5\?HYVAT>?XGC^1T?'[?17R-3'[O%6R`^3"-A,1B +M<@[LR=,[IQ5(^<"AH0\X$D>>!\^M:)="><^[/J8.=0Z#OL[N-4'2UY7;2)_: +MXWALJV0D`I0N^IUIW;-EI104$;71QVZ.34/"R'/J]-R.!94"2UYVVQ:'*;-,?2HT"5(>+SNAT/%Y_/. +MAT?]W.^?^J1]UZM[%B/44&QH$D8PY^/$C$F!\9WZQ#2$,5$@;!G9:T9"'H39 +MKOQ&0F,`F0B#)GF6XS^?]^^^59,<^4OO!UJ+GN_??DI,1+/0$:84$A`C.(D1 +M])26$[,^I]H^]>UR>;S3FY:.:C<:>8.8YN8G-(C!!('(![D&665K,E#220ON +M20_(`]S,Q/<`Z.X=CHX6P?%YX#OPLAJZ;.JM\?K*C3FU3W90Z58.0*7O4S*Z +M155T:O9/+-$/7D:GH6,.,,=]\)BAB/$Q0$V)H`03H8Q,"$(3,W>!)44#WMY\ +MPS%\^N]-FR'8?,_6?XV?Q9];Y!YOK<>LX$LX,YI#3_JX_^6)E.0AADV+C"-QT$ +M%OWF[P_3;0AL^+S. +M=[:MM[;<\+(K+6K*+53L[0$DDF"TP)`-@!B1233`1DS(LTG!14X(:=(L:SD( +M?@UOHG!'#1X":+-3?:_.8/5R>NIH3FM`CZB0R)--34;-"M#8X'!P;VV:R*A>@297S%1F!T4'F^"[C#R7W67;^\U\' +M^[_&=_]I^A_Y_V]G\WYW,SL^'@^=X;_VY:*BAKEEV03E0E2G3.#4C"$0E>0, +M30/,:/;UH-49*'B6CQ2E4F20;0]DL[:VW>VK1R6_?W-S[#_/K?@^1G?1T/MS +M0S_QO4S]@RJK+GZ)G,UK-3,BS@EJRM*'882TFTE(@R`[,A,%10AT/2FJI"F?9,_R_V!^Z-#SNU;^#[K*^)]E(N7B_X\"\7AKI +M>82&+PD-:S**:$.T*I8A3M&[;"(UCBA$AMQX`-%K+87$T/4R=]RCY-9A8W-( +MV^C..RYZNN43Z_P9HFJ+V?9B/@.SCG)X\.08E!R62-2,+,%`'GS_*R<]J(99 +M5*A0+D(SQ9AXU/5]5/6/'W_F?+_*_TN?]OKD/Q>E9SXWKBYL'9@O(/UG[ +MWJZS:-JYH.%LR6[0K;F>]M"4>.@]H?'X]:-9B&EO'K0&#!-`'Q%/#!P:VQ;: +MU;!%NVXY;A;A`M'@J%U;]^^7;PK8@5ZZG +M"\$"XBXAQKS`D$$Y6IZ+9L$(`BI4\H>5HI/+W';YO;_5GZWU]SXGW3IM6BV. +MA+X7,+JEAM>S%,+T#>J\ZJ(6`&"(K)#8DET*5D*EJHN@)@S%6'@LB<=Q-CV< +M9O[_\C?^M_@]A_DD(;W^'EX/3+=NWAJZ:LEE#52R+F9JHB!D!F(1@,51DF89 +ML*4$"@6`YE.:"0H0,O7,O7];OGP^Q8AN]3\DG.665-)DER23*"":#"&F=W:6 +M9IG=,.S$%E)MQ'@B:@RUC@!P'4AA4+A/#.@PY,3.+'!G,A`X:)Z.W1_:R?6^ +M/A^B.\.YAZ6&S245550/%G+'Q&.O$\XYQ)XEU?'UB!H#Q892FQ!*HA:#25(9 +M994J;^4XS)JIQYZ.[I/-JU>;L>F&3\;\3?7YKKQ/+U![MXNW++%PMW&>Y`0D +M)!<&=!:@SS41IV+0#L`+%).I(,0FD>P2LLV.>71:6I^AJB_![$F:+J]7:CDC +MD(H1R00.!([C.,))),&Y&J:!W`[H##+%<-UE,IC[EFM0$VI+"P:DPIG1@^T^ +MJ\=R.WL7$;"'!Y%$.I"*1VDGA_`?SFLUFSPKM3T-FD*@H;(4RA(;,#9 +M84BR%2,8I#9BJ39V:H*ZLX=DV=7PML>]_*YO1[1MF_A-S?Q*)B"K,8.+02B& +M+`&&*2HPE28I!I#%PQ5%](ZVBX7T3W#7WT^O^G^57L:].E*HY]O/ESNWFC'GS(RH<1H38!0$U`:8$I@FD<&=F+A5A,@8K1,AV+1%0AP:`Z%,#S +M7Y^ILH2HZB]QP^'\CR^]DEEDRS#K*G>>>=W=)IB8.`L,+P%FS,%X)$02/!R$ +MWE,PDTS2J9H;%81BG6OS=[?HW_.ZVK_6_\^O^5N^'=N]E];=WGV%>O":[2CR +M%>[=N)VAVE4O:">50F![4.-0:UA2NA[2(\C)'E[=9VGSK+#R'D\??]#P]_A] +M<0JB;8[=1FW!2;<@]5H#;(BC(;9%),=)CVZ`6>[MTNDZQ:*-%\0ZV3!?KOL' +MA[511Q6)&D,W1N#<;@I-U!1&W`=R153,4)B,SMC)3"D[-V9MUV'I]C[;[GN[ +M>GU_#AY'1FM:RCIZ;,/7Z8]>RI.D=`TA$"=*!0$2'3`DI3EC"=(=,Y4A@69E +M#;-S*80X(0ROV,]T@I0%F>8A\4^/['C\?UWQOOA\TX3J^=[GFR\<1XR]JS/' +MX\#Q^,\9XPU/V?C1R#QK3*2%B2S(:IJ2A)0"PU!JRF@\/9[>YMG5V?0*.J=4 +M39LU):+$9U06*;+5JD+2'50*!"&R0LBQHJ`5#9#9.(VN'A-.K5Y/KNYZ_Q#B +M_2?*]ST]I],XG&X''3@8\`<4XV;,30IQ6XXG&<4I]_,B!T''#%X\L +MG8-%#, +M:@?M$*-XN\"MX5O-V_?1ORW-JC[>'CO?28:=GOTWRNGVCZ6'T/5_#'R#L]CU?-/0:=QXG=F9NL@S=E@1 +MNS*#!;=@;A"J0P'=A@.)MW;C=J/B;MQN\7Z'T;SD-LW-L]_[C-@))YLF/+A$ +M*IREZ2D8B9A)(&I9AY`PD>:ERQ.99''2<9V!SN9AT'/P5R-\S9I9M2_$2)F% +MK(&1?4HI94AB6M(]\FDFA`F8UF.Q`B.!(PL0)P#=..L`X-$H::99XXTPE*3% +MZ_1J4G7U*L'=>UP8.N<%JBIBJ:A4.J'4/%"8#D)L@,I@I`Y#J=1J$*`2H"BA +MWH>!0034$RG)YY\M&KAK82(B%$6[DD,PW1%!NC]%%$=QV=D9G9J.S69V)V02G +ML&8)V`'7&0.)%I`-B7T6M*L+IOIT\^[W<,*VC:-J;2S:-H-DE#0GA$I\,F$# +M@>&$PDJE?CU[.SQ:K_3W^K\7)9[^SLFRK(6=NFI% +M44,I,D!@9-"LA1!9,F%,A02DPE\04AS&(.>S6/,\3WYZ.'?]C^5ZNF/>ZNH[ +MO27P1=YV=C2=G9F8TT=@/7AB!@!V9@&(TP10GL#[$=CAWSE[!EHVY>?WN_M\ +MW[?HHI34SO0]`4!0[NT[!0AJ&9D@*&`2!J&)T,)4.BB>=(WM +MC"074X>#'P1UU%%%?C:-1D<84FU`B#9`[5:VP$@;8)R"MI''?@)G:33:27@E +M,V*PF':/:[7F'5-_?V+$S[CS\.!Y_B5QQN/"XV&5)Q7A. +MR'B)PCC:8#H1JD8B,P324)QJ@Z*'C<>.LM;?Z'K'9[_/HT:+F*7:I#$PPHQM +M:J7"JA6%J,4(=63B/7!Z\]$;"I=B4]<&69@F`QG)TP5S2KK2R"LY2)6MK(?5 +M_`^%>EEM)I`DM(BE4JU!@&\[)#?&R'!**!6(7>"1B<8K`)DS2!+*[I,X26I2 +M5\`1YD2/U+>\<9=TWS;XLP-#H=`:`T(H"30P*40E%TFBIT2!@FNC,M5`8!9A +MG98Y=F7EA@THPCC2+I<-N]-BFVR;S_!W35*2B_1?TPI*54D.U"(XWB?$63B> +M*;,4P79(85`&(9#5!4BM!V(#4U.R9W03U4E)=IH[L_8KV+$5?%&8B!M#;Z^W +M&-N&+B-#M!:3:!6V*`(0D@SW42(V=KHDT1BED5V]!Y9I;LO%K<&_RX<.'-BS +M7;A=OJO-Z#ROC\KY4P"E\H^2!\MJ!Q/+)080F+,)L"O+EF$'EC3E'E\KY#T= +MN9XO%\O^/EC[IEUY"6/3FU-6,9HV&2`C9@2",8C3,($(-4&@N8'$>7L[7QO@ +M_!,WT,PS.JKF%06/H5*51(;,$8L1`L0ALDV4A20J.=0&;5JA0YT[66YGT8_> +M>UOF]OX8"WQ,;8VCB@ABLK9B'6E!U%UFL`-*Z)"=1T]4#MO"?O]S-KZNOB>FJFI%105"35`5#,Z!U0,B3*JIA%("`LG`JAP91][FYRW+N]PJ&R/W?N7?ZURY[OO79['RH._;M-M-=^6$;B(W.Z('=F#@!NS!,$HW5& +M29FW6C=`6XV?)WWHST7HS@=]&7.0YR'?W?#^IWO1M'+M7,=TLU6K>\D0$BV[ +MN6RVG3.>.D]KQZT&*Y!H#4^.1E/'!E11@!;3""TK:<=EC+@0>FYM4[NWL<(D +M19(H\.31EHPW&49CB[LQ<4H=PKN1R-VL!V2$FD2"0C"/$^.52CUL9R +M[\K\,_6V?8_A>7O;V"S9JWH6L].DJ.FDTR:4C!RHI-(&ED$!=A"4,"@AI0I) +M41%)IFEJJB+F<>>FDK/O>KZ?XO9YSW._.PW[]V[:;C=6Z"MSNB$-UNLD)"W8 +M@Z&D<2C<5N*=V;MV[N+=N[[W#O\_VWU?>UM8GIN[\**A5((D544,E0P]#IFH +M3"$:"!V8H#("S$<4Y60YPUF$$5'(Y&XWW:M^4XNL;'6S38,2DCEDDP2X1Y@4 +MT$TR$,3`),PTJE`G`:2DWA54[^&_/: +MM6IRW&_VN'M7O9GO\MG+T_8^GS\F_LH[#KZNO'*,&"NO,#$ZX**`E.N,D<%R +M7J'KDEZ]=.!U7P&CKT;5O9ZZ-$]/U]?P]8O2<1=DT[UYDB<=VG@B<0F2)F%) +MQAD*WYB&"4<;(,`B.)7;QCB4+65+TE_4LC\'A]SI7C(\=C1B'B,Z#Q$0T2<0 +M:#,R3J"%>P"D*0[$J@["*@[-=G1I"KZ)?1QUTFHTXZ#&[>U2K4 +M5+X5)0*"DPD610+`7O04142I=ED*+E8E#A=J] +M%WM%5O*&\19L4J@:0W4FV+,B1P3LW80&62XD1HD'=/&\CH)&DP/>O]G?J]?3 +M.#M12J5WE4I(T$ +MO+9Q=_:DX)!0;HJ<7/B=Z7SJ$J!S$4I@1R`.8%`IEX*;$:45@PQ1HVL]EAM%ITE+MC)'$*:-LA(I! +M&$8J[@\<5:Q'A>0>&O'N'F:NJ2;UV]J6DIQ5^J9(M..,C:.*-1NXY&$8Q2;5VSDY#`4+0F +MU`VP$!V"2C:VA*,MRJ.0P+=VL1W.6V1S3#S2RRJ4E4J3L*44YF.^2#?8VZ34 +M4++0IO"ET--.\WY8;H,WQ&ZV:]K*+A=![A[GCW?H.X][?>7K+MRXL,2XQ27( +MI%"%X"S%"Y%`4H0$)A>(+-P,>IJV^+7PGNGI]WDT7Y#DU<0\1Y3><.#OUAPW +M[*.`.`7#!]B5P%RR0Q8F3,E,X"9Y(3#JZ.IT(U\E*>Q`""`0,ZL/7.EB1?.EPYN+E+N_?[=Z]=)&E=Y +M;LG!X!PF#?OA#A++5)9B2IOA.`-2;\ZRQ0X3A/2[7A[S[>[X^4W>7><9BF+4 +M*Q#:MA:K$ZHZNO#0FO!K2NA"ET]5UR%`0U#&6F-<5!Q:#I$Z=WR^#OZL,W3A +M>Y>]ZHPJ@L799DHEV2#)%4;T>YR=RO/K0:S;ZVX< +M/%A2XTN.*8T&&-+#B=<9+@-'39`/6!J,@ZR$^U,S!:$H92D-0TLE'L!Z +MQ>MAJU)H(GUHD*%]8;9A\>U(&"GK#]F'K7K?:>MF9LQS#CQFPDEB.SAQ=KN; +MG%:M;F6Y;MA;II*6HH=J0$F'8I=V'&&*6!T,%*I!TU%-%-%#VF@$*JLK(JX> +MWR=B68FPSF&4$)*4G@Y,$PD$KIQD!,[H09`P$0+P1VPO`'@[,,.#T.\X%;22 +M7J[F%^0V_*E+$A'(6[DI+,TR221+,FE0$PR3$TP!2;YV0ZAQ#A-#&RM_#,R# +MR<=W#P[W6Y.R8F[C>L+LNWBW-QN1$EV,(WJ`A%D-@A>&+3>FE"]38*B51@'! +MCP8+PZ/#V.]YVOU>3DQ;>9[-ZBFJF#JH2*G14DJL^`[-4[L5)F@TR01L,819 +M"DC)E5`B!9(6)E64&$!`J80@NWK5IK0M;6N'%FB]MHM?B?I5])AW=QM&8>KI +MP<0H0^R"BCJ"Z>AUU9!J;/7^3TFP[AXCU.][7LNG2XUS&6C/&KV-CIS:O'[7'R<$\'!6OO^IISSZAQ +M]=R3(TLV(4AF&8"A,LZC+KV<0-@&0%`0>S,>SD'H[\##9KQZPU.KTLWIU:N] +MO[VO=Q*;IHN8J"PN!BA+)+DLP62)%-BJEF2\4QO+U11>]ZKJ8%SBUE^V>CV^ +MO?%QV\<>O2I4O30,<;V$)/.)"S")%DNQ:8%03:HC%+MS%P/1-M];GU\_N?=O +MI?)[?+]N.GEZ3@/!EGEV3,SS0SI,Z0I4S'IRST^]/5R\WAZ?2WC#6G5O,;I,1;-K0HA=NEF%D$A9DB!YU4I* +M%A<,871V+6O>[YV/%K^&?/_'[^G/+`PF$<4*(F-1),80Q0$`PM03%DL%("D2 +M8CAMEDW*J8XY<"Y2]]'9[7E^Y]S@WNX]SSAY_E<3E%RM-N\/3Y>I8-+1TC2$C11I#LD-I)+IM2FE>HLE3`(NDFD +MDHI.ANDH3!:VZW-O2,CM7<[?O=WE\L\E^SK;INO4561:]H. +M--.K5*SU1-0B:5`U*$4U)$FG502U.,(&@F$R06W1;M,ZP-KW,2(/6850&20<6RY'+9OX% +MW\.[._O*39R]/(9.UYOKU&GO;.S/+.\Z<<@E.)A,$Z9(81"R'&$9#C+D&)OB +M/?LGB\BX]%=V'9 +MDA)IYT(E,I)+,^7?Y>2[VXRN:1L5_=S6:?-GL9V-LS9&P'LF0NLUFA.Q#80& +M1*`NAH2%$4-"6==]!KW9T;V]T6X^@[AXGA-/3;3=V/7M=VLPW6X#H1W9C0%! +MB[BS=FY=34ZG4-4LX5EGIJLC-3,, +MZI2I)FD9#-(1A'@SL2E#.G'=#50(/!D69Z<.&K!O:I:Y)Y8XT16(E@>.-HU# +MMU@8.W;CJ-2]$CB)L@90VPP;5&F<3)\`21R.\F"(\/L6-B+>NO%92C(FC0B- +M((FZMNI=ILP3%-L(2!2&V!A?!F68B8TG=HV2(V49''H&1HZM:6S[SYE_!EQ9 +MB\KVQ*TJ!22N6(;Y,C!-X1OEP`S,6AR&@88)20)22,5C8BZ]:O>KV+%LM +MW'N$5B)E!X*P,Q8$ZO8]CLV"FAU(RQ;'LUFK3V9KQ^38;KQ^2.'!>[W_-\KI +MW[F.Z,N7#07`T--:**)*A-"+`$#&J4"F1DO12E!L-F:#`QNZ+%%]C1K5L^!B +M.38WEZ_ON]Z/GO/ZG:S;FYL[ES*9+H[O=+MVZ@97+KH,'QR0ODO+(4LIY81A +MU&&8$4>5"9U=:RPKCJU;M]-]DW;TDLFL9IL>:AZTY.MBB`XZH;D\GE$W)Y1` +M3R6!*Y%;7I=3KWJY=(BS:%(6;1-*TS5G9PD4Q +M!5H,X;))3?(4,!NM^8#(4#2&+OG$2J`SDC8732P@^&3"_%-Q=[W$]<.D:)HM +MHH0:+,:)*R'3(9#B'3"$O2GM)TDW5F=/KGAZ?:T'PZ6[BR9-6HJ:J-Q$1%&X +M[$97K0:`"591IDS1K*@<1VUF/L2AH#XL?%@,#;09S#=""NTBYKJ-Z:V"MPQ& +M]O6]0L11#Q(2NMHM$D$:9$8&ZD4!@*!NDEV$$#=9NL*8D-TW1&;NDOEUST=> +MX;2FV[4V6SM(J6VD&*;0&T)3(5`#902;(@A6U0L-FIM*;4KK:LY]&A$M[M9. +MQU/6Z??\GP>AEWZ>79M6K]J^)%M[5M-2BV-;9.G":8A%!A-40+,*"=29I$>I +M1J.!S-1J-<=8-A;'?-3NYI8S(5Y(FBC=AVC0FC`KI(83,[9R3HDU#"[0S$`P +M=GD)C?/`<)WQB/ +M`E"`T30,!P(,G@F:#.[RIB#30K.#LE-=N2%R@GVJ?7W\9TM)%P\?2'0=2'5& +MR-0Z'J"&1V0E)#U&8N2P@TDYI#FD8:XA>/O^Z]YV>3O[&S@X2XKUV%X=%UY& +MEEK6H-6\B"MY$AO@LUOV!L##AT7ICM?-K +MJ0()SBPWRK"C?/`4%_S-2FE3$LSN[*4F@F:-3(0VL*-D;5=Q`=&L4-">`LER +M$@=\P*5#(E2$I3`387=R,DCDPMYO&W7.P98R3+>DD16XRK<;G=MQU.D-T&2X +MH4[(6`(02$2DA)6@[OW)'7"OI.]<"#U=>)#C-($-' +MQH!A>N:2E)-%)W*Z"%=W:"1!(M6[<Y#DG.'+6LUNN4ZU02"ZXBJ"CY@FC+S0Z$,)-0Y+`'FD)\V92FLUJ<.OL' +MGZ\O;W>,\7:[FY?$QQQIF`LQIH2&*,2#)Z#%BA$)3),8&*.PF)CA,3`R6!TG +M?6T\AC@NW,Y>2X\^9AF6%+R +M8"$YSSD.4II71%`LO.B6'EG1HV0;-5S/0'EO0>^?H^]N]OHY./T=\IPQ2Z71 +M,=BB\ED278%"2B1$)C)<8L(R&-5+B4R47"_43CJY3=8'OZV;'P][T?4]3V-[ +M?T\<^/&U.)Z1ZG!-4#U.PBH"IE(P,A@)#)%)3(5"9"(U14C,N"IE:THR%4[O +M@^%VL=''HQ,3%QQQG->K72T+K5AL4+:`WIH:`2%UC)&!=A%(D+HI!`NA25+H +MP2]`\VM->LX=?I^GX?:Z.CWO[V;OT]+;-G%CVML@/=K.[7;;%UU=>Z7;HURZ +M"2'=V+KXX!Y925\L'VLC`%+28/EK,*P+B=0NU@NM=%L[5O3O*Z=;COKDS=VXAQJI@>)-`P(;UXYB&+Q>)QH]^"8G((U#9U#'U>M%BCQ0>*.,2L!%$XXS. +MS$43.DDPR8&<&$$-`D2*:$B;DT=GLF'P^/#V/,?<##`<,\7$QF>/4L6ES8D+ +ME502ZL(D"XJ0$A+@6$R$]F%@B51&T:(JI.KK]O\[S?>[GO:V;=TZJ=RBEJ6I +MH#EPUSV#L4YP%+*=%1$#('T^Q[ +M[T3;-AF*N:JD#/1`R`RF2Y5*A41F0Q@*"PR@+UTDR(4,4`23@.YG0AT63,TN +M?K<_1US]__O?7[5KXW/2-$T:)?1!00#0*D$DT(BB`P*ZB2(.SH9!$-62KQ.A +M%@Y%CBWCN8ML_E%KM]HY/T7RS/5YO5SN8#F_.W<):X:SVNYQ']XYEOO]4[-K8M54U,J2@*$U+` +M[)W&*44ZS"@)3G$0)"SQ\9Q>E^/II>3'&-DCTW1 +M*2A*DTJ$U9$H[EWQ2$`6_'(`P4W5OL6MELM!6R.XY#'D%,1[6/3VIINM\'M5 +M_PSSO<9#U=,T[74JM<\M-:69T)O&'M>T.>UEK,B!,CVB$H2!*4>:%I#(!U:+ +M6FF?4+E8S0<@)75;3U/4X>=UBH\&>?!DY=O/(>O#@!F3*`,F#"<" +M*!P6HI(%B!DL6,A$DL'`!E5%&67`=O-[QWN?7Z=[P_;'^MUR>?J4ST\F["BR +MZJ*K)G)&JK3LK36F23)K0!>T>UFM0L)HD-D!@'M&S$P/:G),]I&:1TG`?\B_ +M#?AG?^)NUO&]NM;SO;"7EZ2]Z2E%Q"7&"D$DO54R*`P+F#0*1DJ#N5Q)J]^Q +M=MG>][H'9Y9HIGZQ8W(BU%;MRRC2LTHA,2DDANB(20W;\I&`RI"6\>'`Q-I? +M%G)X(2XTA(*6_N;9M'5ZF_A]+V7O7Y9>;(T1&A$9&-'$XSC1IEE#1$04%*0O8 +M42$.V2VE$3*)U&W34FOP%92S;$^*CZ7USR.O\/L[7?T-G0VGWQ<4,HFI%@D.(03B8AQ4TJ'$CPTG8.QPZ?C?E3Z +M_ZDNSY_NFT]W;V.LVEM3LVA=ED&MJ[&0A=I020#M*)2E@=M[$N;8C069M#Y& +M2>.+36,\SX7F:_K=7R]AZ_JUO>OW.(ZGJ\5;X6Y#F&VC*9S(ZDT,H4F_O`-]V11)-$9`9"XBA$DT#'0,.6"P6$E8;>-D7)ZLG!*?5 +M^ELEGW?Z8K?[\_ZG#!<4%]QMYOX/1[//Q>0UTZYQ=R+PZ]8:Y#7$@L!8)#7$ +M#4&*^:(BD(1\R^;Y.:\&!I-AGF\W=LSY/G7'R6S!/*R]48IY8@A(3R20'ELC@9L;FX- +MP@QBH."A#CA!P2@1<)"RASENG2ON,!Q^AC(3W8&4A)^C//5EF,7M?:O/[LA\'@X.PFE2)=^932\V8'9E,Z9/F$?'D@#@Q10[)3%=Q&0F +M(%!,)G0.$Q,!O%A1R2%.WV.WER_47+!Q,BB>1WGH>>M8<]G/[CT'V_MF?/_4_OOW +M-]?/IY;MWR'>;]YO@S`WVYH#%=VLP8)`MV4TY(&#^/.ZU#O#1OMYM=>_PK>3 +M9%V3WZJF/M38F1(&9F/(PT6K9 +M)B&^Z(AY&N,4)$*U:?L^8N9O]R[Q=?M<>UMP16(GW6>/64 +MD<4@%4RNZAIDD:-U5&Z,7"6`D@FL($TC.[B3<+1+6#64%8DUMZ7XWRN/ZAC_ +M$K<_P_4^SSGYO.SNO]-?`Y_0_2^S[[P:]YB_>:^=&Z%Y)7B\RO.DF9KB$DDP +M23AMQ!9CR4=2T*).H(`S64AQ37SO/SEG`N=WSVOP_R?E_,A?SOZ?TK3\S.K5 +MN9S.IZONKO`6^FBU::S9W!QVM%2;2V&B66`78(Y,"I`J(Q",CG0B9`64BET6 +M0LJH[9NEE[6;=?=6X=KZ'T^]_M\D]SUU6K>A>YF;WOK=IWYS>)\;>P>,K^ZV +M&_@;!A@-?AA0L,`%A3NS&%DWF@<0\]LUK12,)L)/^F<3O)([I[PPG*`!@XF< +MS1Z>;9,S80K*?Y?)8UO+]U$RJ:+E(3(>8J-34IAI2DT,QYI/-#2"9)#H@,L0 +M/$5XLR3KG$#X\)L_#L`$,%E`BR9\'++.GLAN)6FS=Z7TZJH?SOW'X7S?Q=WY +MSZ&A^9\W._7_CZ-;@YU;0S_O?D^)H>=P8/.;"8,`L`Q@#!:08`>"9BZ24A`U +MTRLAY6"?)%Y/+!Y?T?J^Z/5W9]S_&][DY?]O=M7.'YGC^+^)E)20T:)#MCUO +MD9*T<3I%Q<0XPH1N0C*3T2![:VHQ3VX38&;,]NT)D21('MQ1[>&4TDJY,FJ/->7D7W>;F^B\BOE>`<[A7LU:R[O3-Z-%FD!O#F#3?N4DWL +M0JZ`^J,SUO&)79@XJKDY*SC%!R<`Y.0/'9#C(=6"*,`XT4C).L"*?BF%=#25 +MMB+=S30?'OM3BO?&;,H21HTG? +M$1G,@XF%HZ1I^-,Z!U/68=XP^[!V,:9I*W[I17!U1X9;3JN9'Y+:%\/\R_HO +M6V(0SNAT.9G\_Q.=@PX7\3R/6.)L38C2383$R98G0"1B=#RG?+1DAB!WQ7?+ +MDC"&40R.9@1@H/@]3ZC[2E]54!ZE]50DC[_JS/PMFE1(48;;30PGE%%"=?@PM +MU%@L!DIJQ3WL457XVUUGV:DI])L.PU&12:I2OU)R>OT8WI4YZ1=G=X?9LDO: +MWJXXS#_;.O,:18>$*LMKB:##2S,:RLLZ$*3>R;?HYGMT:O[+;^!_$?@?.!@SLME +ME:CC/#<\M9AQXQAYCX7:BS?J7/[1,R^P0"7P3.74$F&AU.\M<_P/=&PX\V%` +MYY56;R<0JMXU;+X)%QH94;'PCA4ZRJ:V2P5]$RQ+`IL3E`LS9L7K'E,KM/E`XYY"\H\IOA +MI^$'X:\D`9.14$2A\,I(_>990,0$H86IP.,>YZCSRJ@E!E"A1M%#GH,P^<]- +M]^NQN\BMKF>GUEI]YOD86)25S9RJK%S]]QZ^\8/S(SZ;%)?18KRVTJ21A4V+ +MJ3/#.64OG;6!D9T3FW,AP\(L/3.FJNF +MQT_&882=#.R$;SM@)JU/XF.+LAP&^<&?5C']/!]`Q]5F/S_G^%;U2"//6FI= +M#TBXF\S%[9UTQCN>U*0A;_R9^71"DS$SD(<(DJ53_YF7O6*VNVWO64NMAL!X +M[:+60#:TH#[7UD>;K'@-RZLKRVA95MR:E^+S+,X$KM=,&=SQXV3'#Q#-MIG7$GW'@F@NLF<8WD&RX/!SK\IJ'WWP.8+S>P9G'0[LLWQ<]GA"YO)2,B@T5E";(XDXC@^W\"ZA4= +M_*FR5:S3UC)*'N@U5%T6]*Y/H#%Z,:I+C`SKBVRJ3$P\)5R4Y`[-Y;&40[&2 +M`Y>18#,NMB6,=V)9:&IN;$BRP!I6&`^=GE\?C/5\1X8=92'B62>PB,1!).YX +M*+,I4D80\]@@HA$D\#3*$9X/!/D8>'U_#ZGK^`G]MFI/PH]O1J*!E8>]MY7< +M^;?2L5JM%M$` +MUIEBVI5O;M'1<5M*DADH\GW+-6Q)65H:EL-+HE=FI?6`Y+OSQ[';Z_/S^][W +MO>3+M^,^K[)PP\3Y)-;Y!&/DZA`5&**+!)/(J)^QK]8DM`\"##V5#V3OD\IY +M?9]XXS9IBCHB/]AFKP>(]T-C#(>-V=_#^R6#U0QGO,XY7L:NK\>A2[;]5]LY +MK'%L-3RJD,OVP]$N+0/SYS)F6C[+_<;F)F56U)--:PZ34&O-:^WN#>QI,TNH +MW=68'!J:41\,+EQ=GR>3C\?C\6Z3PU7AW=@GL69&54HD\"(BD8$?G8?/B8*$ +MA;,^59#`8_//G:_WOH?0=G#Y_Y7SC]KF%:V!J#N#%!M6^I$,=U-[MJP_ZS)S +M;=M'2=Z(^+3P$_<&ZNP/4&\5F^)F<5]TY9Y\;!*(4T*9*F^O1,OO01REU(M; +MGD$-I4@P?"BC3T*HJ(QDE==T*6GF4_@+[&TL"H_Z9NG"=CD4S?1)Y0QWQ?$:2NUZA0+'[Q +M2WE,5H[QJ-SV#H0KK1I(_!U>5\PC6JA;Z:NONJ@HCNL31S5E.VK//!>S43^^ +MR:G/V=^_ENZ.YXVV48/&K_>GP^B&AKU=?L[:#L]ANR;-9,=E*6^['Q`!3SWS +M*/FJI!`*9OI0L(OF&#-@^<>[)W]R*"%.-(VF@DS6!X'OZ:_W%KHAB:OA969S +M43C,9<4%@/VOPR9?>0.73_BPZJ<*RU'6/5:.F6N`O^-2-5.QYYEKO0*M\U):WF"?[[.^=I&L+ZP)EMG? +MLWAK<7Q7#4M1#$_C^$CLMGO,T%^!SOL]Z3I_4WL._N^-9D-?>U]K`W[?ZQT] +MDN7/(/Y/N3TDN%JU@(>@_F'H+5@?-^L?5UAB'WTS40A]68AOWN9!3(E2-T1` +M1!"I!HN\!%(-D&,\/$&(C^O$&MD/M\4'X3XG_16SOGH`=);1T?75?BY]_:6& +M+FT%^Z7W?9-_TK0D!];^AB(/R$=CHKZG26/T]%JW+P:6,Y;4V!Z9H".;EJ:?'Z((@VO%,U>X;6FAG:!56R'M;Z-1.7$=[KMNMM?QEYO]G +M.23COHYBZ8K$`\0'9#&B?I%>6P.^/OR^;@&6D7/T631$10L+]]'U/O=:#IC! +M?D=&!F&5[MEY(Q-@_4_A,^'9L#'\/9GT#][F4@2E(Q^+B#_N+0>),Y^3&RNR +MTEOQ!36APMM+HG37+@P^']\4WP-Q\M3*\%<:K60_' +MX&92+LOS&'>.-V;AT>LW.$9O,.=#??D*RGB_/JMQLG+2YH[&A,/>+7Y1,[M9\0-6^1R +M=\<18SVQ_.37F&$E#9OEL-/`!-=-9Y@^,BLSX6C4\8*6:F5]6+LNCM*+4O5+ +M-!1;X2L+,S([83MX-/ORULE>KRMN+@'R;*MM*JM2LK,B%H1B,=K-(D".BJJ" +MA`2D2E"*D%D9"(A&)`60(L)!@?+3\:C_%6+*[-!@2?&)#(^/!$9!A^0_^-_+ +M)^0EM+4\/&_6S!O;;[7!WNN!>*/;%10]_#V'\1AW2D5J,2S/.;^=,.1A"W2E/8#J +MU<+M<9^A7F3E:$+HXG7J9#2=3J0LK^'$6[*5[%\W_37+S4\TGP7=4;)Q2G!4 +M[H:@D;6!MZYW)/:/N.CKS'X^3<0OU/H=FT.E(=!X[36&2D71[KW@7KJ!/U,/ +MH%%!+43UF'D/=5]8QF:7PH%;RM<'V#K5RA:>6RZ&MBF"J/QNAT-7CIJN.@+8 +MP=DP8+AH8QF@,[57.7F?R/@6)BSPX?I/TVCX:0^]:H_.0/Y=4444"?EIA9?# +M!0$>(R(;J?H[?SS5'0VKOH-CZ$=;4H^*? +M"[MQL#Y9)--Y>*2_R6J21P'OI\#!W_AUJ;7-<5<'2A +M'99R]BXQ^PX;JA;M@*[+''S>!!B('((BA"E*-OZ4`/"X>AI(>M@8]3^9B(3[-?IA(ILD?>:: +MBTU0QTOE3ACA<3-X]WG,T5@84>:!41KR]1H:A"[/B65Y]) +MYA?BS'ZZ!*JD_6R!@CRB#]=GZ_64C/QHJE_SIUX,\%&K']I^PPT'V1)?"QHS +M#6\-%HC11X$-"RLRD7S?.M(?;XF)Q?`@J0L[?4H)>P4FM]7.)WW$*03=!N;& +MH.\SF62KS\5R.\L&6GG1U2KT2?6A-EFIS>HXVO@KWIM+?5&1G;MA.3_ +MKK%.P8PT^S^^"U[O&\.`D@WRQS]Y.Y_3UPXZY"JV1HU+Z;XL/K%_K81C&^KM +M\(-\_\W[Y[A->IF?X*G[C>^P;B(`D\?#86,8L_49PPR4+W<.:RTM!Y"0W;^Z +MKJH?`TSS%NUNX[G$G8@9]G%^K5&4?Y*&PJZ>EQ-9.:JIZ).3QYJ1\^6+2BI6 +MR8A1O)[5D`J)QBK":D8BB&;;H497&3G-9!2MVQFLA<:ZRD9Z/#[9/F.NUAI= +M89JD73,B4>S6E>H%***JG9%]R,!&9-J,=6Y'-`N4G,9P;GNT,5EE!H9$\6=! +M@8OHY^,+^4U1NE#\H*D)$_*JJ_)S*OU__5FF)R[;$3;2&CVW.UE97,#'JXX0 +M:D!6!PV9,;SR]F,&1WFK[,5,Q!C*.JEX1\BQ-W%K2XV5%2^+"]UE\5?Q@.1R +M7AMH?+G?LX#[#Z'RTG\Y0?6>!L?/1S:AJVAK[W^Q_W8&8:AU#:1JD;&=U6=C +M]^8.L[WM?U=@^VZVWMVF9?[([7+#0RR&(-.A'PY/B1LUK?C'+O]+\MS;UC$\ +MC"P9J'55NY$"%/R:-]XIA6)N+#[E\H9VKW/6S,YXQ_YC29"^>*,X:5N1)R?H.=D99V8:*BQ +M&1X$BSEJSC08#0^O&/7UFON42L(?^ESRY6[E)<; +MQ`\22F?CL?53^ZCZ@4VF8EL-DG.+=:F[8A1FIMB?=9J:CJ948&DL5H:."K'9 +MA?"TKWG8@*98\D%\HV?6ZT@%=RLFC/,<5;F9+7.G:CU"KM6>7+(+6.+J--FN +M@:'6[%W`7TT'LV>XUX!XXM9>2Z8I\^"&R5MG;H#^S*"E/Y_\S]9\0V3$`?&C +M]A\M-F@P1TWGD<$]:/RZB*G_LP,@_-_8I^QUAL_5;#7[+#_/VPPX1NCM;^O. +M./FQFA`\C#(/L[G<'I1^WV>P.U?--D5VQYJ!.G_:CNPOP9QHQ?Z!O[+S<%@W +MSR_\K>C>BD21,8<73+]&G9[W>>H+OXPP6'5H,!XQ.TEVW68%@LB9N.`*G'/7 +M',''2,O[HH]LOF3>YUE+>,4SG$!C!M@`J3*TP>F,WZU@5HT2UX#`7+OD%%1S +MGM&G3OJP4F[?#(MN]=GU#"V37 +M>@Y^KD/)A\V6ZC/;7N3@5FZY+/UQ]9M$D1>Z!/`HACQH),ZXT.GQE?`%M&)6*Q +MGB[K)O(/[7^B/1+>'\ORT(FI(X15F$)FJ&7ETPM:O`3(F[C7',=(OA4TU7O5 +M3A9E46C7^0UM%K\P+^V>[!MG*II`;MC^28+)M&_[LU[G+C);'%*-/N-?48%\ +MZ@+$,[T^PNE]K"^G#]27F;OHO1,>,#X6=XV5GS7^U.4M)HQ1A1E8N_M-F'?: +M'#`FF.DO`4:@"&U-96>9`BO^NAJ,^UV;"0Z]_#;K;N4@+SXQ!H"CB4&."_K( +MP4_;0.?W@8T_J8<5*#P2?N>N\A:UW$B/%HGX']HQZ^:8@!I'^8_"U:$A^NK?^FH3;_B$@',-)T7HUOJ +MR'OHLBT-NOL?QBZ* +M2\K*O]D?*2NH\EG+J_VO\,8N>SJMIQ7ZQ$L<*#W,E<<,:_]N?CCY`4SU@;]AZN!@#8 +MST"]\>`6B[#B1_&GND-DZEK[G?FIUOHH_,Y,P1#8>@4RKE7^RD*VPF^"(D^7 +MS2C(K#ZN7:X'D-!I@=ZVG/"X`6:K$^!M*,Z<2-9TJW#@'SA)Y\E;:U1HF`H^?J!4]X'N5?YPS@2Z:\&47!)R +M;`O'Q@BOUO"VV@%U]3LW$3PRK5K^\$!2$FO]U6QO#7#+X^\\:DN*R=\^0SF^K]!&)CR* +MJ9:0"%H8S"ES>QI*V.L'8K%<$@!(K^5?,CO_/@KJT1I7T/C/9]!5N98:,>O@&8L,K$% +MT;,6P14,DMM-#&!/YZ$^2SB?):D2?C$J'SS%A/YWLT?U7^'>H'VQA?H7R*.I +M5DD'O6?PB-NU@E&",KSPR)J,8>ZFO-D^*V]0@IA!R#L: +M=/2Q)OU,.<=Q)[3ES\%G\I00Y<'`O14"#2IKA1IPWLK^:2_O>KJ6,ZQPZN;A +M>\8L[8X[M]@>WDR5X-;MG74S_3FY\94&,;)R5S2Y%%1^[M;@6ERKAVJ3-=S8$MJDF!!N79% +MY;)^J\4OQ^_TU:TFFG/?6/UOU&-QE^-^0]K73^@ACQ&4S +M;U5T\D`Y(\(I4^??LG"[V(?O!:,]?=&@]^MI!- +M<5;CW_8;$X"`@!J#?W5P\N<'&N\PA?-FK+S6WWQ/0FOUL_%]RWOF9KC?39=C +M\4[VEL)C#P.9DEP,'?'UNI>.@6S=],^GF954%[U-%P]YE,KRS`Z;6F$DP+'[ +M]:]'DT?%&JG2:9#99+;O_JOMM9TN9WI\"G432$RQ^',Q+3LF`YR_]]J5#*M* +MCYIOXMDEZRX=.+ENC30F-'OI%BZV6G3(S`$F8BAH>AU6XLDD;;SA%V<&XYXJ +MG[CX\V,FM5N@#'J_W?2&D,.5/1&$W47ENY8^\#DU* +MW^7!6WE=H9KI;VRU>&TT,O0'"[>SQ*C[;T?H9+A9'L5@(]857IY"E +ME!+ZZ[L6P<+G%,F'R:]@=X=7I-Q*&1T^W(F';ZNA)A@+FY&A"Z8G:J6)MZER +M>6667-Y[#9#7=,[BE`:],6]^APSV;K17V8XQNT*!1$;0M2:-V1?J'Y5"Z;*1 +MW)Z*G)G%85!"-,/VYG`*22+'*W_Z9B-56GBC,*BU?EJG,5/17G,K%D.$I4NL +M'B]:5_BNA%-1SK&I>E_#KI!G(("'^^WZF2V=X!U%4Y/6%N37P%'AI*RA+CU1 +MSI7%F^O/G'233ENB&KG=[@TVDF$_Z=AE8YXHJSY&*?BE\@=TM"5`M_QQ*S97 +M)>O+:FMPE[SR52T'!:";XB\^1L?5W^2MWG\#E3VL#?O*YLQN=*'W.)V"[FPB +M"";-H\>8()>Y)$)4\!S,67%8P[WM5;]]?,5M>LGKBF,&9PR&%^A#!%%+3/<* +M+X0XX>.UL3=\6`HL7P06+OOIQ+K0'IX4W50$>0PV1-4#]6']SJP@G[V#/CM2 +M_JF/S?Q<#;L3N4#A98H\*TQ0_WN^>::P?R>Z)Y.ZXF$F[@":SV/;2B#M0\1G +M^S.$[LW1Z:`"AU#\?V_Y0@8[!/J4SF'YJ7M^KSVJM;_]T,,;`X?&M*6A(*.Z +M8_>S&2SWAL^:N[X\)#`J&8?8-(]G@R22Q&=Z-AF"-T<7$=MUENMN;%QX[3#Q!1X.;X?\CI_.SUND2BB2MH&VOM;Q!4MA$D&>E%S;?+"<+A4_H&H.6Y@L_6VO]T&AH?HE:3M$_QV.I +M7CD&A&FY09.`6:_CI!I&W9G@MC<_X@_HO\AKSYF\W85]A'&'\36-&)U +MN\.;4'`<"%XOX\C27J^^/-*^& +M1C9ZP>S(S57HHXR.W7Y%X4M;F2B/Z^ONZ.%)SOH_#]2UBT8$Q4P1AML^*(`P +M3?1#"T^C&/'OSK3_9Y1VRM>9XS>S_W]D-9C,^R]TPJ +MJ_U]_:'P\0@_77#*89PU,(.M^75TGODAXWKTL6( +M43O0)-!Q.UJ/8P6($A8#P&KUA,"XQ4Z(R8,EYJ^;'P2;#W?,_#V=O(@:OR;8 +MT(8?OA&>J%#)F1IG>Y&&ZF=-TKVG,6]I+X>R?!?I$?F:&&!XP(*%IMMUSSE> +M6:08]B85"[?]'_KU)->WH'(,"!I[[O.X++S$$Z(CA4.!Z!=?;TP'7?3*N%)_O!V-O2RY9OTYD]H(&8+B4.'[>/;$/(WR9XMG8"<,2B77@ +MNIH6E_BZ)7<#LR!6=&<@3?`Q-#H,?J2#E&.IKU=I6QY0600$A(=#!G+P=M.S +M*.77NX!J="T;<:)U._N6(OY@#APKYP."LPX`'?,F`D,Y[#`+W)B5`7779$!"8F=YFP]@5ZL\L" +M6(S/CAF"$Y=[;W_*Y'F^M!*?T>#L>F8COJ'O]G&0CQ^(T%FYF`^7Z8![7%TT +M%F?9`\7G8FM1<<7\/L!PJ6Y=_!=#2WR`5+#WB.TBI:7NC;,B]^L_)L40_-_; +M?\.A?!`%(00K7[*``7(II^+9$2`4A$BE115143,55%1(@%04P`T(20[K]`R! +ML*"?ZD_K-G7_9HGUNP?!BQ40156;A?)],0$@,6Y]!P)_9*LU-SVO,_^ +M(./;XT4O]EGOL_.;@DN4W2G\KL$=9A0X`E-LEVGHNYD`'W +M&/U;K3J21`0'%AU-C%?^\Y[=(YG2&2.`]4U\L;`D\IKY!S%;Q[@T,XY&*9"E +MN)*XGE5]]^2DAW_!P'%F#>9(,CD>,5NFJNQ7=![`4%KOW,/B?4AJM=Q-OBAZ,-*@!: +MK/QWF-@ZG'XXZX@VJ:1$038,#*I<](GB*(R&3`@(RVDRD=6.4>"9AW$JA3P)W6R?X(2+O=A +M@3`N0PJIXEW+$IWLL*B(.)!2_\>+;<"M9/-K+";R6&"QO5_"<#[`N- +M6CO$)`/:[\A"]R@Y3U1Y\M,C,@:M\D55@1$"R1'C:?,^=M@I +M@-TS`N%,RGR-E:=UU>*HE]AYM47(;-^>*CWOJJ2;XSFQ9\"4 +M((-2.U];6QH%(DR:I,`:;1#S]5?3#876*V=OK*,W8,@46MC<;5N'W(1QE/X@ +MXF)KS13VED"LJV1.&QO.6][>K'!X.;-%FH73.AHJZ-SLL*/Z\"KU1P"]7+Q: +MFS8&'F/^UIE(HM;;&(W^$.SER>O^WU=KD7J/$(2MLL*M+^"O,BGWO.H"]5OL +M5$V);;U8'([XHC07/E5[?*\O198X0RQ0[;KCV.Q6G/`EILZU[067?=S($/AS +M)@@#MT9!?3'LU)"UE_]#(W\-5F@1U0H\B+Z^,EV//:=I+SIHA'LSB,N9@>R_ +M.'&/`MQ+(%*R>>FSZ)2!>QLTET0C(BE:U7AH_M9WYXA&&YCP?$V3O@J?#B"]TM,Z'F'"#WVJ>\H3!4FP^$T,Z8W/H@XL +MR&*U42.(G[5)@[5+CM#Y8?OY+E:1G@TE#\2&>8^47]9#-G +M@,/[KE1+D/6]6[1>'"Y-3W0-'GFC\XR8Y%.?(0GK!K7^8T1#A9F*(2O+F/=2 +MNAWHF`'Z&YLJFQ)!?_?SXR5CSH%,I3X#:FZS9&R^34`P>T:!NLL<=`NE^,L! +M)4G[-FR&'O^#9-?7!NGUM4;+0.TX!=AXV!S$.!V:IK$G/P9+RIKRX$4=4>O. +M!GC:KP?.`]*(%;9&!S*\0WZ=M#1J=K1''-FX/)PAV_^Z-&N&B8X/REJL['>L +MV!`=O!V0&5F=*P'P'^YYA>%E.'[U>M`QN^OSP/Z,"5A<3^/'WD)6J81UNW+Y +ML%O?S\W^G#RP3RU=G`&/2`L27L=<]<`Z6G+AN@.!L.]XC9&J6"5"GS&HKRZ/Z.+2)R.D2FO%E +M[_4V!L3>[B@4HWOQHK)>CRS\354Z/@*IX#;KGAY@6<9RS0<_N2=%%8Q/=IUW +MN'2'8_%0!4;"YD.@<`ZRYP`.M.XBX;=YD@R1^.V!MP=]%S/FNZTR75+SRIG2 +MTQ"HJ7.U&F;3I4?:4(R)2O\`I,''>P%ONF5O=E[,IJI\V5#1RQ%[-DQ=5CSL +M^I%^63(O1ZN[Z4>3OU(3\L1/SMOO0?D,T!2^;$^Z.0#4C3P9TAZQ#&&1Y\-6 +M@3D&JZ4VJ9X5]GF\"=!>[[>>RFS@W'`F@`S?4(O,,W/+E0?`>-%>#%,AGO\L +M@"AUJU>GBVE[0@"WDD +MI[K)\Z2-\G88%LUR@AS8M:@IC6'31(SW)*XGKHT%Y%$D!L5'UZR4LSI2ZK?T +M:(E1CQR`(ZUT1KX`4 +M%WG30=OSMB&:S<33<\`=*DQKV;+H0440NM<99Y4OA8.>:FZ$'0/3C9D7AJ<<^;8N' +MX%KS;XA'QQPVS/[<&%`":VX.0H^..E2!$4SM;]QHK`I:YMJ-=OB'>.Y +MMR-TW*(O+Y,6H1D8=WQ#40F-WS\<'.]TR`L[=X;EZ*!.'9X$'0:!"7^?B16. +MXQ.,".%]>$7X8QX/`@M&(">,`W)XTA%8*GF&AL!/':@X&G)^X?X%4<=W:=?!"TNG?&TR#(PH`9X>!X\3OYH^QDQ^4; +ME9,Z=R=R`ZT@XY0WAPX`X$IIL(^+_'D4TRXT\.\V5N"`'?\,ZROLG!EZ,1_@ +M#]GL+8$\S3SE-%^-!:D7NMO-8<(#A:#PXKL#\BR?8)L`*JTGSTR>\,FI.GQ1 +M^8>$OG%D34U8K_M5/`$OFS0_3Y?)7L+^RLJ!KT5T0$\SQ[_HD'#I/&!5]];I +MC]KZ]:;,)0`"L3%VZ.XB$@1A::%Q:$&2:0EG6))&0K[>:/I +M1Q!UJ%^ZT9[A7J.@-NQ(ZUB=^@04'C931XJU$<$>A6^UL[[_GRI*`KO]_Y0_ +M4XR7I,[*7E]KJK_*%D0VVFV-L;8VBA;>D>AWVCO/EZ:S1<9R@E8?]_1[K.Q6 +M!6`;3?(LN#B;/].ET_D@F/^N,\CD[CDY^2A2YM-![A._OKRDS)+S- +M'I^FGGP0A%G>_'[=5)/73K][:X,'0"5-U8[EZJG/:I.\_/MN'SAZ9AS>00D1 +M(DR*[G9VT+@?*`^,!4Y.`S5>`7->J5=J55(>ZG8]N8-:2@\#KZ&>'K-] +MM[W2QEP>!!-3,XF\?FWDIV\#<;F*6'0QO>0=(" +M0ZSIW'^)X?!0?PQ\C@(*EET/SX-GS_?TD&*8E#XZSHH2(+:XTSTMP_MTT.JR +M.K;6Z"HY1``5#L7/PZ3'8]8?/8_,=/3'@"5]A+.*1CV?V;NIW&] +M*[2``8MS0:)O)__$>-^F-`MX%G]=ZC(%V:#/ED1QV/GPJPYT$<(!4!!N8QSF +MPI<*M:)_A_WIG@0TFU^W$?RVU)MF%LFTRP:K):V:0`4SW83`H-:3[&<^R +MN>!"'O_#OO-OA.063TC[^V3F]#QDUHB`$WT?.TO4T-$T)D%OO/)\L^`2_YHA +MVF0)''_)?TT?S%B"G7*)2"(..*V7^01SSEKZF;Z2\(A7??Y^*@97!K6):OL\4=E6)R:I0Z"CWG/M:UEI#\@D'(W^U^E@Z[AM]['T_4`&ZL^U9 +MN^HSR+W7#B[Q^!G.;?]NYX@'&Y7NUT]/%HP2Y,:H)VBL$YM/D0V26U_CM"SY +M[CQ1-J,!M.]O50`KE\>_,XUPO]+$Y'S)!@ZE$1#!^GQNOY`0Z0U!$;B]-7*0 +M`ZN9?%/RA(?W&?Y*1CAF)Y_0D"2(R_@U,AMFO+*LUE_G.9VRHD1`6+[@!*G8 +M-6LTG*'@!IVC`"`/NXH[?SG0`P8W<$WY;=S&4B>JH^NIQ:(@$=A3RFZSU3TR +MCI:N2XEODORF<="1#0)\1UBZ>&/W/)#[FYJO:4(`$&XZ3MV0':I[3>[R29DV +M3'M0D"W*.)P5,N'T9/?\#=)(@OL@(OUL]KS)HJSFFX/P0#\VGP`I^S>!S=Z# +M7?B\SG^`)H=X5!M.;O-MDIPZ>!#&T&'<5N(=(*_D?TB%@B&15G'?4FQW]2IH`!GN3>E +M=:J8DP3OOYW,MNW>+X^`K(/M*DLRJ#>[MHGQ$T:XA!!=4O2V$4!%><'SFR@0 +MXJP\.]1D07GJ5P$(`PN:;=/(74ROQ-P?W,)->)U`0'T[F$!'J2TH<6[G(2+S7F'ZNN7]C=[P\A221X"AWT +MY_U:0[1,-127"0=`"\UOL/##L^DOE[56D-EP82X\LP0&%UOSS_%U\@1JJN:B +M-G20`"TOC4BK\6N:%A/;ZGVQ;L,K]^JE)GP^YKO8S:>]2`%4SLQ,+)>[Q[K) +M\[M)PI`#:^M,S-W``BW+0QW6SC]E]NI@N!P03AD,U'5]I4;&#EK>S_*RE$0= +M75L*\X:O!2+L8.&WX\`.;4D)_SR2^A4,$\11U&!*4W%=Z8,?IUQKY("`QE0] +M+IF!"2Y;/09[,?&J/D7&NB+RUN'#]XS@92:5DV#1@#AP(+S>H3J:@1_*QM%, +M%EWCS@(ZT)W/8OFT]"(`/_TB5;[P!\/--HQ7O/)HDMN0@M!`@8/I;A1)Q\'0 +M7'A?."->7=[3'X*WA6R`#1>D%GCZ+(M10U]R]7!-'(Y/Q0$3E5?W +MM]H`9L-]33<1;SFQG=]Z>,D`#+=7CD5`.FNJ'(UQT"9<78`6GW0J"^G??IC( +M">4J=3.KJ4"$1A1`*!SSS'O>ZHG/R^+;6/Z^_H1@B8.)Z"#!#7*=J@]9@SWC +MY%9(\R"US[ZPVZ;63M)&NA!RA5B2A$8`'XYU002QX>;>>W)L!X$N>:>`_NBL +M.4B1BO.^!ZVW?W78TJ(\1*7( +MF>D012>Y;[XX+_JN6U!"P$XM[QI:F>/26/3+H^I]$DD78`%+DS@M>7":?Z/E +M0-;L60)=::9DLB)>QE\`L6#?33Z&=VNPW[=5)!$&:1Z!)76;M<-S-G2&S5/F +M14_\U?=_[8QB@?`@\S4$6%]GUL_<8)&65,01J(BSG.O""G_.]_LG;;')GP4% +M:J_E`N^#F*++HMMP>:Y;QRBQ[THB"7^M7/`#TW[E +MAM3?&42,-3EY$@`?2.E%7P$)U-#.:#-!R7F(1Z)(GM%.+DNE$`U0DHMLBP5.TUT;J'.II@!D(2A +M94I0T'JM<%"1/.[R9#^)\NZ5JD=*1PX_C$43SA:VF20O[Y!(""^922+\:=HV +M3J<+QUUQZ02+6XJ9R9S(R@)E@9,]NG7)W=]QXJ&2`!FH<`?50]2P.0C?JND? +MU=&188`PI,4DV_'>48+^[*!(!^_YB51V!T6[,-EEM7A(06,^0%+A(] +MJY[8Q1;JF2>\%ZX200V'8E`5O%6*6T,&KGCX&$]Z>.4_."$M2=OZ8B7>ME.@ +M*1(M%BNT>&B4V5E&4RCGOD@`51$HC-+45]:EED,?4(05K5Q:.>!<#,;)22%% +M^]I\$O^2EJ`!EWV47;\5-X*+)H`51)R&7\H'OKOHB"-D2/[1$7N;%:_(1+NQ +M/L9O*FHY"F"^='1D01[^DC<1F?L?1*8%O@W&](MWWW2D/4VBBLY`$,A[D9`N +MR`/QMQOA6A/R?.I!P_F_(!!AH05%,=4FMRB +MYGC#-'0,C?S`()(@OMJ:H;*4XKNW9@(B*AO"*FN8%(LOD=#YZ90@/WU;_RM_ +M8:%-_K)CHLNW2@4GJXN^QX`YZA(064OA.]*F#6A!:T@%KG4\G(0GPB( +M@S];2D30M_45-;R64'B'OA4[3D&O^:%O2]2MH@$N^2].0*$R,@'F*KO3UJE='8:(1)!?:-,0<'9$0 +MT'G?][N@NQZE;4<")2C206+O@4/JA#@*262!=[[5&K2%5 +MWVN59(CLOH:\KX'IG300X-!0@!E\]F3B_.Z2>)#D(\ARG:($`Z4#43J?!"?K +MFF:_J;SB(2VF=O#G]UD>3W4!"VR/5!#V\+\1@G>XAG3Y*%CY)SM\4B'6:G-G +MRW".WDY9_:+`#!4U>\X:YT*-Q;$)",BVC_HT@.K8^>SE*1+C-'C$UN6=`_(R +M`D(TB&LQB5J!$]7S_M83O,B+M>*ZX!%CKU$$2+9\\\7P?N#F^,"'EO?(O=56 +MW![SJ6W-$*N>(G=%QW->Y5HYLB`F#GZA)("EE1VMZE(TI^9('S(@5_S2(6'A +MS]FN#(]#O/'0HC"`BVO=G`0U6OBFW/Z.@JN;:2&B2`$+>"%- +MX)1A\239!5UT@JH@%TQ_2',7-?]HYW:[8?S\]-<<-B$O2.OP@!5,*1 +M;6,@7-FFK&-/E[=K_R/$96($!LL]D]#BMFYU^JZ#&>X'2SO?9T>\3""^\PP! +M8S$RMV\!03.LX.]DO7B802@"VEIMIX@6@1C/[:GS,TC>JM"!8ZX@&SC7GU8A +MN91JAI=)1`IN_Q.B0#7190>6/G$A>/E]\F"T3G7]CH=)K/#AO2H"8''))S?B +MG<)DBF0[)%KLORUMBC@A+F+-8=_I$+$_G(SMJV54@K7/H\J^"'5?*F_T*=^I +M'.]\,5OR(?3=/VW9#(2]'J9*MJ0B!0^(C^>.R9`3S=U!GWM>Y!T\!L%@@%I< +MG[Z[IGWJH@Q)[_UY8B#)45W18%;6Z#.UT5DQ4)0!,01B!+:Y<8]6@#E;'-%# +M$A64Z5*`,PSD0/JM7OY^&F4&0B#RF0S]>0*2Z.VVJ1J0\>MX;^1!]:S:#@JA +MUVSW">?Q^;-?D%@$`]1&+OQ`27&QKIC=&[,"2%R29X2*(DBX^N3Y#5ISL2?( +M:NQ<_UQ2(MJW.VP9J<[-KT?I@"XE)UHE4L,CZ-)VT(>-W%RBIHP1/7F>,?]@ +MF.,)N^5"9%(+^.I`>+H3"1M5_IK`D5!""W?LH(@@5?Z"^NFT_#D`P(BR&F[U +MB`*_V^:!O-C%A#LK93!02&:``K*"T8+9D;74T^./JD8Z$1_7^7O\T:X=!$MI +M]!IU77]E.-K.I,H0-E41\7787$.@ABM#':CU(K[-S#G#1Z07VHO\D*K^L60& +M_FOO^L$UR2D578:+-D06K*AN<.G1RM;&BOTJ0A$$2N[N]?$R*)J/EC9O.D1: +MK9X'5-1=ZI#JGQXZO+<\B+RR=?O9_PYJSV+[/&00#0XY^5C?'4?!I2W46D=$ +MX(MBV*OIZ?YS[[FX=4+2XKC44PQ@B;*%^_:,J&(;*/"F&$81P"K]^$"*$R'` +MNZ-)GC`RBR>0`9SHKOFX.,`)>2Z3`2H@PE+SH@#5):^HB;1:(`1HD7=0IDO= +M'3*8ZKJNB"B[`B=MOV4MYN^NA&75TU$0C-;[+.XPE$$!S6GC,*NCQC](^[+Q +M[C$*I-+>8B((?VA%."V6X6;$P8O#`N(9G(.*N"]G@I[_/^=>5TKZ7=,99KIW +MDHF,^QKSX)ZE_NR1J!W/XT@.WU44%G5IEWA\NW_4Y[VF!.9?)@` +MH/1?W^?@?/=E"(F=';L*D<O7,&Y2%2N.MM_)SWER%]2H@":=@QZSN-*%"*1OCY;ZJ-A7+-:J`B#( +M9U56UH,+TV=ZU%"'ZM$FJSD:0HI5GOK_QX`@R.%94^3^%)+;#Y9.JU"[?0:W +MX7M`""(O=553(ZNYT)+MG>P;(@0%&8!,!@`EXPO]'">>%47\GMYU:^+(!^%! +M]:[I_CI%/P8U=15T0?HVQIC;6P:X=3+\"CI\!\_&Y4L!!UK,#O0/%Q,SIU4_.H@" +M"B1%>=6T4D!P1)@B('T&8,>[-W6G/$"$*VFS00@=%Q-110A5WC(_OC'@,-E' +MVW'NTSLOD_+;:SMI6]Z-Y#544T4-3*X*C[F%'F:_:,?7>WK8]!)N]-F-M9+C +M'BE^OM:;$VFQV6$&6P80@7RT=JJ^)'>3'/L_>=7U;33 +M$PY[K;)#P-WI_,SKB=(@]L3WOIEVT=OU]_L@6*,%T$U9O(K`T`/``-FFZ?EO +M^W[*/LK-NG$N<:._G+1;K_1ROO=BD$`'9-V@]9]C\)A-$V*!>]:#WS^C\B'[TLBW0&38H``"*E\]\EL%DN5PAHV.P4H;]VD0Q- +M[>U.*60`YV^^;MT,/6C@37+I&L;4`LI.3J>)V*VR:";D4$0ZJ_%P1NCX(KRT[&SOUN"RY*SU.,6G[*)B<"! +M3]#\:?1&\U/?!J9\:D;D0`"2R[FR_:9RF:G0]V4E=9WZ^+XD`-+SW5V4"-GZ +M^26[/5SR(`57$Y-OWTXG:>LW8QLXW-+ +M.%5_ZGON1TEP@13&6N''D2*LX[/./W^FEU/B<_7I!`!LF9'&#>3/?0]]GV1O(0@BM&>Y\[S& +M*X$#7I! +M^&G/\%YU;:VU743Y9$0*\WD!\./25O0S8&#Q:I[U';?J9`NG472C;`.@14E +M6Q*T7,^>4\B,B%[9\:J_]XG"D`NG2;9ZR\:?-37LX9&"*]EK\"P:'^G5A,FF +M?L.N[#;HR(I^UFMST;=<]J]H"$VT];C=%J>IH4OSY4C(*B4")8>\&>5H:5TF +M[2S&]DH-`0)(,OZ9&CJLN:Y*4/!CCP(9_MMP`5GFQTB]LX;K]J#'-6_W=+'] +M2DLB+Y[=XQ!`RP8_P\L<-1U\BY]]"0+G$!N(8<%;6V[7^'K[O1(@15VAC5+- +MD6J3(ZZGZ21:.8ZLLX@XJ>$"4"`E7OY\7@EQ6)^>W++?#=L2&S>5XT+$.LZB!"D] +M;U@;WFBWE=;=S[JKXJ>1;6RDD@!2&S[^@K2*%5-![7BW3*X@5,``.[J)VWG)*HB9BVRG-G;Y-]W&6R(=R5QV)VI+$PN;A@OLR-$WKF.;YS +M!7SZ,@/;=Z3<\@%R>-C^(__YTC>7ZKA62"(;X]Q[W[4'EYY%EDU-K@_9/+]? +M7*\-8S"2"$W'R06=`DK.=1.AX@,M64!!>A^N'+*NYT$*529ONZ$!M;M<[F,Q +MF@55S>6K)GUP9^ZJ;^SX-MH>K8+X!";\7=T7-(4]749F]V&1B[&AIT8`BK\B +M6U5PJL="23=Q*V];'9KS;4]+!$7?]_'!-WS?6A6Q:$M9XK468+%E];_H4G-@ +M$B(B&\<+KQ(R%9P7E=2>9JTF!NEA$`2)RFXH@:>L_*Q\Y1P%#KO-2)!$3Y]3 +M?:(N;Q<>F_3>L.7U/!@<*120![:6,(A8P?$Q)-_ZSNT\IXTK8)<+OUD4PB'? +MS&8N@\)C.SNS\VHRFYF;S7LTZ4`!S>-_J`%JDY +M*V6"`$U[K\`7#1W=$&VW>L&WB+>L>_W500TSGI`!HVN>A5G\6U?51VHEDT:4 +M`*'3(NWA\39LR5J;-_@ZS@6R2"'Z]48""6XID;//*:QOC]UDT9O7T50M)@(= +M[9S)`9UY']H9/G[^2QE1GN\SUJ40$LN8.IIR%NO^%TXUKTL=CG!D1`!3YGJ[ +M7RZG!!?AMIK-9:0:YRWPNDC!6VK!,R5S#)';&/5=PC!#10VW:2(1^XOQFL_GZ#I47O]2(B^=3]^N1=WE +M0G!XN%I-WUTWP]).200G7^04_N.FA>N<3;N=Y!?#SH2(O>DTE:[+Q%4O#-OM +MZNZ%A=[G]DI!4XK"`VIO^=K +M2C]S,_^)""$S(Z&;(!ZFF1DT"PL.$OQ>TB)A8."1!Z/W-5MIH]^X:OVWWF>K)+(# +M4XOK)``IF//,:=LY_L-Z-;]NY8^1I^Z^"S7D\@!;09`=."=D_CQ\W#-[W7T* +M00W](0'I12GI6[Z4K.+D/"M0G62?4C(A_/7\'A>2B+S35FEK7"SS<8R]Z/3@ +M\==52`AHK\R&-[K5#S4;>V4+VQ[D9`?RT2M7R0+@,V\N:*2812*JF0&\4/U- +M$/;,9^ERFQRE#%IDXQ=7<,:,$(8]G0`D^Q@6&RDN^(T9_D/5(DD!"*6)-D!] +MA:].>?VHT2L--GG$E/A*I`>=YY$_HB(2HYD#DJ#&GU;>HNJ9Z[L'R`8?QW5B5(#(I1;- +M42Z2=T&;Y;[/Z=)!>;L=ZN`A8!+0YCFW76S<:A`'\6T2VA>T,WRCY`O3NB`N +M-RXYKF^"`K*J\QZ(%+8%S*$4$B9MN?WW$2<"S7+U(`'"E[`@7>L1I'_M_C%, +MS1'U-EM-T&PHJ0,EXN]GIHP604)D`:+$I)9-D9V:T$^A(?BN(L3QYW5;SQP&5Z,%!AX +M5/G+(P0V?RO^_RR+:Z9X2(&P3-<.Z@`J"`A[YV\E+K9C'Q>FXSXD$.3_WNN; +M(`=W[TKTEN3VXK*<,8,56))`3;M`V)%LNGXQH4RS[;`X/Z9R+M)`'TR!!)B5 +M:[[:#WE +M_R(/VHB'/2:7H$0C/KU%S=>3T4GH;%1=\#;)2B6"G.-ZB+Q2'U3UOO9CFV3J +MR:M(!6]N"';6NG8?.UY'"X_9^L&\=Y*!"BS8!2\[F6QY$=ZXMDVSK]=C4O2@ +M]IA`;+./5R1#P!MVZWG^[E56]Z&_3/RD@#9\ZX!-W.M4X]4>;%2B`$UMO:(! +M.X>5_(BF7OUPTEML7\Q$Y;. +M:H3X97Z[18:,ED +M/.E`L;HG[[-H`DDZY]*6WS[%>-B:_:!)!10[`(0!RVY"AQ,IH?7J6?LS]+0= +MF16"`H'/>$-$Y;59P:U)2=+,)T8`^X%XDM'J:%5\$#P(7X8>2RG7Z2$#\)L."&X@VC0#:V.(B2O?\OW/>E+[=/3Z\;E +M;XNX8.+_4TB&;5;(%9J^\0#B/HU$PFRJ$$+SYRL#D*L"$HOT[;4[:9_/8-L$ +M1`0\O>?7Z2\.K$!O,]MY3-,Y["8/K(:+N*8/-J,@("S`#__=[FT]/[*#9^F) +MSB01,'F("F[/_6Y8N5JYP^!L\>10I_.SEXM;#._)`1,B\1#M0;MJXOC(Z_AC +ME;84K@EM\"E@!%KM-ZP`P$TZUM:3^@%:CODTE_RW'W_'[[W +M+S4A;4DW`K*:1#L^S[=F6_4""*7026@EJQ5W^\9]W"K%/;R7#B1\?*G@$8!! +M08,;?/G$Q?9XB07:JD@`5,2`5OILA#>>N3OAKY.M4.5U?:C(1;WVY1N(!Q'5 +MKOBEQU8MIM%(,0@J:2Z:6"$GQ*3N-&Q`+5G-"0S#L[KM2B('J":GB(M!Y +MHYYA3_6,9A-UPT4:FRG)&Z2P0JUR.`'ZSD_MNAX]OWEQ`!PLU-?V=(#Q^OV? +M"JUD"8M_8[.5#Q:FV60[B% +MFW-ZSIB,%\F*`(B\N>U(R7LG>K&.:L0@6\ACR!8M(W6,GE5+U8E(YS&T=."U:>]A=3_2X0*29O!BP!GD"C!X" +MS<[F/OE0@]>!+AT=,1!;]N[_WE[03>+6UZR>4@#Q*7%Z`5S4>R_P\7D5..K] +M/X$A"+7YL/X(?AO0E)&9@F3CUW"G$0*QR((>)A]1CBU_@OC^-GUGN9-PS-(E +MD!0QVS[K&*2W!5_U_B0U^XW$QN7J73E)I2(;SS9/NW-"")HM9RPX/LM5YQK@ +MXR+`OR:L"FJW'>G)D3B&_1T3SUTI*8HE"18?XB8C##U\\Z0$/;++7NH.;DHV +M7B!8_3H)0`U,55-?1`+#3\\Y6*?\M\H24ZGSB2!@S!$6?_%,&GW[Z)E:].7, +MJN:/-Q#8]]]?3R`7L$$<@^FG16^V\CJC"`BGW^XRWV`%F]^?QO^GV^<94C;N +MT\D@#1VEMMH1Y(!FMKW!JN/*3QIIW6LLD!3/9(%VFBU&3:>!#BIM:.!5?\2@ +M65-Y<^\VY$&%WKE2!W-K:X.AD;Z^^1KPM +MV\?4=I*0UC;70WH:&8&I]:@=$/\SF4E>B0+LR9SQ$!VI;N>Y_":W!HAAW%6PH.IU> +M71JR2A`[.M=NN0*-=ME+1KTPL+!;(0LM4J1#J1^1Y5O*/"!_FF%$!?*G#.P) +M$.]^G:W'8J,-O%EFP@C!,_E[ +M&HUX(G>C7[OW[R,S?8=,'QQ<@HJ.R[^FU]B/BH@@R2M9)$`(7DM8>LWHB"6S_>4AP!=_?B):9I99F1TJ$AI^2`'.!5$"DW*F\*VN5V<7?[:FQW5B'OFO1Y +M/YY:4B`RHQ>\B)OI+U,&X&E,!O"H$A#S]_SH0`$$;^E_AM+(K.[)+CHI`6L< +MUAK(#FQF_CTM\0M.9TNP1$&?Z6'N42!/]%;>17JZ[3041T,RD%`WM`>(AL.A +MD_I9[Y5QZ4@)1_4)-[B:!!'8M'>XAP(N>)-*!LA04$NM_Q1`)J[2SJT>L7NF +MT[>GCT@L9J51EX74]_(:`"%_[E)0T>N4O`CUG4ZC1%:80K&U*U<$\B'`Z/TJ +M/[!S?2(B02"CT8Q5W..P%?2.IAYE4,;QDL`,7ZHF/W;<`":^IV7U_YW6H/EE +MYMQ@LF1"5KN$J2K+'YUH9):E2$+'K8\$6U]M9\F5TB!`*MTMHP)"Y[-5B*,A +MYO9TY,@6=\U;*Y3`A^"[\UU5;+_P(NT=$Q)\N[)?6&/`B2R3DSVV^J;W@^YR +MKEE952&@RRRVV1`8E.[7"66,;54J($\?E1;]E(`'K/F.L-Y-5E5*E89O'32H +MMVU\H8M-!6.LVSN`-N%'-?'3+QQK2]],QR(BCO16_A]R`("'A*6FG+GQMN[@ +M\N+3J.*ZC%Y,Y"!M8G7@`M=J\;M9&E_/&A[[/LWC,1#I;I9;G`XA`KVLS/:7 +M+WJ,2-3%!F+4@6`P:ETZ*-&ZL"]2-B0H+3K4H`!)+VO[BDGHZ$5RPUGIHQEF +MY504K%*A$.=J\C)R4-I,^B$_!X.4'MN#[V`3"I:[D)=O^_19RW;8%6E55&3E:\"H4GNR3=("`V%YKL?J_+H +M%+O\X_IU%@]B4!#6E![8_&@A+;Y)B=Y3_+D`+9HNUI(3Y)?WY8H@4)9\3#D?1 +ME0HX7U@GG=GN>YD"%P_W6DC^W0[CPOFE:5H[3-12VMKJFO[EK8`"G=AT[Z2SPX,E9?G4#KR&08@0H5]\U8GT'Q\>UV[ +M*"(9J/D)1WDZL;[+[[FL,#D]$[I8%A^,KX>O2+K``0VKJXS-/!G$U/#XG(0O +M"OJ_&SOB`$`QJDECIERVTTTSVI6G-&2C?GU8O)+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int dm_test_targets(void); int dm_test_versions(void); /* * Test simple dm versions command on device-mapper device. */ int dm_test_versions(void) { int fd; int error; prop_dictionary_t dict_in, dict_out; struct plistref prefp; char *xml; error = 0; error = rump_init(); if (error != 0) err(1, "Rump init failed"); fd = rump_sys_open("/dev/mapper/control", O_RDWR, 0); if (fd == -1) err(1, "Open dm device failed"); dict_in = prop_dictionary_internalize_from_file("dm_version_cmd.plist"); dict_out = prop_dictionary_create(); prop_dictionary_externalize_to_pref(dict_in, &prefp); error = rump_sys_ioctl(fd, NETBSD_DM_IOCTL, &prefp); if (error < 0) err(1, "Dm control ioctl failed"); dict_out = prop_dictionary_internalize(prefp.pref_plist); xml = prop_dictionary_externalize(dict_out); + __USE(xml); rump_sys_close(fd); return error; } /* * Test simple dm targets command on device-mapper device. */ int dm_test_targets(void) { int fd; int error; prop_dictionary_t dict_in, dict_out; struct plistref prefp; char *xml; error = 0; error = rump_init(); if (error != 0) err(1, "Rump init failed"); fd = rump_sys_open("/dev/mapper/control", O_RDWR, 0); if (fd == -1) err(1, "Open dm device failed"); dict_in = prop_dictionary_internalize_from_file("dm_targets_cmd.plist"); dict_out = prop_dictionary_create(); prop_dictionary_externalize_to_pref(dict_in, &prefp); error = rump_sys_ioctl(fd, NETBSD_DM_IOCTL, &prefp); if (error < 0) err(1, "Dm control ioctl failed"); dict_out = prop_dictionary_internalize(prefp.pref_plist); xml = prop_dictionary_externalize(dict_out); + __USE(xml); rump_sys_close(fd); return error; } int main(int argc, char **argv) { int error; error = 0; error = dm_test_versions(); if (error != 0) err(1, "dm_test_versions failed"); error = dm_test_targets(); if (error != 0) err(1, "dm_test_targets failed"); return error; } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/fss/t_fss.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/fss/t_fss.sh (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/fss/t_fss.sh (revision 304003) @@ -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 +} Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/fss/t_fss.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swsensor.sh =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swsensor.sh (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swsensor.sh (revision 304003) @@ -1,398 +1,404 @@ -# $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 | \ sed -e "\;swsensor;,\;/array;p" -e "d" } 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() { grep "not running" powerd.log | wc -l } get_rnd_bits_count() { env RUMPHIJACK=blanket=/dev/random:/dev/urandom \ RUMP_SERVER=unix://t_swsensor_socket \ LD_PRELOAD=/usr/lib/librumphijack.so rndctl -l | \ grep "swsensor-sensor" | \ awk '{print $2}' } check_powerd_event() { event=$(grep "not running" powerd.log | \ sed -e "$1p" -e "d" ) event=${event##*//} script=${event%% *} event=${event#* } device=${event%% *} event=${event#* } state=${event%% *} sensor=${event#* } sensor=${sensor% *} if [ "${script}" != "sensor_indicator" ] ; then echo "Event uses wrong script: ${script}" elif [ "${device}" != "swsensor" ] ; then echo "Event uses wrong device: ${device}" elif [ "${sensor}" != "sensor" ] ; then echo "Event uses wrong sensor: ${sensor}" elif [ "${state}" != "$2" ] ; then echo "Event uses wrong state: ${state}" fi } # Start the rump server, then load the swsensor module with the # requested properties start_rump() { rump_allserver -l rumpvfs -l rumpdev -l rumpdev_sysmon ${RUMP_SERVER} if [ $( get_sensor_info | wc -l ) -ne 0 ] ; then rump.modunload swsensor rump.modload -f $1 swsensor else rump.modload $1 swsensor fi return $? } 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 \ rndctl expr } common_cleanup() { rump.modunload swsensor rump.halt } create_envsys_conf_files() { cat << ENV0 > env0.conf swsensor { refresh-timeout = 2s; } ENV0 cat << ENV1 > env1.conf swsensor { sensor0 { critical-min = $(( $1 - $2 )); } } ENV1 cat << ENV2 > env2.conf swsensor { sensor0 { critical-min = $1; } } ENV2 } # Test body common to all sensors # $1 sensor mode # $2 initial sensor value # $3 initial limit # $4 amount to lower limit # $5 difference from limit to trigger event # $6 sensor flags, for FHAS_ENTROPY and FMONNOTSUPP common_body() { # Start the rump-server process and load the module modload_args="-i mode=$1 -i value=$2 -i limit=$3 ${6:+-i flags=$6}" start_rump "$modload_args" # create configuration files for updates create_envsys_conf_files $3 $4 if [ $? -ne 0 ] ; then atf_skip "Cannot set-up rump environment" fi # start powerd so we can detect sensor events rump.powerd -n -d > powerd.log 2>&1 & if [ -z "$(jobs)" ] ; then skip_events=1 echo "Skipping event sub-tests - powerd did not start" else skip_events=0 expected_event=1 fi # Step 0 - verify that sensor is registered get_sensor_info | grep -q swsensor || atf_fail "0: Device swsensor not registered" # Step 1 - update the refresh-timeout and verify # (use $(( ... )) since the timeout is displayed in hex!) rump.envstat -c env0.conf if [ $(( $( get_sensor_key refresh-timeout ) )) -ne 2 ] ; then atf_fail "1: Could not set refresh-timout to 2s" fi # Step 2 - verify that we can read sensor's value if [ $1 -ne 0 -a $( get_sensor_key cur-value ) -ne $2 ] ; then atf_fail "2: Value not available" fi # Step 3 - verify that changes in sensor value are seen rump.sysctl -w hw.swsensor.cur_value=$(( $2 + 1 )) if [ $( get_sensor_key cur-value ) -ne $(( $2 + 1 )) ] ; then atf_fail "3: Value not updated" fi # Step 4 - if sensor provides hw limit, make sure we can read it if [ $1 -ne 0 ] ; then if [ $( get_sensor_key critical-min ) -ne $3 ] ; then atf_fail "4: Limit not set by device" fi fi # Step 5 - if sensor provides hw limit, make sure it works if [ $1 -ne 0 -a ${skip_events} -eq 0 ] ; then rump.sysctl -w hw.swsensor.cur_value=$(( $3 - $5 )) sleep 5 cnt=$(get_powerd_event_count) if [ ${cnt} -lt ${expected_event} ] ; then atf_fail "5: No event triggered" elif [ ${cnt} -gt ${expected_event} ] ; then atf_fail "5: Multiple events triggered" fi evt=$( check_powerd_event ${cnt} "critical-under") if [ -n "${evt}" ] ; then atf_fail "5: ${evt}" fi expected_event=$(( 1 + ${expected_event} )) fi # Step 6 - verify that we return to normal state if [ $1 -ne 0 -a ${skip_events} -eq 0 ] ; then rump.sysctl -w hw.swsensor.cur_value=$(( $3 + $5 )) sleep 5 cnt=$(get_powerd_event_count) if [ ${cnt} -lt ${expected_event} ] ; then atf_fail "6: No event triggered" elif [ ${cnt} -gt ${expected_event} ] ; then atf_fail "6: Multiple events triggered" fi evt=$( check_powerd_event ${cnt} "normal") if [ -n "${evt}" ] ; then atf_fail "6: ${evt}" fi expected_event=$(( 1 + ${expected_event} )) fi # Step 7 - verify that we can set our own limit # Steps 7 thru 12 are skipped if the sensor cannot be monitored if [ $( expr \( 0$6 / 2048 \) % 2 ) -ne 1 ] ; then rump.envstat -c env1.conf if [ $( get_sensor_key critical-min ) -ne $(( $3 - $4 )) ] ; then atf_fail "7: Limit not set by envstat -c" fi # Step 8 - make sure user-set limit works if [ ${skip_events} -eq 0 ] ; then rump.sysctl -w hw.swsensor.cur_value=$(( $3 - $4 - $5 )) sleep 5 cnt=$(get_powerd_event_count) if [ ${cnt} -lt ${expected_event} ] ; then atf_fail "8: No event triggered" elif [ ${cnt} -gt ${expected_event} ] ; then atf_fail "8: Multiple events triggered" fi evt=$( check_powerd_event ${cnt} "critical-under") if [ -n "${evt}" ] ; then atf_fail "8: ${evt}" fi expected_event=$(( 1 + ${expected_event} )) fi # Step 9 - verify that we return to normal state if [ ${skip_events} -eq 0 ] ; then rump.sysctl -w hw.swsensor.cur_value=$(( $3 - $4 + $5 )) sleep 5 cnt=$(get_powerd_event_count) if [ ${cnt} -lt ${expected_event} ] ; then atf_fail "9: No event triggered" elif [ ${cnt} -gt ${expected_event} ] ; then atf_fail "9: Multiple events triggered" fi evt=$( check_powerd_event ${cnt} "normal") if [ -n "${evt}" ] ; then atf_fail "9: ${evt}" fi expected_event=$(( 1 + ${expected_event} )) fi # Step 10 - reset to defaults rump.envstat -S if [ $1 -eq 0 ] ; then get_sensor_info | grep -q critical-min && atf_fail "10: Failed to clear a limit with envstat -S" else if [ $( get_sensor_key critical-min ) -ne $3 ] ; then atf_fail "10: Limit not reset to initial value" fi fi # Step 11 - see if more events occur if [ ${skip_events} -eq 0 ] ; then rump.envstat -c env0.conf rump.sysctl -w hw.swsensor.cur_value=$(( $3 - $4 - $5 )) sleep 5 cnt=$(get_powerd_event_count) if [ ${cnt} -ge ${expected_event} ] ; then if [ $1 -ne 2 ] ; then atf_fail "11b Event triggered after reset" fi evt=$( check_powerd_event ${cnt} "critical-under") if [ -n "${evt}" ] ; then atf_fail "11a: ${evt}" fi fi fi # Step 12 - make sure we can set new limits once more rump.envstat -c env2.conf if [ $( get_sensor_key critical-min ) -ne $3 ] ; then atf_fail "12a: Limit not reset to same value" fi rump.envstat -c env1.conf if [ $( get_sensor_key critical-min ) -ne $(( $3 - $4 )) ] ; then atf_fail "12b: Limit not reset to new value" fi fi # Step 13 - confirm registration (or lack thereof) with rndctl rnd_bits=$( get_rnd_bits_count ) if [ $( expr \( 0$6 / 8192 \) % 2 ) -eq 1 ] ; then if [ -z "$rnd_bits" ] ; then atf_fail "13a: Not registered with rndctl" fi else if [ -n "$rnd_bits" ] ; then atf_fail "13b: Wrongly registered with rndctl" fi fi # Steps 14 and 15 are only if sensor is providing entropy if [ $( expr \( 0$6 / 8192 \) % 2 ) -ne 1 ] ; then return fi # Step 14 - make sure entropy collected when device is being polled rump.envstat -c env0.conf rump.sysctl -w hw.swsensor.cur_value=$3 sleep 5 rump.sysctl -w hw.swsensor.cur_value=$(( $3 + $4 )) sleep 5 new_rnd_bits=$( get_rnd_bits_count ) if [ $new_rnd_bits -le $rnd_bits ] ; then atf_expect_fail "PR kern/47661" atf_fail "14a: entropy bits did not increase after polling" fi rnd_bits=$new_rnd_bits sleep 5 new_rnd_bits=$( get_rnd_bits_count ) if [ $new_rnd_bits -gt $rnd_bits ] ; then atf_expect_fail "PR kern/47661" atf_fail "14b: entropy bits increased after poll with no value change" fi # Step 15 - make sure entropy collected when device is interrogated # rump.envstat -c env0.conf rump.sysctl -w hw.swsensor.cur_value=$3 get_sensor_key cur-value rnd_bits=$( get_rnd_bits_count ) rump.sysctl -w hw.swsensor.cur_value=$(( $3 + $4 )) get_sensor_key cur-value new_rnd_bits=$( get_rnd_bits_count ) if [ $new_rnd_bits -le $rnd_bits ] ; then atf_expect_fail "PR kern/47661" atf_fail "15a: entropy bits did not increase after interrogation" fi rnd_bits=$new_rnd_bits get_sensor_key cur-value new_rnd_bits=$( get_rnd_bits_count ) if [ $new_rnd_bits -gt $rnd_bits ] ; then atf_expect_fail "PR kern/47661" atf_fail "15b: entropy bits increased after interrogation with no value change" fi } atf_test_case simple_sensor cleanup simple_sensor_head() { common_head "Test a simple sensor" } simple_sensor_body() { common_body 0 50 30 10 1 } simple_sensor_cleanup() { common_cleanup } atf_test_case limit_sensor cleanup limit_sensor_head() { common_head "Test a sensor with internal limit" } limit_sensor_body() { common_body 1 45 25 8 2 } limit_sensor_cleanup() { common_cleanup } atf_test_case alarm_sensor cleanup alarm_sensor_head() { common_head "Test a sensor with internal checking" } alarm_sensor_body() { common_body 2 40 20 6 3 } alarm_sensor_cleanup() { common_cleanup } atf_test_case entropy_polled_sensor cleanup entropy_polled_sensor_head() { common_head "Test a simple sensor that provides entropy" } entropy_polled_sensor_body() { common_body 0 50 30 10 1 8192 } entropy_polled_sensor_cleanup() { common_cleanup } atf_test_case entropy_interrupt_sensor cleanup entropy_interrupt_sensor_head() { common_head "Test a sensor that provides entropy without polling" } entropy_interrupt_sensor_body() { common_body 0 50 30 10 1 10240 } entropy_interrupt_sensor_cleanup() { common_cleanup } atf_init_test_cases() { RUMP_SERVER="unix://t_swsensor_socket" ; export RUMP_SERVER atf_add_test_case simple_sensor atf_add_test_case limit_sensor atf_add_test_case alarm_sensor atf_add_test_case entropy_polled_sensor atf_add_test_case entropy_interrupt_sensor } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swwdog.c =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swwdog.c (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/sysmon/t_swwdog.c (revision 304003) @@ -1,192 +1,193 @@ -/* $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. * * 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 AUTHOR ``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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../h_macros.h" static volatile sig_atomic_t tcount; static void sigcount(int sig) { assert(sig == SIGUSR1); tcount++; } /* * Since we are testing for swwdog's ability to reboot/panic, we need * to fork and monitor the exit status from the parent and report * something sensible back to atf. */ static int testbody(int max) { char wname[WDOG_NAMESIZE]; struct wdog_conf wc; struct wdog_mode wm; pid_t p1, p2; int status; int fd; signal(SIGUSR1, sigcount); switch ((p1 = fork())) { case 0: break; case -1: atf_tc_fail_errno("fork"); break; default: p2 = wait(&status); ATF_REQUIRE_EQ(p1, p2); ATF_REQUIRE_EQ(tcount, max); return status; } rump_init(); fd = rump_sys_open("/dev/watchdog", O_RDWR); if (fd == -1) err(1, "open watchdog"); wc.wc_count = 1; wc.wc_names = wname; if (rump_sys_ioctl(fd, WDOGIOC_GWDOGS, &wc) == -1) err(1, "can't fetch watchdog names"); if (wc.wc_count) { assert(wc.wc_count == 1); strlcpy(wm.wm_name, wc.wc_names, sizeof(wm.wm_name)); wm.wm_mode = WDOG_MODE_ETICKLE; wm.wm_period = 1; if (rump_sys_ioctl(fd, WDOGIOC_SMODE, &wm) == -1) atf_tc_fail_errno("failed to set tickle"); usleep(400000); if (max == 1) rump_sys_ioctl(fd, WDOGIOC_TICKLE); else { wm.wm_mode = WDOG_MODE_DISARMED; rump_sys_ioctl(fd, WDOGIOC_SMODE, &wm); } kill(getppid(), SIGUSR1); sleep(2); printf("staying alive\n"); kill(getppid(), SIGUSR1); _exit(2); } /* fail */ + printf("no watchdog registered!\n"); _exit(1); } ATF_TC(reboot); ATF_TC_HEAD(reboot, tc) { atf_tc_set_md_var(tc, "descr", "check swwdog reboot capability"); } ATF_TC_BODY(reboot, tc) { extern bool rumpns_swwdog_reboot; int status; /* XXX: should use sysctl */ rumpns_swwdog_reboot = true; status = testbody(1); ATF_REQUIRE(WIFEXITED(status)); ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); } ATF_TC(panic); ATF_TC_HEAD(panic, tc) { atf_tc_set_md_var(tc, "descr", "check swwdog panic capability"); } ATF_TC_BODY(panic, tc) { extern bool rumpns_swwdog_reboot; int status; /* XXX: should use sysctl */ rumpns_swwdog_reboot = false; status = testbody(1); ATF_REQUIRE(WIFSIGNALED(status)); ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT); } ATF_TC(disarm); ATF_TC_HEAD(disarm, tc) { atf_tc_set_md_var(tc, "descr", "check swwdog disarm capability"); } ATF_TC_BODY(disarm, tc) { int status; status = testbody(2); ATF_REQUIRE(WIFEXITED(status)); ATF_REQUIRE_EQ(WEXITSTATUS(status), 2); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, panic); ATF_TP_ADD_TC(tp, reboot); ATF_TP_ADD_TC(tp, disarm); return atf_no_error(); } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/usb/t_hid.c =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/usb/t_hid.c (nonexistent) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/usb/t_hid.c (revision 304003) @@ -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 +__RCSID("$NetBSD: t_hid.c,v 1.8 2016/05/05 17:40:26 jakllsch Exp $"); + +#include +#include +#include +#include +#include + +#include + +#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 +#include +#include + +#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(); +} + Property changes on: projects/netbsd-tests-update-12/contrib/netbsd-tests/dev/usb/t_hid.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/fstest_lfs.c =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/fstest_lfs.c (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/fstest_lfs.c (revision 304003) @@ -1,192 +1,190 @@ -/* $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. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Nicolas Joly. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include "h_fsmacros.h" #include "mount_lfs.h" - -sem_t lfs_clearnerloop; struct lfstestargs { struct ufs_args ta_uargs; pthread_t ta_cleanerthread; sem_t ta_cleanerloop; char ta_devpath[MAXPATHLEN]; char ta_imgpath[MAXPATHLEN]; char ta_mntpath[MAXPATHLEN]; char ta_hostpath[MAXPATHLEN]; }; int lfs_fstest_newfs(const atf_tc_t *tc, void **buf, const char *image, off_t size, void *fspriv) { char cmd[1024]; int res; static unsigned int num = 0; struct lfstestargs *args; size /= 512; snprintf(cmd, 1024, "newfs_lfs -D -F -s %"PRId64" ./%s >/dev/null", size, image); res = system(cmd); if (res != 0) return res; res = rump_init(); if (res != 0) return res; args = calloc(1, sizeof(*args)); if (args == NULL) return -1; strcpy(args->ta_hostpath, image); snprintf(args->ta_devpath, MAXPATHLEN, "/dev/device%d.lfs", num); snprintf(args->ta_imgpath, MAXPATHLEN, "%s", image); args->ta_uargs.fspec = args->ta_devpath; sem_init(&args->ta_cleanerloop, 0, 0); res = rump_pub_etfs_register(args->ta_devpath, image, RUMP_ETFS_BLK); if (res != 0) { free(args); return res; } *buf = args; num++; return 0; } int lfs_fstest_delfs(const atf_tc_t *tc, void *buf) { int res; struct lfstestargs *args = buf; res = rump_pub_etfs_remove(args->ta_devpath); if (res != 0) return res; res = unlink(args->ta_imgpath); if (res != 0) return res; pthread_join(args->ta_cleanerthread, NULL); free(args); return 0; } static void * cleaner(void *arg) { char thepath[MAXPATHLEN]; struct lfstestargs *args = arg; const char *the_argv[7]; char buf[64]; /* this inspired by the cleaner code. fixme */ sprintf(thepath, "/dev/r%s", args->ta_devpath+5); rump_pub_etfs_register(thepath, args->ta_hostpath, RUMP_ETFS_CHR); sprintf(buf, "%p", &args->ta_cleanerloop); the_argv[0] = "megamaid"; the_argv[1] = "-D"; /* don't fork() & detach */ the_argv[2] = "-S"; the_argv[3] = buf; the_argv[4] = args->ta_mntpath; the_argv[5] = NULL; /* xxxatf */ optind = 1; opterr = 1; lfs_cleaner_main(5, __UNCONST(the_argv)); return NULL; } int lfs_fstest_mount(const atf_tc_t *tc, void *buf, const char *path, int flags) { struct lfstestargs *args = buf; int res; res = rump_sys_mkdir(path, 0777); if (res == -1) return res; res = rump_sys_mount(MOUNT_LFS, path, flags, &args->ta_uargs, sizeof(args->ta_uargs)); if (res == -1) return res; strcpy(args->ta_mntpath, path); res = pthread_create(&args->ta_cleanerthread, NULL, cleaner, args); if (res) return res; /* wait for cleaner to initialize */ sem_wait(&args->ta_cleanerloop); return 0; } int lfs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags) { int res; res = rump_sys_unmount(path, flags); if (res == -1) { return res; } res = rump_sys_rmdir(path); return res; } Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/h_fsmacros.h =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/h_fsmacros.h (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/common/h_fsmacros.h (revision 304003) @@ -1,337 +1,329 @@ -/* $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. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Nicolas Joly. * * 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. */ #ifndef __H_FSMACROS_H_ #define __H_FSMACROS_H_ #include #include #include #include #include #include "../../h_macros.h" #define FSPROTOS(_fs_) \ int _fs_##_fstest_newfs(const atf_tc_t *, void **, const char *, \ off_t, void *); \ int _fs_##_fstest_delfs(const atf_tc_t *, void *); \ int _fs_##_fstest_mount(const atf_tc_t *, void *, const char *, int); \ int _fs_##_fstest_unmount(const atf_tc_t *, const char *, int); FSPROTOS(ext2fs); FSPROTOS(ffs); FSPROTOS(ffslog); FSPROTOS(lfs); FSPROTOS(msdosfs); FSPROTOS(nfs); FSPROTOS(nfsro); FSPROTOS(p2k_ffs); FSPROTOS(puffs); FSPROTOS(rumpfs); FSPROTOS(sysvbfs); FSPROTOS(tmpfs); FSPROTOS(udf); FSPROTOS(v7fs); FSPROTOS(zfs); #ifndef FSTEST_IMGNAME #define FSTEST_IMGNAME "image.fs" #endif #ifndef FSTEST_IMGSIZE #define FSTEST_IMGSIZE (10000 * 512) #endif #ifndef FSTEST_MNTNAME #define FSTEST_MNTNAME "/mnt" #endif #define FSTEST_CONSTRUCTOR(_tc_, _fs_, _args_) \ do { \ if (_fs_##_fstest_newfs(_tc_, &_args_, \ FSTEST_IMGNAME, FSTEST_IMGSIZE, NULL) != 0) \ atf_tc_fail_errno("newfs failed"); \ if (_fs_##_fstest_mount(_tc_, _args_, FSTEST_MNTNAME, 0) != 0) \ atf_tc_fail_errno("mount failed"); \ } while (/*CONSTCOND*/0); #define FSTEST_CONSTRUCTOR_FSPRIV(_tc_, _fs_, _args_, _privargs_) \ do { \ if (_fs_##_fstest_newfs(_tc_, &_args_, \ FSTEST_IMGNAME, FSTEST_IMGSIZE, _privargs_) != 0) \ atf_tc_fail_errno("newfs failed"); \ if (_fs_##_fstest_mount(_tc_, _args_, FSTEST_MNTNAME, 0) != 0) \ atf_tc_fail_errno("mount failed"); \ } while (/*CONSTCOND*/0); #define FSTEST_DESTRUCTOR(_tc_, _fs_, _args_) \ do { \ if (_fs_##_fstest_unmount(_tc_, FSTEST_MNTNAME, 0) != 0) { \ rump_pub_vfs_mount_print(FSTEST_MNTNAME, 1); \ atf_tc_fail_errno("unmount failed"); \ } \ if (_fs_##_fstest_delfs(_tc_, _args_) != 0) \ atf_tc_fail_errno("delfs failed"); \ } while (/*CONSTCOND*/0); #define ATF_TC_FSADD(fs,type,func,desc) \ ATF_TC(fs##_##func); \ ATF_TC_HEAD(fs##_##func,tc) \ { \ 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; \ \ ATF_TC_BODY(fs##_##func,tc) \ { \ if (!atf_check_fstype(tc, #fs)) \ atf_tc_skip("filesystem not selected"); \ FSTEST_CONSTRUCTOR(tc,fs,fs##func##tmp); \ func(tc,FSTEST_MNTNAME); \ if (fs##_fstest_unmount(tc, FSTEST_MNTNAME, 0) != 0) { \ rump_pub_vfs_mount_print(FSTEST_MNTNAME, 1); \ atf_tc_fail_errno("unmount failed"); \ } \ } #define ATF_TC_FSADD_RO(_fs_,_type_,_func_,_desc_,_gen_) \ ATF_TC(_fs_##_##_func_); \ ATF_TC_HEAD(_fs_##_##_func_,tc) \ { \ 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; \ \ ATF_TC_BODY(_fs_##_##_func_,tc) \ { \ if (!atf_check_fstype(tc, #_fs_)) \ atf_tc_skip("filesystem not selected"); \ FSTEST_CONSTRUCTOR(tc,_fs_,_fs_##_func_##tmp); \ _gen_(tc,FSTEST_MNTNAME); \ if (_fs_##_fstest_unmount(tc, FSTEST_MNTNAME, 0) != 0) \ 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); \ atf_tc_fail_errno("unmount failed"); \ } \ } #define ATF_TP_FSADD(fs,func) \ ATF_TP_ADD_TC(tp,fs##_##func) #define ATF_TC_FSAPPLY_NOZFS(func,desc) \ ATF_TC_FSADD(ext2fs,MOUNT_EXT2FS,func,desc) \ ATF_TC_FSADD(ffs,MOUNT_FFS,func,desc) \ ATF_TC_FSADD(ffslog,MOUNT_FFS,func,desc) \ ATF_TC_FSADD(lfs,MOUNT_LFS,func,desc) \ ATF_TC_FSADD(msdosfs,MOUNT_MSDOS,func,desc) \ ATF_TC_FSADD(nfs,MOUNT_NFS,func,desc) \ ATF_TC_FSADD(puffs,MOUNT_PUFFS,func,desc) \ ATF_TC_FSADD(p2k_ffs,MOUNT_PUFFS,func,desc) \ ATF_TC_FSADD(rumpfs,MOUNT_RUMPFS,func,desc) \ ATF_TC_FSADD(sysvbfs,MOUNT_SYSVBFS,func,desc) \ ATF_TC_FSADD(tmpfs,MOUNT_TMPFS,func,desc) \ ATF_TC_FSADD(udf,MOUNT_UDF,func,desc) \ ATF_TC_FSADD(v7fs,MOUNT_V7FS,func,desc) #define ATF_TP_FSAPPLY_NOZFS(func) \ ATF_TP_FSADD(ext2fs,func); \ ATF_TP_FSADD(ffs,func); \ ATF_TP_FSADD(ffslog,func); \ ATF_TP_FSADD(lfs,func); \ ATF_TP_FSADD(msdosfs,func); \ ATF_TP_FSADD(nfs,func); \ ATF_TP_FSADD(puffs,func); \ ATF_TP_FSADD(p2k_ffs,func); \ ATF_TP_FSADD(rumpfs,func); \ ATF_TP_FSADD(sysvbfs,func); \ ATF_TP_FSADD(tmpfs,func); \ ATF_TP_FSADD(udf,func); \ ATF_TP_FSADD(v7fs,func); /* XXX: this will not scale */ #ifdef WANT_ZFS_TESTS #define ATF_TC_FSAPPLY(func,desc) \ ATF_TC_FSAPPLY_NOZFS(func,desc) \ ATF_TC_FSADD(zfs,MOUNT_ZFS,func,desc) #define ATF_TP_FSAPPLY(func) \ ATF_TP_FSAPPLY_NOZFS(func) \ ATF_TP_FSADD(zfs,func); #else /* !WANT_ZFS_TESTS */ #define ATF_TC_FSAPPLY(func,desc) \ ATF_TC_FSAPPLY_NOZFS(func,desc) #define ATF_TP_FSAPPLY(func) \ ATF_TP_FSAPPLY_NOZFS(func) #endif /* WANT_ZFS_TESTS */ /* * Same as above, but generate a file system image first and perform * tests for a r/o mount. * * Missing the following file systems: * + lfs (fstest_lfs routines cannot handle remount. FIXME!) * + tmpfs (memory backend) * + rumpfs (memory backend) * + puffs (memory backend, but could be run in theory) */ #define ATF_TC_FSAPPLY_RO(func,desc,gen) \ ATF_TC_FSADD_RO(ext2fs,MOUNT_EXT2FS,func,desc,gen) \ ATF_TC_FSADD_RO(ffs,MOUNT_FFS,func,desc,gen) \ ATF_TC_FSADD_RO(ffslog,MOUNT_FFS,func,desc,gen) \ ATF_TC_FSADD_RO(msdosfs,MOUNT_MSDOS,func,desc,gen) \ ATF_TC_FSADD_RO(nfs,MOUNT_NFS,func,desc,gen) \ ATF_TC_FSADD_RO(nfsro,MOUNT_NFS,func,desc,gen) \ ATF_TC_FSADD_RO(sysvbfs,MOUNT_SYSVBFS,func,desc,gen) \ ATF_TC_FSADD_RO(udf,MOUNT_UDF,func,desc,gen) \ ATF_TC_FSADD_RO(v7fs,MOUNT_V7FS,func,desc,gen) #define ATF_TP_FSAPPLY_RO(func) \ ATF_TP_FSADD(ext2fs,func); \ ATF_TP_FSADD(ffs,func); \ ATF_TP_FSADD(ffslog,func); \ ATF_TP_FSADD(msdosfs,func); \ ATF_TP_FSADD(nfs,func); \ ATF_TP_FSADD(nfsro,func); \ ATF_TP_FSADD(sysvbfs,func); \ ATF_TP_FSADD(udf,func); \ ATF_TP_FSADD(v7fs,func); #define ATF_FSAPPLY(func,desc) \ ATF_TC_FSAPPLY(func,desc); \ ATF_TP_ADD_TCS(tp) \ { \ ATF_TP_FSAPPLY(func); \ return atf_no_error(); \ } static __inline bool atf_check_fstype(const atf_tc_t *tc, const char *fs) { const char *fstype; if (!atf_tc_has_config_var(tc, "fstype")) return true; fstype = atf_tc_get_config_var(tc, "fstype"); if (strcmp(fstype, fs) == 0) return true; return false; } #define FSTYPE_EXT2FS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "ext2fs") == 0) #define FSTYPE_FFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "ffs") == 0) #define FSTYPE_FFSLOG(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "ffslog") == 0) #define FSTYPE_LFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "lfs") == 0) #define FSTYPE_MSDOS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "msdosfs") == 0) #define FSTYPE_NFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "nfs") == 0) #define FSTYPE_NFSRO(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "nfsro") == 0) #define FSTYPE_P2K_FFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "p2k_ffs") == 0) #define FSTYPE_PUFFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "puffs") == 0) #define FSTYPE_RUMPFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "rumpfs") == 0) #define FSTYPE_SYSVBFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "sysvbfs") == 0) #define FSTYPE_TMPFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "tmpfs") == 0) #define FSTYPE_UDF(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "udf") == 0) #define FSTYPE_V7FS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "v7fs") == 0) #define FSTYPE_ZFS(tc)\ (strcmp(atf_tc_get_md_var(tc, "X-fs.type"), "zfs") == 0) #define FSTEST_ENTER() \ if (rump_sys_chdir(FSTEST_MNTNAME) == -1) \ atf_tc_fail_errno("failed to cd into test mount") #define FSTEST_EXIT() \ if (rump_sys_chdir("/") == -1) \ atf_tc_fail_errno("failed to cd out of test mount") /* * file system args structures */ struct nfstestargs { pid_t ta_childpid; char ta_ethername[MAXPATHLEN]; }; struct puffstestargs { uint8_t *pta_pargs; size_t pta_pargslen; int pta_pflags; pid_t pta_childpid; int pta_rumpfd; int pta_servfd; char pta_dev[MAXPATHLEN]; char pta_dir[MAXPATHLEN]; int pta_mntflags; int pta_vfs_toserv_ops[PUFFS_VFS_MAX]; int pta_vn_toserv_ops[PUFFS_VN_MAX]; }; #endif /* __H_FSMACROS_H_ */ Index: projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c =================================================================== --- projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c (revision 304002) +++ projects/netbsd-tests-update-12/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c (nonexistent) @@ -1,2575 +0,0 @@ -/* $NetBSD: mountd.c,v 1.8 2013/10/19 17:45:00 christos Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Herb Hasler and 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 -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; -#else -__RCSID("$NetBSD: mountd.c,v 1.8 2013/10/19 17:45:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pathnames.h" - -#ifdef IPSEC -#include -#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */ -#undef IPSEC -#endif -#include "ipsec.h" -#endif - -#include "svc_fdset.h" - -#include - -/* - * Structures for keeping the mount list and export list - */ -struct mountlist { - struct mountlist *ml_next; - char ml_host[RPCMNT_NAMELEN + 1]; - char ml_dirp[RPCMNT_PATHLEN + 1]; - int ml_flag;/* XXX more flags (same as dp_flag) */ -}; - -struct dirlist { - struct dirlist *dp_left; - struct dirlist *dp_right; - int dp_flag; - struct hostlist *dp_hosts; /* List of hosts this dir exported to */ - char dp_dirp[1]; /* Actually malloc'd to size of dir */ -}; -/* dp_flag bits */ -#define DP_DEFSET 0x1 -#define DP_HOSTSET 0x2 -#define DP_KERB 0x4 -#define DP_NORESMNT 0x8 - -struct exportlist { - struct exportlist *ex_next; - struct dirlist *ex_dirl; - struct dirlist *ex_defdir; - int ex_flag; - fsid_t ex_fs; - char *ex_fsdir; - char *ex_indexfile; -}; -/* ex_flag bits */ -#define EX_LINKED 0x1 - -struct netmsk { - struct sockaddr_storage nt_net; - int nt_len; - char *nt_name; -}; - -union grouptypes { - struct addrinfo *gt_addrinfo; - struct netmsk gt_net; -}; - -struct grouplist { - int gr_type; - union grouptypes gr_ptr; - struct grouplist *gr_next; -}; -/* Group types */ -#define GT_NULL 0x0 -#define GT_HOST 0x1 -#define GT_NET 0x2 - -struct hostlist { - int ht_flag;/* Uses DP_xx bits */ - struct grouplist *ht_grp; - struct hostlist *ht_next; -}; - -struct fhreturn { - int fhr_flag; - int fhr_vers; - size_t fhr_fhsize; - union { - uint8_t v2[NFSX_V2FH]; - uint8_t v3[NFSX_V3FHMAX]; - } fhr_fh; -}; - -/* Global defs */ -static char *add_expdir __P((struct dirlist **, char *, int)); -static void add_dlist __P((struct dirlist **, struct dirlist *, - struct grouplist *, int)); -static void add_mlist __P((char *, char *, int)); -static int check_dirpath __P((const char *, size_t, char *)); -static int check_options __P((const char *, size_t, struct dirlist *)); -static int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *)); -static int del_mlist __P((char *, char *, struct sockaddr *)); -static struct dirlist *dirp_search __P((struct dirlist *, char *)); -static int do_nfssvc __P((const char *, size_t, struct exportlist *, - struct grouplist *, int, struct uucred *, char *, int, struct statvfs *)); -static int do_opt __P((const char *, size_t, char **, char **, - struct exportlist *, struct grouplist *, int *, int *, struct uucred *)); -static struct exportlist *ex_search __P((fsid_t *)); -static int parse_directory __P((const char *, size_t, struct grouplist *, - int, char *, struct exportlist **, struct statvfs *)); -static int parse_host_netgroup __P((const char *, size_t, struct exportlist *, - struct grouplist *, char *, int *, struct grouplist **)); -static struct exportlist *get_exp __P((void)); -static void free_dir __P((struct dirlist *)); -static void free_exp __P((struct exportlist *)); -static void free_grp __P((struct grouplist *)); -static void free_host __P((struct hostlist *)); -void get_exportlist __P((int)); -static int get_host __P((const char *, size_t, const char *, - struct grouplist *)); -static struct hostlist *get_ht __P((void)); -static void get_mountlist __P((void)); -static int get_net __P((char *, struct netmsk *, int)); -static void free_exp_grp __P((struct exportlist *, struct grouplist *)); -static struct grouplist *get_grp __P((void)); -static void hang_dirp __P((struct dirlist *, struct grouplist *, - struct exportlist *, int)); -static void mntsrv __P((struct svc_req *, SVCXPRT *)); -static void nextfield __P((char **, char **)); -static void parsecred __P((char *, struct uucred *)); -static int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); -static int scan_tree __P((struct dirlist *, struct sockaddr *)); -static void send_umntall __P((int)); -#if 0 -static int umntall_each __P((caddr_t, struct sockaddr_in *)); -#endif -static int xdr_dir __P((XDR *, char *)); -static int xdr_explist __P((XDR *, caddr_t)); -static int xdr_fhs __P((XDR *, caddr_t)); -static int xdr_mlist __P((XDR *, caddr_t)); -static int bitcmp __P((void *, void *, int)); -static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int)); -static int sacmp __P((struct sockaddr *, struct sockaddr *)); -static int allones __P((struct sockaddr_storage *, int)); -static int countones __P((struct sockaddr *)); -static void bind_resv_port __P((int, sa_family_t, in_port_t)); -static void no_nfs(int); -static struct exportlist *exphead; -static struct mountlist *mlhead; -static struct grouplist *grphead; -static char *exname; -static struct uucred def_anon = { - 1, - (uid_t) -2, - (gid_t) -2, - 0, - { 0 } -}; - -static int opt_flags; -static int have_v6 = 1; -static const int ninumeric = NI_NUMERICHOST; - -/* Bits for above */ -#define OP_MAPROOT 0x001 -#define OP_MAPALL 0x002 -#define OP_KERB 0x004 -#define OP_MASK 0x008 -#define OP_NET 0x010 -#define OP_ALLDIRS 0x040 -#define OP_NORESPORT 0x080 -#define OP_NORESMNT 0x100 -#define OP_MASKLEN 0x200 - -static int debug = 1; -#if 0 -static void SYSLOG __P((int, const char *,...)); -#endif -int main __P((int, char *[])); - -/* - * If this is non-zero, -noresvport and -noresvmnt are implied for - * each export. - */ -static int noprivports; - -#define C2FD(_c_) ((int)(uintptr_t)(_c_)) -static int -rumpread(void *cookie, char *buf, int count) -{ - - return rump_sys_read(C2FD(cookie), buf, count); -} - -static int -rumpwrite(void *cookie, const char *buf, int count) -{ - - return rump_sys_write(C2FD(cookie), buf, count); -} - -static off_t -rumpseek(void *cookie, off_t off, int whence) -{ - - return rump_sys_lseek(C2FD(cookie), off, whence); -} - -static int -rumpclose(void *cookie) -{ - - return rump_sys_close(C2FD(cookie)); -} - -int __sflags(const char *, int *); /* XXX */ -static FILE * -rumpfopen(const char *path, const char *opts) -{ - int fd, oflags; - - __sflags(opts, &oflags); - fd = rump_sys_open(path, oflags, 0777); - if (fd == -1) - return NULL; - - return funopen((void *)(uintptr_t)fd, - rumpread, rumpwrite, rumpseek, rumpclose); -} - -/* - * Make sure mountd signal handler is executed from a thread context - * instead of the signal handler. This avoids the signal handler - * ruining our kernel context. - */ -static sem_t exportsem; -static void -signal_get_exportlist(int sig) -{ - - sem_post(&exportsem); -} - -static void * -exportlist_thread(void *arg) -{ - - for (;;) { - sem_wait(&exportsem); - get_exportlist(0); - } - - return NULL; -} - -/* - * Mountd server for NFS mount protocol as described in: - * NFS: Network File System Protocol Specification, RFC1094, Appendix A - * The optional arguments are the exports file name - * default: _PATH_EXPORTS - * "-d" to enable debugging - * and "-n" to allow nonroot mount. - */ -void *mountd_main(void *); -void * -mountd_main(void *arg) -{ - SVCXPRT *udptransp, *tcptransp; - struct netconfig *udpconf, *tcpconf; - int udpsock, tcpsock; - int xcreated = 0; - int maxrec = RPC_MAXDATASIZE; - in_port_t forcedport = 0; - extern sem_t gensem; - pthread_t ptdummy; - - alloc_fdset(); - -#if 0 - while ((c = getopt(argc, argv, "dNnrp:" ADDOPTS)) != -1) - switch (c) { -#ifdef IPSEC - case 'P': - if (ipsecsetup_test(policy = optarg)) - errx(1, "Invalid ipsec policy `%s'", policy); - break; -#endif - case 'p': - /* A forced port "0" will dynamically allocate a port */ - forcedport = atoi(optarg); - break; - case 'd': - debug = 1; - break; - case 'N': - noprivports = 1; - break; - /* Compatibility */ - case 'n': - case 'r': - break; - default: - fprintf(stderr, "usage: %s [-dNn]" -#ifdef IPSEC - " [-P policy]" -#endif - " [-p port] [exportsfile]\n", getprogname()); - exit(1); - }; - argc -= optind; - argv += optind; -#endif - - sem_init(&exportsem, 0, 0); - pthread_create(&ptdummy, NULL, exportlist_thread, NULL); - - grphead = NULL; - exphead = NULL; - mlhead = NULL; - exname = _PATH_EXPORTS; - openlog("mountd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON); - (void)signal(SIGSYS, no_nfs); - - if (debug) - (void)fprintf(stderr, "Getting export list.\n"); - get_exportlist(0); - if (debug) - (void)fprintf(stderr, "Getting mount list.\n"); - get_mountlist(); - if (debug) - (void)fprintf(stderr, "Here we go.\n"); - if (debug == 0) { - daemon(0, 0); - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - } - (void)signal(SIGHUP, signal_get_exportlist); - (void)signal(SIGTERM, send_umntall); - pidfile(NULL); - - rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); - rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); - - udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - udpconf = getnetconfigent("udp"); - tcpconf = getnetconfigent("tcp"); - - rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); - - if (udpsock != -1 && udpconf != NULL) { - bind_resv_port(udpsock, AF_INET, forcedport); -#ifdef IPSEC - if (policy) - ipsecsetup(AF_INET, udpsock, policy); -#endif - udptransp = svc_dg_create(udpsock, 0, 0); - if (udptransp != NULL) { - if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, udpconf) || - !svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, udpconf)) { - syslog(LOG_WARNING, "can't register UDP service"); - } - else { - xcreated++; - } - } else { - syslog(LOG_WARNING, "can't create UDP service"); - } - - } - - if (tcpsock != -1 && tcpconf != NULL) { - bind_resv_port(tcpsock, AF_INET, forcedport); -#ifdef IPSEC - if (policy) - ipsecsetup(AF_INET, tcpsock, policy); -#endif - listen(tcpsock, SOMAXCONN); - tcptransp = svc_vc_create(tcpsock, RPC_MAXDATASIZE, - RPC_MAXDATASIZE); - if (tcptransp != NULL) { - if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, tcpconf) || - !svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, tcpconf)) - syslog(LOG_WARNING, "can't register TCP service"); - else - xcreated++; - } else - syslog(LOG_WARNING, "can't create TCP service"); - - } - - if (xcreated == 0) { - syslog(LOG_ERR, "could not create any services"); - exit(1); - } - - sem_post(&gensem); - svc_run(); - syslog(LOG_ERR, "Mountd died"); - exit(1); -} - -/* - * The mount rpc service - */ -void -mntsrv(rqstp, transp) - struct svc_req *rqstp; - SVCXPRT *transp; -{ - struct exportlist *ep; - struct dirlist *dp; - struct fhreturn fhr; - struct stat stb; - struct statvfs fsb; - char host[NI_MAXHOST], numerichost[NI_MAXHOST]; - int lookup_failed = 1; - struct sockaddr *saddr; - u_short sport; - char rpcpath[RPCMNT_PATHLEN + 1], dpath[MAXPATHLEN]; - long bad = EACCES; - int defset, hostset, ret; - sigset_t sighup_mask; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - size_t fh_size; - int error = 0; - - (void)sigemptyset(&sighup_mask); - (void)sigaddset(&sighup_mask, SIGHUP); - saddr = svc_getrpccaller(transp)->buf; - switch (saddr->sa_family) { - case AF_INET6: - sin6 = (struct sockaddr_in6 *)saddr; - sport = ntohs(sin6->sin6_port); - break; - case AF_INET: - sin = (struct sockaddr_in *)saddr; - sport = ntohs(sin->sin_port); - break; - default: - syslog(LOG_ERR, "request from unknown address family"); - return; - } - lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, - NULL, 0, 0); - if (getnameinfo(saddr, saddr->sa_len, numerichost, - sizeof numerichost, NULL, 0, ninumeric) != 0) - strlcpy(numerichost, "?", sizeof(numerichost)); - ret = 0; - switch (rqstp->rq_proc) { - case NULLPROC: - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_MNT: - if (debug) - fprintf(stderr, - "got mount request from %s\n", numerichost); - if (!svc_getargs(transp, xdr_dir, rpcpath)) { - if (debug) - fprintf(stderr, "-> garbage args\n"); - svcerr_decode(transp); - return; - } - if (debug) - fprintf(stderr, - "-> rpcpath: %s\n", rpcpath); - /* - * Get the real pathname and make sure it is a file or - * directory that exists. - */ -#if 0 - if (realpath(rpcpath, dpath) == 0 || -#endif - strcpy(dpath, rpcpath); - if (rump_sys_stat(dpath, &stb) < 0 || - (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) || - rump_sys_statvfs1(dpath, &fsb, ST_WAIT) < 0) { - (void)chdir("/"); /* Just in case realpath doesn't */ - if (debug) - (void)fprintf(stderr, "-> stat failed on %s\n", - dpath); - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, (caddr_t) &bad)) - syslog(LOG_ERR, "Can't send reply"); - return; - } - if (debug) - fprintf(stderr, - "-> dpath: %s\n", dpath); - /* Check in the exports list */ - (void)sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = ex_search(&fsb.f_fsidx); - hostset = defset = 0; - if (ep && (chk_host(ep->ex_defdir, saddr, &defset, - &hostset) || ((dp = dirp_search(ep->ex_dirl, dpath)) && - chk_host(dp, saddr, &defset, &hostset)) || - (defset && scan_tree(ep->ex_defdir, saddr) == 0 && - scan_tree(ep->ex_dirl, saddr) == 0))) { - if ((hostset & DP_HOSTSET) == 0) { - hostset = defset; - } - if (sport >= IPPORT_RESERVED && - !(hostset & DP_NORESMNT)) { - syslog(LOG_NOTICE, - "Refused mount RPC from host %s port %d", - numerichost, sport); - svcerr_weakauth(transp); - goto out; - } - fhr.fhr_flag = hostset; - fhr.fhr_vers = rqstp->rq_vers; - /* Get the file handle */ - memset(&fhr.fhr_fh, 0, sizeof(fhr.fhr_fh)); /* for v2 */ - fh_size = sizeof(fhr.fhr_fh); - error = 0; - if (rump_sys_getfh(dpath, &fhr.fhr_fh, &fh_size) < 0) { - bad = error; - //syslog(LOG_ERR, "Can't get fh for %s %d %d", dpath, error, fh_size); - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, - (char *)&bad)) - syslog(LOG_ERR, "Can't send reply"); - goto out; - } - if ((fhr.fhr_vers == 1 && fh_size > NFSX_V2FH) || - fh_size > NFSX_V3FHMAX) { - bad = EINVAL; /* XXX */ - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, - (char *)&bad)) - syslog(LOG_ERR, "Can't send reply"); - goto out; - } - fhr.fhr_fhsize = fh_size; - if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs, (char *) &fhr)) - syslog(LOG_ERR, "Can't send reply"); - if (!lookup_failed) - add_mlist(host, dpath, hostset); - else - add_mlist(numerichost, dpath, hostset); - if (debug) - (void)fprintf(stderr, "Mount successful.\n"); - } else { - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, (caddr_t) &bad)) - syslog(LOG_ERR, "Can't send reply"); - } -out: - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return; - case MOUNTPROC_DUMP: - if (!svc_sendreply(transp, (xdrproc_t)xdr_mlist, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_UMNT: - if (!svc_getargs(transp, xdr_dir, dpath)) { - svcerr_decode(transp); - return; - } - if (!lookup_failed) - ret = del_mlist(host, dpath, saddr); - ret |= del_mlist(numerichost, dpath, saddr); - if (ret) { - svcerr_weakauth(transp); - return; - } - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_UMNTALL: - if (!lookup_failed) - ret = del_mlist(host, NULL, saddr); - ret |= del_mlist(numerichost, NULL, saddr); - if (ret) { - svcerr_weakauth(transp); - return; - } - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_EXPORT: - case MOUNTPROC_EXPORTALL: - if (!svc_sendreply(transp, (xdrproc_t)xdr_explist, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - - - default: - svcerr_noproc(transp); - return; - } -} - -/* - * Xdr conversion for a dpath string - */ -static int -xdr_dir(xdrsp, dirp) - XDR *xdrsp; - char *dirp; -{ - - return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); -} - -/* - * Xdr routine to generate file handle reply - */ -static int -xdr_fhs(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct fhreturn *fhrp = (struct fhreturn *) cp; - long ok = 0, len, auth; - - if (!xdr_long(xdrsp, &ok)) - return (0); - switch (fhrp->fhr_vers) { - case 1: - return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); - case 3: - len = fhrp->fhr_fhsize; - if (!xdr_long(xdrsp, &len)) - return (0); - if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) - return (0); - if (fhrp->fhr_flag & DP_KERB) - auth = RPCAUTH_KERB4; - else - auth = RPCAUTH_UNIX; - len = 1; - if (!xdr_long(xdrsp, &len)) - return (0); - return (xdr_long(xdrsp, &auth)); - }; - return (0); -} - -int -xdr_mlist(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct mountlist *mlp; - int trueval = 1; - int falseval = 0; - char *strp; - - mlp = mlhead; - while (mlp) { - if (!xdr_bool(xdrsp, &trueval)) - return (0); - strp = &mlp->ml_host[0]; - if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) - return (0); - strp = &mlp->ml_dirp[0]; - if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) - return (0); - mlp = mlp->ml_next; - } - if (!xdr_bool(xdrsp, &falseval)) - return (0); - return (1); -} - -/* - * Xdr conversion for export list - */ -int -xdr_explist(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct exportlist *ep; - int falseval = 0; - int putdef; - sigset_t sighup_mask; - - (void)sigemptyset(&sighup_mask); - (void)sigaddset(&sighup_mask, SIGHUP); - (void)sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = exphead; - while (ep) { - putdef = 0; - if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) - goto errout; - if (ep->ex_defdir && putdef == 0 && - put_exlist(ep->ex_defdir, xdrsp, NULL, &putdef)) - goto errout; - ep = ep->ex_next; - } - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - if (!xdr_bool(xdrsp, &falseval)) - return (0); - return (1); -errout: - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return (0); -} - -/* - * Called from xdr_explist() to traverse the tree and export the - * directory paths. Assumes SIGHUP has already been masked. - */ -int -put_exlist(dp, xdrsp, adp, putdefp) - struct dirlist *dp; - XDR *xdrsp; - struct dirlist *adp; - int *putdefp; -{ - struct grouplist *grp; - struct hostlist *hp; - int trueval = 1; - int falseval = 0; - int gotalldir = 0; - char *strp; - - if (dp) { - if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) - return (1); - if (!xdr_bool(xdrsp, &trueval)) - return (1); - strp = dp->dp_dirp; - if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) - return (1); - if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { - gotalldir = 1; - *putdefp = 1; - } - if ((dp->dp_flag & DP_DEFSET) == 0 && - (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { - hp = dp->dp_hosts; - while (hp) { - grp = hp->ht_grp; - if (grp->gr_type == GT_HOST) { - if (!xdr_bool(xdrsp, &trueval)) - return (1); - strp = - grp->gr_ptr.gt_addrinfo->ai_canonname; - if (!xdr_string(xdrsp, &strp, - RPCMNT_NAMELEN)) - return (1); - } else if (grp->gr_type == GT_NET) { - if (!xdr_bool(xdrsp, &trueval)) - return (1); - strp = grp->gr_ptr.gt_net.nt_name; - if (!xdr_string(xdrsp, &strp, - RPCMNT_NAMELEN)) - return (1); - } - hp = hp->ht_next; - if (gotalldir && hp == NULL) { - hp = adp->dp_hosts; - gotalldir = 0; - } - } - } - if (!xdr_bool(xdrsp, &falseval)) - return (1); - if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) - return (1); - } - return (0); -} - -static int -parse_host_netgroup(line, lineno, ep, tgrp, cp, has_host, grp) - const char *line; - size_t lineno; - struct exportlist *ep; - struct grouplist *tgrp; - char *cp; - int *has_host; - struct grouplist **grp; -{ - const char *hst, *usr, *dom; - int netgrp; - - if (ep == NULL) { - syslog(LOG_ERR, "\"%s\", line %ld: No current export", - line, (unsigned long)lineno); - return 0; - } - setnetgrent(cp); - netgrp = getnetgrent(&hst, &usr, &dom); - do { - if (*has_host) { - (*grp)->gr_next = get_grp(); - *grp = (*grp)->gr_next; - } - if (netgrp) { - if (hst == NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: No host in netgroup %s", - line, (unsigned long)lineno, cp); - goto bad; - } - if (get_host(line, lineno, hst, *grp)) - goto bad; - } else if (get_host(line, lineno, cp, *grp)) - goto bad; - *has_host = TRUE; - } while (netgrp && getnetgrent(&hst, &usr, &dom)); - - endnetgrent(); - return 1; -bad: - endnetgrent(); - return 0; - -} - -static int -parse_directory(line, lineno, tgrp, got_nondir, cp, ep, fsp) - const char *line; - size_t lineno; - struct grouplist *tgrp; - int got_nondir; - char *cp; - struct exportlist **ep; - struct statvfs *fsp; -{ - int error = 0; - - if (!check_dirpath(line, lineno, cp)) - return 0; - - if (rump_sys_statvfs1(cp, fsp, ST_WAIT) == -1) { - syslog(LOG_ERR, "\"%s\", line %ld: statvfs for `%s' failed: %m %d", - line, (unsigned long)lineno, cp, error); - return 0; - } - - if (got_nondir) { - syslog(LOG_ERR, - "\"%s\", line %ld: Directories must precede files", - line, (unsigned long)lineno); - return 0; - } - if (*ep) { - if ((*ep)->ex_fs.__fsid_val[0] != fsp->f_fsidx.__fsid_val[0] || - (*ep)->ex_fs.__fsid_val[1] != fsp->f_fsidx.__fsid_val[1]) { - syslog(LOG_ERR, - "\"%s\", line %ld: filesystem ids disagree", - line, (unsigned long)lineno); - return 0; - } - } else { - /* - * See if this directory is already - * in the list. - */ - *ep = ex_search(&fsp->f_fsidx); - if (*ep == NULL) { - *ep = get_exp(); - (*ep)->ex_fs = fsp->f_fsidx; - (*ep)->ex_fsdir = estrdup(fsp->f_mntonname); - if (debug) - (void)fprintf(stderr, - "Making new ep fs=0x%x,0x%x\n", - fsp->f_fsidx.__fsid_val[0], fsp->f_fsidx.__fsid_val[1]); - } else { - if (debug) - (void)fprintf(stderr, - "Found ep fs=0x%x,0x%x\n", - fsp->f_fsidx.__fsid_val[0], fsp->f_fsidx.__fsid_val[1]); - } - } - - return 1; -} - - -/* - * Get the export list - */ -/* ARGSUSED */ -void -get_exportlist(n) - int n; -{ - struct exportlist *ep, *ep2; - struct grouplist *grp, *tgrp; - struct exportlist **epp; - struct dirlist *dirhead; - struct statvfs fsb, *fsp; - struct addrinfo *ai; - struct uucred anon; - char *cp, *endcp, *dirp, savedc; - int has_host, exflags, got_nondir, dirplen, num, i; - FILE *exp_file; - char *line; - size_t lineno = 0, len; - - - /* - * First, get rid of the old list - */ - ep = exphead; - while (ep) { - ep2 = ep; - ep = ep->ex_next; - free_exp(ep2); - } - exphead = NULL; - - dirp = NULL; - dirplen = 0; - grp = grphead; - while (grp) { - tgrp = grp; - grp = grp->gr_next; - free_grp(tgrp); - } - grphead = NULL; - - /* - * And delete exports that are in the kernel for all local - * file systems. - */ - num = getmntinfo(&fsp, MNT_NOWAIT); - for (i = 0; i < num; i++) { - struct mountd_exports_list mel; - - /* Delete all entries from the export list. */ - mel.mel_path = fsp->f_mntonname; - mel.mel_nexports = 0; - if (rump_sys_nfssvc(NFSSVC_SETEXPORTSLIST, &mel) == -1 && - errno != EOPNOTSUPP) - syslog(LOG_ERR, "Can't delete exports for %s (%m)", - fsp->f_mntonname); - - fsp++; - } - - /* - * Read in the exports file and build the list, calling - * mount() as we go along to push the export rules into the kernel. - */ - exname = _PATH_EXPORTS; - if ((exp_file = rumpfopen(exname, "r")) == NULL) { - /* - * Don't exit here; we can still reload the config - * after a SIGHUP. - */ - if (debug) - (void)fprintf(stderr, "Can't open %s: %s\n", exname, - strerror(errno)); - return; - } - dirhead = NULL; - while ((line = fparseln(exp_file, &len, &lineno, NULL, 0)) != NULL) { - if (debug) - (void)fprintf(stderr, "Got line %s\n", line); - cp = line; - nextfield(&cp, &endcp); - if (cp == endcp) - goto nextline; /* skip empty line */ - /* - * Set defaults. - */ - has_host = FALSE; - anon = def_anon; - exflags = MNT_EXPORTED; - got_nondir = 0; - opt_flags = 0; - ep = NULL; - - if (noprivports) { - opt_flags |= OP_NORESMNT | OP_NORESPORT; - exflags |= MNT_EXNORESPORT; - } - - /* - * Create new exports list entry - */ - len = endcp - cp; - tgrp = grp = get_grp(); - while (len > 0) { - if (len > RPCMNT_NAMELEN) { - *endcp = '\0'; - syslog(LOG_ERR, - "\"%s\", line %ld: name `%s' is too long", - line, (unsigned long)lineno, cp); - goto badline; - } - switch (*cp) { - case '-': - /* - * Option - */ - if (ep == NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: No current export list", - line, (unsigned long)lineno); - goto badline; - } - if (debug) - (void)fprintf(stderr, "doing opt %s\n", - cp); - got_nondir = 1; - if (do_opt(line, lineno, &cp, &endcp, ep, grp, - &has_host, &exflags, &anon)) - goto badline; - break; - - case '/': - /* - * Directory - */ - savedc = *endcp; - *endcp = '\0'; - - if (!parse_directory(line, lineno, tgrp, - got_nondir, cp, &ep, &fsb)) - goto badline; - /* - * Add dirpath to export mount point. - */ - dirp = add_expdir(&dirhead, cp, len); - dirplen = len; - - *endcp = savedc; - break; - - default: - /* - * Host or netgroup. - */ - savedc = *endcp; - *endcp = '\0'; - - if (!parse_host_netgroup(line, lineno, ep, - tgrp, cp, &has_host, &grp)) - goto badline; - - got_nondir = 1; - - *endcp = savedc; - break; - } - - cp = endcp; - nextfield(&cp, &endcp); - len = endcp - cp; - } - if (check_options(line, lineno, dirhead)) - goto badline; - - if (!has_host) { - grp->gr_type = GT_HOST; - if (debug) - (void)fprintf(stderr, - "Adding a default entry\n"); - /* add a default group and make the grp list NULL */ - ai = emalloc(sizeof(struct addrinfo)); - ai->ai_flags = 0; - ai->ai_family = AF_INET; /* XXXX */ - ai->ai_socktype = SOCK_DGRAM; - /* setting the length to 0 will match anything */ - ai->ai_addrlen = 0; - ai->ai_flags = AI_CANONNAME; - ai->ai_canonname = estrdup("Default"); - ai->ai_addr = NULL; - ai->ai_next = NULL; - grp->gr_ptr.gt_addrinfo = ai; - - } else if ((opt_flags & OP_NET) && tgrp->gr_next) { - /* - * Don't allow a network export coincide with a list of - * host(s) on the same line. - */ - syslog(LOG_ERR, - "\"%s\", line %ld: Mixed exporting of networks and hosts is disallowed", - line, (unsigned long)lineno); - goto badline; - } - /* - * Loop through hosts, pushing the exports into the kernel. - * After loop, tgrp points to the start of the list and - * grp points to the last entry in the list. - */ - grp = tgrp; - do { - if (do_nfssvc(line, lineno, ep, grp, exflags, &anon, - dirp, dirplen, &fsb)) - goto badline; - } while (grp->gr_next && (grp = grp->gr_next)); - - /* - * Success. Update the data structures. - */ - if (has_host) { - hang_dirp(dirhead, tgrp, ep, opt_flags); - grp->gr_next = grphead; - grphead = tgrp; - } else { - hang_dirp(dirhead, NULL, ep, opt_flags); - free_grp(tgrp); - } - tgrp = NULL; - dirhead = NULL; - if ((ep->ex_flag & EX_LINKED) == 0) { - ep2 = exphead; - epp = &exphead; - - /* - * Insert in the list in alphabetical order. - */ - while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { - epp = &ep2->ex_next; - ep2 = ep2->ex_next; - } - if (ep2) - ep->ex_next = ep2; - *epp = ep; - ep->ex_flag |= EX_LINKED; - } - goto nextline; -badline: - free_exp_grp(ep, grp); -nextline: - if (dirhead) { - free_dir(dirhead); - dirhead = NULL; - } - free(line); - } - (void)fclose(exp_file); -} - -/* - * Allocate an export list element - */ -static struct exportlist * -get_exp() -{ - struct exportlist *ep; - - ep = emalloc(sizeof(struct exportlist)); - (void)memset(ep, 0, sizeof(struct exportlist)); - return (ep); -} - -/* - * Allocate a group list element - */ -static struct grouplist * -get_grp() -{ - struct grouplist *gp; - - gp = emalloc(sizeof(struct grouplist)); - (void)memset(gp, 0, sizeof(struct grouplist)); - return (gp); -} - -/* - * Clean up upon an error in get_exportlist(). - */ -static void -free_exp_grp(ep, grp) - struct exportlist *ep; - struct grouplist *grp; -{ - struct grouplist *tgrp; - - if (ep && (ep->ex_flag & EX_LINKED) == 0) - free_exp(ep); - while (grp) { - tgrp = grp; - grp = grp->gr_next; - free_grp(tgrp); - } -} - -/* - * Search the export list for a matching fs. - */ -static struct exportlist * -ex_search(fsid) - fsid_t *fsid; -{ - struct exportlist *ep; - - ep = exphead; - return ep; - while (ep) { - if (ep->ex_fs.__fsid_val[0] == fsid->__fsid_val[0] && - ep->ex_fs.__fsid_val[1] == fsid->__fsid_val[1]) - return (ep); - ep = ep->ex_next; - } - return (ep); -} - -/* - * Add a directory path to the list. - */ -static char * -add_expdir(dpp, cp, len) - struct dirlist **dpp; - char *cp; - int len; -{ - struct dirlist *dp; - - dp = emalloc(sizeof(struct dirlist) + len); - dp->dp_left = *dpp; - dp->dp_right = NULL; - dp->dp_flag = 0; - dp->dp_hosts = NULL; - (void)strcpy(dp->dp_dirp, cp); - *dpp = dp; - return (dp->dp_dirp); -} - -/* - * Hang the dir list element off the dirpath binary tree as required - * and update the entry for host. - */ -void -hang_dirp(dp, grp, ep, flags) - struct dirlist *dp; - struct grouplist *grp; - struct exportlist *ep; - int flags; -{ - struct hostlist *hp; - struct dirlist *dp2; - - if (flags & OP_ALLDIRS) { - if (ep->ex_defdir) - free(dp); - else - ep->ex_defdir = dp; - if (grp == NULL) { - ep->ex_defdir->dp_flag |= DP_DEFSET; - if (flags & OP_KERB) - ep->ex_defdir->dp_flag |= DP_KERB; - if (flags & OP_NORESMNT) - ep->ex_defdir->dp_flag |= DP_NORESMNT; - } else - while (grp) { - hp = get_ht(); - if (flags & OP_KERB) - hp->ht_flag |= DP_KERB; - if (flags & OP_NORESMNT) - hp->ht_flag |= DP_NORESMNT; - hp->ht_grp = grp; - hp->ht_next = ep->ex_defdir->dp_hosts; - ep->ex_defdir->dp_hosts = hp; - grp = grp->gr_next; - } - } else { - - /* - * Loop through the directories adding them to the tree. - */ - while (dp) { - dp2 = dp->dp_left; - add_dlist(&ep->ex_dirl, dp, grp, flags); - dp = dp2; - } - } -} - -/* - * Traverse the binary tree either updating a node that is already there - * for the new directory or adding the new node. - */ -static void -add_dlist(dpp, newdp, grp, flags) - struct dirlist **dpp; - struct dirlist *newdp; - struct grouplist *grp; - int flags; -{ - struct dirlist *dp; - struct hostlist *hp; - int cmp; - - dp = *dpp; - if (dp) { - cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); - if (cmp > 0) { - add_dlist(&dp->dp_left, newdp, grp, flags); - return; - } else if (cmp < 0) { - add_dlist(&dp->dp_right, newdp, grp, flags); - return; - } else - free(newdp); - } else { - dp = newdp; - dp->dp_left = NULL; - *dpp = dp; - } - if (grp) { - - /* - * Hang all of the host(s) off of the directory point. - */ - do { - hp = get_ht(); - if (flags & OP_KERB) - hp->ht_flag |= DP_KERB; - if (flags & OP_NORESMNT) - hp->ht_flag |= DP_NORESMNT; - hp->ht_grp = grp; - hp->ht_next = dp->dp_hosts; - dp->dp_hosts = hp; - grp = grp->gr_next; - } while (grp); - } else { - dp->dp_flag |= DP_DEFSET; - if (flags & OP_KERB) - dp->dp_flag |= DP_KERB; - if (flags & OP_NORESMNT) - dp->dp_flag |= DP_NORESMNT; - } -} - -/* - * Search for a dirpath on the export point. - */ -static struct dirlist * -dirp_search(dp, dirp) - struct dirlist *dp; - char *dirp; -{ - int cmp; - - if (dp) { - cmp = strcmp(dp->dp_dirp, dirp); - if (cmp > 0) - return (dirp_search(dp->dp_left, dirp)); - else if (cmp < 0) - return (dirp_search(dp->dp_right, dirp)); - else - return (dp); - } - return (dp); -} - -/* - * Some helper functions for netmasks. They all assume masks in network - * order (big endian). - */ -static int -bitcmp(void *dst, void *src, int bitlen) -{ - int i; - u_int8_t *p1 = dst, *p2 = src; - u_int8_t bitmask; - int bytelen, bitsleft; - - bytelen = bitlen / 8; - bitsleft = bitlen % 8; - - if (debug) { - printf("comparing:\n"); - for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) - printf("%02x", p1[i]); - printf("\n"); - for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) - printf("%02x", p2[i]); - printf("\n"); - } - - for (i = 0; i < bytelen; i++) { - if (*p1 != *p2) - return 1; - p1++; - p2++; - } - - for (i = 0; i < bitsleft; i++) { - bitmask = 1 << (7 - i); - if ((*p1 & bitmask) != (*p2 & bitmask)) - return 1; - } - - return 0; -} - -static int -netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen) -{ - void *src, *dst; - - if (s1->sa_family != s2->sa_family) - return 1; - - switch (s1->sa_family) { - case AF_INET: - src = &((struct sockaddr_in *)s1)->sin_addr; - dst = &((struct sockaddr_in *)s2)->sin_addr; - if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8) - return 1; - break; - case AF_INET6: - src = &((struct sockaddr_in6 *)s1)->sin6_addr; - dst = &((struct sockaddr_in6 *)s2)->sin6_addr; - if (((struct sockaddr_in6 *)s1)->sin6_scope_id != - ((struct sockaddr_in6 *)s2)->sin6_scope_id) - return 1; - if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8) - return 1; - break; - default: - return 1; - } - - return bitcmp(src, dst, bitlen); -} - -static int -allones(struct sockaddr_storage *ssp, int bitlen) -{ - u_int8_t *p; - int bytelen, bitsleft, i; - int zerolen; - - switch (ssp->ss_family) { - case AF_INET: - p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr; - zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr); - break; - case AF_INET6: - p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr; - zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr); - break; - default: - return -1; - } - - memset(p, 0, zerolen); - - bytelen = bitlen / 8; - bitsleft = bitlen % 8; - - if (bytelen > zerolen) - return -1; - - for (i = 0; i < bytelen; i++) - *p++ = 0xff; - - for (i = 0; i < bitsleft; i++) - *p |= 1 << (7 - i); - - return 0; -} - -static int -countones(struct sockaddr *sa) -{ - void *mask; - int i, bits = 0, bytelen; - u_int8_t *p; - - switch (sa->sa_family) { - case AF_INET: - mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; - bytelen = 4; - break; - case AF_INET6: - mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; - bytelen = 16; - break; - default: - return 0; - } - - p = mask; - - for (i = 0; i < bytelen; i++, p++) { - if (*p != 0xff) { - for (bits = 0; bits < 8; bits++) { - if (!(*p & (1 << (7 - bits)))) - break; - } - break; - } - } - - return (i * 8 + bits); -} - -static int -sacmp(struct sockaddr *sa1, struct sockaddr *sa2) -{ - void *p1, *p2; - int len; - - if (sa1->sa_family != sa2->sa_family) - return 1; - - switch (sa1->sa_family) { - case AF_INET: - p1 = &((struct sockaddr_in *)sa1)->sin_addr; - p2 = &((struct sockaddr_in *)sa2)->sin_addr; - len = 4; - break; - case AF_INET6: - p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; - p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; - len = 16; - if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != - ((struct sockaddr_in6 *)sa2)->sin6_scope_id) - return 1; - break; - default: - return 1; - } - - return memcmp(p1, p2, len); -} - -/* - * Scan for a host match in a directory tree. - */ -static int -chk_host(dp, saddr, defsetp, hostsetp) - struct dirlist *dp; - struct sockaddr *saddr; - int *defsetp; - int *hostsetp; -{ - struct hostlist *hp; - struct grouplist *grp; - struct addrinfo *ai; - - if (dp) { - if (dp->dp_flag & DP_DEFSET) - *defsetp = dp->dp_flag; - hp = dp->dp_hosts; - while (hp) { - grp = hp->ht_grp; - switch (grp->gr_type) { - case GT_HOST: - ai = grp->gr_ptr.gt_addrinfo; - for (; ai; ai = ai->ai_next) { - if (!sacmp(ai->ai_addr, saddr)) { - *hostsetp = - (hp->ht_flag | DP_HOSTSET); - return (1); - } - } - break; - case GT_NET: - if (!netpartcmp(saddr, - (struct sockaddr *) - &grp->gr_ptr.gt_net.nt_net, - grp->gr_ptr.gt_net.nt_len)) { - *hostsetp = (hp->ht_flag | DP_HOSTSET); - return (1); - } - break; - }; - hp = hp->ht_next; - } - } - return (0); -} - -/* - * Scan tree for a host that matches the address. - */ -static int -scan_tree(dp, saddr) - struct dirlist *dp; - struct sockaddr *saddr; -{ - int defset, hostset; - - if (dp) { - if (scan_tree(dp->dp_left, saddr)) - return (1); - if (chk_host(dp, saddr, &defset, &hostset)) - return (1); - if (scan_tree(dp->dp_right, saddr)) - return (1); - } - return (0); -} - -/* - * Traverse the dirlist tree and free it up. - */ -static void -free_dir(dp) - struct dirlist *dp; -{ - - if (dp) { - free_dir(dp->dp_left); - free_dir(dp->dp_right); - free_host(dp->dp_hosts); - free(dp); - } -} - -/* - * Parse the option string and update fields. - * Option arguments may either be -