Home | History | Annotate | Line # | Download | only in sh
      1 # $NetBSD: t_redircloexec.sh,v 1.5 2017/05/27 13:11:50 kre Exp $
      2 #
      3 # Copyright (c) 2016 The NetBSD Foundation, Inc.
      4 # All rights reserved.
      5 #
      6 # This code is derived from software contributed to The NetBSD Foundation
      7 # by Christos Zoulas.
      8 #
      9 # Redistribution and use in source and binary forms, with or without
     10 # modification, are permitted provided that the following conditions
     11 # are met:
     12 # 1. Redistributions of source code must retain the above copyright
     13 #    notice, this list of conditions and the following disclaimer.
     14 # 2. Redistributions in binary form must reproduce the above copyright
     15 #    notice, this list of conditions and the following disclaimer in the
     16 #    documentation and/or other materials provided with the distribution.
     17 #
     18 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28 # POSSIBILITY OF SUCH DAMAGE.
     29 #
     30 # the implementation of "sh" to test
     31 : ${TEST_SH:="/bin/sh"}
     32 
     33 mkhelper() {
     34 	name=$1
     35 	fd=$2
     36 	shift 2
     37 
     38 	echo "$@" > ./"${name}1"
     39 	echo "echo ${name}2" ">&${fd}" > ./"${name}2"
     40 }
     41 
     42 cleanhelper() {
     43 	# not really needed, atf cleans up...
     44 	rm -f ./"${1}1" ./"${1}2" out
     45 }
     46 
     47 atf_test_case exec_redir_closed
     48 exec_redir_closed_head() {
     49 	atf_set "descr" "Tests that redirections created by exec are closed on exec"
     50 }
     51 exec_redir_closed_body() {
     52 
     53 	[ -n "${POSIXLY_CORRECT+set}" ] && atf_skip "tests non-posix behaviour"
     54 
     55 	mkhelper exec 6 \
     56 		"exec 6> out; echo exec1 >&6; ${TEST_SH} exec2; exec 6>&-"
     57 
     58 	atf_check -s exit:0 -o empty -e not-empty ${TEST_SH} ./exec1
     59 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -e ./exec1
     60 
     61 	mkhelper exec 9 \
     62 		"exec 9> out; echo exec1 >&9; ${TEST_SH} exec2"
     63 
     64 	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} ./exec1
     65 
     66 	mkhelper exec 8 \
     67 		"exec 8> out; printf OK; echo exec1 >&8;" \
     68 		"printf OK; ${TEST_SH} exec2; printf ERR"
     69 
     70 	atf_check -s not-exit:0 -o match:OKOK -o not-match:ERR -e not-empty \
     71 		${TEST_SH} -e ./exec1
     72 
     73 	mkhelper exec 7 \
     74 		"exec 7> out; printf OK; echo exec1 >&7;" \
     75 		"printf OK; ${TEST_SH} exec2 || printf ERR"
     76 
     77 	atf_check -s exit:0 -o match:OKOKERR -e not-empty \
     78 		${TEST_SH} ./exec1
     79 
     80 	cleanhelper exec
     81 }
     82 
     83 atf_test_case exec_redir_open
     84 exec_redir_open_head() {
     85 	atf_set "descr" "Tests that redirections created by exec can remain open"
     86 }
     87 exec_redir_open_body() {
     88 
     89 	mkhelper exec 6 \
     90 		"exec 6> out 6>&6; echo exec1 >&6; ${TEST_SH} exec2; exec 6>&-"
     91 
     92 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
     93 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -e ./exec1
     94 
     95 	mkhelper exec 9 \
     96 		"exec 9> out ; echo exec1 >&9; ${TEST_SH} exec2 9>&9"
     97 
     98 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
     99 
    100 	mkhelper exec 8 \
    101 		"exec 8> out; printf OK; exec 8>&8; echo exec1 >&8;" \
    102 		"printf OK; ${TEST_SH} exec2; printf OK"
    103 
    104 	atf_check -s exit:0 -o match:OKOKOK -e empty \
    105 		${TEST_SH} -e ./exec1
    106 
    107 	mkhelper exec 7 \
    108 		"exec 7> out; printf OK; echo exec1 >&7;" \
    109 		"printf OK; ${TEST_SH} 7>&7 exec2; printf OK"
    110 
    111 	atf_check -s exit:0 -o match:OKOKOK -e empty \
    112 		${TEST_SH} -e ./exec1
    113 
    114 	cleanhelper exec
    115 }
    116 
    117 atf_test_case loop_redir_open
    118 loop_redir_open_head() {
    119 	atf_set "descr" "Tests that redirections in loops don't close on exec"
    120 }
    121 loop_redir_open_body() {
    122 	mkhelper for 3 "for x in x; do ${TEST_SH} ./for2; done 3>out"
    123 	atf_check -s exit:0 \
    124 		-o empty \
    125 		-e empty \
    126 		${TEST_SH} ./for1
    127 	cleanhelper for
    128 }
    129 
    130 atf_test_case compound_redir_open
    131 compound_redir_open_head() {
    132 	atf_set "descr" "Tests that redirections in compound statements don't close on exec"
    133 }
    134 compound_redir_open_body() {
    135 	mkhelper comp 3 "{ ${TEST_SH} ./comp2; } 3>out"
    136 	atf_check -s exit:0 \
    137 		-o empty \
    138 		-e empty \
    139 		${TEST_SH} ./comp1
    140 	cleanhelper comp
    141 }
    142 
    143 atf_test_case simple_redir_open
    144 simple_redir_open_head() {
    145 	atf_set "descr" "Tests that redirections in simple commands don't close on exec"
    146 }
    147 simple_redir_open_body() {
    148 	mkhelper simp 4 "${TEST_SH} ./simp2 4>out"
    149 	atf_check -s exit:0 \
    150 		-o empty \
    151 		-e empty \
    152 		${TEST_SH} ./simp1
    153 	cleanhelper simp
    154 }
    155 
    156 atf_test_case subshell_redir_open
    157 subshell_redir_open_head() {
    158 	atf_set "descr" "Tests that redirections on subshells don't close on exec"
    159 }
    160 subshell_redir_open_body() {
    161 	mkhelper comp 5 "( ${TEST_SH} ./comp2; ${TEST_SH} ./comp2 ) 5>out"
    162 	atf_check -s exit:0 \
    163 		-o empty \
    164 		-e empty \
    165 		${TEST_SH} ./comp1
    166 	cleanhelper comp
    167 }
    168 
    169 atf_test_case posix_exec_redir
    170 posix_exec_redir_head() {
    171 	atf_set "descr" "Tests that redirections created by exec" \
    172 		" in posix mode  are not closed on exec"
    173 }
    174 posix_exec_redir_body() {
    175 
    176 	# This test mostly just expects the opposite results than
    177 	# exec_redir_closed ...
    178 
    179 	# First work out how to get shell into posix mode
    180 	POSIX=
    181 
    182 	# This should succeed only if "set -o posix" succeeds.
    183 	# If it fails, whether it fails and exits the shell, or
    184 	# just returns a "false" from set (exit != 0), with or
    185 	# without errs on stderr, should not matter
    186 
    187 	if ${TEST_SH} -c "set -o posix && exit 0 || exit 1" 2>/dev/null
    188 	then
    189 		# If we have this method, use it, as we can expect
    190 		# this really should mean the shell is in posix mode.
    191 
    192 		POSIX='set -o posix;'
    193 
    194 	else
    195 		# This one is just a guess, and there is no assurance
    196 		# that it will do anything at all.  What's more, since
    197 		# we do not know what the shell being tested does
    198 		# differently in posix and non-posix modes, if it
    199 		# even has that concept, there's nothing we can test
    200 		# to find out.
    201 
    202 		# A shell that always operates in posix mode (at least
    203 		# with regard to redirects on exec and close-on-exec
    204 		# should pass this test, in any case.
    205 
    206 		POSIXLY_CORRECT=true ; export POSIXLY_CORRECT
    207 
    208 	fi
    209 
    210 	mkhelper exec 6 \
    211 	    "${POSIX} exec 6> out; echo exec1 >&6; ${TEST_SH} exec2; exec 6>&-"
    212 
    213 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
    214 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} -e ./exec1
    215 
    216 	mkhelper exec 9 \
    217 		"${POSIX} exec 9> out; echo exec1 >&9; ${TEST_SH} exec2"
    218 
    219 	atf_check -s exit:0 -o empty -e empty ${TEST_SH} ./exec1
    220 
    221 	mkhelper exec 8 \
    222 		"${POSIX}"				\
    223 		"exec 8> out; printf OK; echo exec1 >&8;" \
    224 		"printf OK; ${TEST_SH} exec2; printf GOOD"
    225 
    226 	atf_check -s exit:0 -o match:OKOKGOOD -e empty \
    227 		${TEST_SH} -e ./exec1
    228 
    229 	mkhelper exec 7 \
    230 		"${POSIX}"				\
    231 		"exec 7> out; printf OK; echo exec1 >&7;" \
    232 		"printf OK; ${TEST_SH} exec2 || printf ERR"
    233 
    234 	atf_check -s exit:0 -o match:OKOK -o not-match:ERR -e empty \
    235 		${TEST_SH} ./exec1
    236 
    237 	cleanhelper exec
    238 }
    239 
    240 atf_init_test_cases() {
    241 	atf_add_test_case exec_redir_closed
    242 	atf_add_test_case exec_redir_open
    243 	atf_add_test_case loop_redir_open
    244 	atf_add_test_case compound_redir_open
    245 	atf_add_test_case simple_redir_open
    246 	atf_add_test_case subshell_redir_open
    247 	atf_add_test_case posix_exec_redir
    248 }
    249