18462SApril.Chin@Sun.COM########################################################################
28462SApril.Chin@Sun.COM#                                                                      #
38462SApril.Chin@Sun.COM#               This software is part of the ast package               #
4*10898Sroland.mainz@nrubsig.org#          Copyright (c) 1982-2009 AT&T Intellectual Property          #
58462SApril.Chin@Sun.COM#                      and is licensed under the                       #
68462SApril.Chin@Sun.COM#                  Common Public License, Version 1.0                  #
78462SApril.Chin@Sun.COM#                    by AT&T Intellectual Property                     #
88462SApril.Chin@Sun.COM#                                                                      #
98462SApril.Chin@Sun.COM#                A copy of the License is available at                 #
108462SApril.Chin@Sun.COM#            http://www.opensource.org/licenses/cpl1.0.txt             #
118462SApril.Chin@Sun.COM#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
128462SApril.Chin@Sun.COM#                                                                      #
138462SApril.Chin@Sun.COM#              Information and Software Systems Research               #
148462SApril.Chin@Sun.COM#                            AT&T Research                             #
158462SApril.Chin@Sun.COM#                           Florham Park NJ                            #
168462SApril.Chin@Sun.COM#                                                                      #
178462SApril.Chin@Sun.COM#                  David Korn <dgk@research.att.com>                   #
188462SApril.Chin@Sun.COM#                                                                      #
198462SApril.Chin@Sun.COM########################################################################
208462SApril.Chin@Sun.COMfunction err_exit
218462SApril.Chin@Sun.COM{
228462SApril.Chin@Sun.COM	print -u2 -n "\t"
238462SApril.Chin@Sun.COM	print -u2 -r ${Command}[$1]: "${@:2}"
248462SApril.Chin@Sun.COM	(( Errors++ ))
258462SApril.Chin@Sun.COM}
268462SApril.Chin@Sun.COMalias err_exit='err_exit $LINENO'
278462SApril.Chin@Sun.COM
288462SApril.Chin@Sun.COMCommand=${0##*/}
298462SApril.Chin@Sun.COMinteger Errors=0
308462SApril.Chin@Sun.COM
31*10898Sroland.mainz@nrubsig.orgtmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32*10898Sroland.mainz@nrubsig.orgtrap "cd /; rm -rf $tmp" EXIT
33*10898Sroland.mainz@nrubsig.org
34*10898Sroland.mainz@nrubsig.orgcd $tmp || err_exit "cd $tmp failed"
35*10898Sroland.mainz@nrubsig.org
36*10898Sroland.mainz@nrubsig.org(
37*10898Sroland.mainz@nrubsig.org	set --pipefail
38*10898Sroland.mainz@nrubsig.org	{
39*10898Sroland.mainz@nrubsig.org		$SHELL 2> out2 <<- \EOF
40*10898Sroland.mainz@nrubsig.org			g=false
41*10898Sroland.mainz@nrubsig.org			trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
42*10898Sroland.mainz@nrubsig.org			while :
43*10898Sroland.mainz@nrubsig.org			do 	print hello
44*10898Sroland.mainz@nrubsig.org			done
45*10898Sroland.mainz@nrubsig.org		EOF
46*10898Sroland.mainz@nrubsig.org	} | head > /dev/null
47*10898Sroland.mainz@nrubsig.org	(( $? == 0)) ||   err_exit "SIGPIPE with wrong error code $?"
48*10898Sroland.mainz@nrubsig.org	[[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
49*10898Sroland.mainz@nrubsig.org) &
50*10898Sroland.mainz@nrubsig.orgcop=$!
51*10898Sroland.mainz@nrubsig.org{ sleep 4; kill $cop; } 2>/dev/null &
52*10898Sroland.mainz@nrubsig.orgspy=$!
53*10898Sroland.mainz@nrubsig.orgif	wait $cop 2>/dev/null
54*10898Sroland.mainz@nrubsig.orgthen	kill $spy 2>/dev/null
55*10898Sroland.mainz@nrubsig.orgelse	err_exit "pipe with --pipefail PIPE trap hangs"
56*10898Sroland.mainz@nrubsig.orgfi
57*10898Sroland.mainz@nrubsig.orgwait
58*10898Sroland.mainz@nrubsig.orgrm -f out2
598462SApril.Chin@Sun.COM
608462SApril.Chin@Sun.COM[[ $( trap 'print -n got_child' SIGCHLD
618462SApril.Chin@Sun.COM	sleep 2 &
628462SApril.Chin@Sun.COM	for	((i=0; i < 4; i++))
63*10898Sroland.mainz@nrubsig.org	do 	sleep .75
648462SApril.Chin@Sun.COM		print -n $i
658462SApril.Chin@Sun.COM	done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
668462SApril.Chin@Sun.COM
678462SApril.Chin@Sun.COM# begin standalone SIGINT test generation
688462SApril.Chin@Sun.COM
698462SApril.Chin@Sun.COMcat > tst <<'!'
708462SApril.Chin@Sun.COM# shell trap tests
718462SApril.Chin@Sun.COM#
728462SApril.Chin@Sun.COM#    tst  control script that calls tst-1, must be run by ksh
738462SApril.Chin@Sun.COM#  tst-1  calls tst-2
748462SApril.Chin@Sun.COM#  tst-2  calls tst-3
758462SApril.Chin@Sun.COM#  tst-3  defaults or handles and discards/propagates SIGINT
768462SApril.Chin@Sun.COM#
778462SApril.Chin@Sun.COM# initial -v option lists script entry and SIGINT delivery
788462SApril.Chin@Sun.COM#
798462SApril.Chin@Sun.COM# three test options
808462SApril.Chin@Sun.COM#
818462SApril.Chin@Sun.COM#     d call next script directly, otherwise via $SHELL -c
828462SApril.Chin@Sun.COM#     t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
83*10898Sroland.mainz@nrubsig.org#     x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
84*10898Sroland.mainz@nrubsig.org#     z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
858462SApril.Chin@Sun.COM#
868462SApril.Chin@Sun.COM# Usage: tst [-v] [-options] shell-to-test ...
878462SApril.Chin@Sun.COM
888462SApril.Chin@Sun.COM# "trap + sig" is an unadvertized extension for this test
898462SApril.Chin@Sun.COM# if run from nmake SIGINT is set to SIG_IGN
908462SApril.Chin@Sun.COM# this call sets it back to SIG_DFL
918462SApril.Chin@Sun.COM# semantics w.r.t. function scope must be worked out before
928462SApril.Chin@Sun.COM# making it public
938462SApril.Chin@Sun.COMtrap + INT
948462SApril.Chin@Sun.COM
958462SApril.Chin@Sun.COMset -o monitor
968462SApril.Chin@Sun.COM
978462SApril.Chin@Sun.COMfunction gen
988462SApril.Chin@Sun.COM{
998462SApril.Chin@Sun.COM	typeset o t x d
100*10898Sroland.mainz@nrubsig.org	for x in - x z
1018462SApril.Chin@Sun.COM	do	case $x in
1028462SApril.Chin@Sun.COM		[$1])	for t in - t
1038462SApril.Chin@Sun.COM			do	case $t in
1048462SApril.Chin@Sun.COM				[$1])	for d in - d
1058462SApril.Chin@Sun.COM					do	case $d in
1068462SApril.Chin@Sun.COM						[$1])	o="$o $x$t$d"
1078462SApril.Chin@Sun.COM						esac
1088462SApril.Chin@Sun.COM					done
1098462SApril.Chin@Sun.COM				esac
1108462SApril.Chin@Sun.COM			done
1118462SApril.Chin@Sun.COM		esac
1128462SApril.Chin@Sun.COM	done
1138462SApril.Chin@Sun.COM	echo '' $o
1148462SApril.Chin@Sun.COM}
1158462SApril.Chin@Sun.COM
1168462SApril.Chin@Sun.COMcase $1 in
1178462SApril.Chin@Sun.COM-v)	v=v; shift ;;
1188462SApril.Chin@Sun.COM-*v*)	v=v ;;
1198462SApril.Chin@Sun.COM*)	v= ;;
1208462SApril.Chin@Sun.COMesac
1218462SApril.Chin@Sun.COMcase $1 in
1228462SApril.Chin@Sun.COM*' '*)	o=$1; shift ;;
1238462SApril.Chin@Sun.COM-*)	o=$(gen $1); shift ;;
1248462SApril.Chin@Sun.COM*)	o=$(gen -txd) ;;
1258462SApril.Chin@Sun.COMesac
1268462SApril.Chin@Sun.COMcase $# in
1278462SApril.Chin@Sun.COM0)	set ksh bash ksh88 pdksh ash zsh ;;
1288462SApril.Chin@Sun.COMesac
1298462SApril.Chin@Sun.COMfor f in $o
1308462SApril.Chin@Sun.COMdo	case $# in
1318462SApril.Chin@Sun.COM	1)	;;
1328462SApril.Chin@Sun.COM	*)	echo ;;
1338462SApril.Chin@Sun.COM	esac
1348462SApril.Chin@Sun.COM	for sh
1358462SApril.Chin@Sun.COM	do	if	$sh -c 'exit 0' > /dev/null 2>&1
1368462SApril.Chin@Sun.COM		then	case $# in
1378462SApril.Chin@Sun.COM			1)	printf '%3s ' "$f" ;;
1388462SApril.Chin@Sun.COM			*)	printf '%16s %3s ' "$sh" "$f" ;;
1398462SApril.Chin@Sun.COM			esac
1408462SApril.Chin@Sun.COM			$sh tst-1 $v$f $sh > tst.out &
1418462SApril.Chin@Sun.COM			wait
1428462SApril.Chin@Sun.COM			echo $(cat tst.out)
1438462SApril.Chin@Sun.COM		fi
1448462SApril.Chin@Sun.COM	done
1458462SApril.Chin@Sun.COMdone
1468462SApril.Chin@Sun.COMcase $# in
1478462SApril.Chin@Sun.COM1)	;;
1488462SApril.Chin@Sun.COM*)	echo ;;
1498462SApril.Chin@Sun.COMesac
1508462SApril.Chin@Sun.COM!
1518462SApril.Chin@Sun.COMcat > tst-1 <<'!'
1528462SApril.Chin@Sun.COMexec 2>/dev/null
1538462SApril.Chin@Sun.COMcase $1 in
1548462SApril.Chin@Sun.COM*v*)	echo 1-main ;;
1558462SApril.Chin@Sun.COMesac
1568462SApril.Chin@Sun.COM{
1578462SApril.Chin@Sun.COM	sleep 2
1588462SApril.Chin@Sun.COM	case $1 in
1598462SApril.Chin@Sun.COM	*v*)	echo "SIGINT" ;;
1608462SApril.Chin@Sun.COM	esac
1618462SApril.Chin@Sun.COM	kill -s INT 0
1628462SApril.Chin@Sun.COM} &
1638462SApril.Chin@Sun.COMcase $1 in
1648462SApril.Chin@Sun.COM*t*)	trap '
1658462SApril.Chin@Sun.COM		echo 1-intr
1668462SApril.Chin@Sun.COM		trap - INT
1678462SApril.Chin@Sun.COM		# omitting the self kill exposes shells that deliver
1688462SApril.Chin@Sun.COM		# the SIGINT trap but exit 0 for -xt
1698462SApril.Chin@Sun.COM		# kill -s INT $$
1708462SApril.Chin@Sun.COM	' INT
1718462SApril.Chin@Sun.COM	;;
1728462SApril.Chin@Sun.COMesac
1738462SApril.Chin@Sun.COMcase $1 in
1748462SApril.Chin@Sun.COM*d*)	tst-2 $1 $2; status=$? ;;
1758462SApril.Chin@Sun.COM*)	$2 -c "tst-2 $1 $2"; status=$? ;;
1768462SApril.Chin@Sun.COMesac
1778462SApril.Chin@Sun.COMprintf '1-%04d\n' $status
1788462SApril.Chin@Sun.COMsleep 2
1798462SApril.Chin@Sun.COM!
1808462SApril.Chin@Sun.COMcat > tst-2 <<'!'
1818462SApril.Chin@Sun.COMcase $1 in
182*10898Sroland.mainz@nrubsig.org*z*)	trap '
183*10898Sroland.mainz@nrubsig.org		echo 2-intr
184*10898Sroland.mainz@nrubsig.org		exit 0
185*10898Sroland.mainz@nrubsig.org	' INT
186*10898Sroland.mainz@nrubsig.org	;;
1878462SApril.Chin@Sun.COM*x*)	trap '
1888462SApril.Chin@Sun.COM		echo 2-intr
1898462SApril.Chin@Sun.COM		exit
1908462SApril.Chin@Sun.COM	' INT
1918462SApril.Chin@Sun.COM	;;
1928462SApril.Chin@Sun.COM*t*)	trap '
1938462SApril.Chin@Sun.COM		echo 2-intr
1948462SApril.Chin@Sun.COM		trap - INT
1958462SApril.Chin@Sun.COM		kill -s INT $$
1968462SApril.Chin@Sun.COM	' INT
1978462SApril.Chin@Sun.COM	;;
1988462SApril.Chin@Sun.COMesac
1998462SApril.Chin@Sun.COMcase $1 in
2008462SApril.Chin@Sun.COM*v*)	echo 2-main ;;
2018462SApril.Chin@Sun.COMesac
2028462SApril.Chin@Sun.COMcase $1 in
2038462SApril.Chin@Sun.COM*d*)	tst-3 $1 $2; status=$? ;;
2048462SApril.Chin@Sun.COM*)	$2 -c "tst-3 $1 $2"; status=$? ;;
2058462SApril.Chin@Sun.COMesac
2068462SApril.Chin@Sun.COMprintf '2-%04d\n' $status
2078462SApril.Chin@Sun.COM!
2088462SApril.Chin@Sun.COMcat > tst-3 <<'!'
2098462SApril.Chin@Sun.COMcase $1 in
210*10898Sroland.mainz@nrubsig.org*[xz]*)	trap '
2118462SApril.Chin@Sun.COM		sleep 2
2128462SApril.Chin@Sun.COM		echo 3-intr
2138462SApril.Chin@Sun.COM		exit 0
2148462SApril.Chin@Sun.COM	' INT
2158462SApril.Chin@Sun.COM	;;
2168462SApril.Chin@Sun.COM*)	trap '
2178462SApril.Chin@Sun.COM		sleep 2
2188462SApril.Chin@Sun.COM		echo 3-intr
2198462SApril.Chin@Sun.COM		trap - INT
2208462SApril.Chin@Sun.COM		kill -s INT $$
2218462SApril.Chin@Sun.COM	' INT
2228462SApril.Chin@Sun.COM	;;
2238462SApril.Chin@Sun.COMesac
2248462SApril.Chin@Sun.COMcase $1 in
2258462SApril.Chin@Sun.COM*v*)	echo 3-main ;;
2268462SApril.Chin@Sun.COMesac
2278462SApril.Chin@Sun.COMsleep 5
2288462SApril.Chin@Sun.COMprintf '3-%04d\n' $?
2298462SApril.Chin@Sun.COM!
2308462SApril.Chin@Sun.COMchmod +x tst tst-?
2318462SApril.Chin@Sun.COM
2328462SApril.Chin@Sun.COM# end standalone test generation
2338462SApril.Chin@Sun.COM
2348462SApril.Chin@Sun.COMexport PATH=$PATH:
2358462SApril.Chin@Sun.COMtypeset -A expected
2368462SApril.Chin@Sun.COMexpected[---]="3-intr"
2378462SApril.Chin@Sun.COMexpected[--d]="3-intr"
2388462SApril.Chin@Sun.COMexpected[-t-]="3-intr 2-intr 1-intr 1-0258"
2398462SApril.Chin@Sun.COMexpected[-td]="3-intr 2-intr 1-intr 1-0258"
240*10898Sroland.mainz@nrubsig.orgexpected[x--]="3-intr 2-intr"
241*10898Sroland.mainz@nrubsig.orgexpected[x-d]="3-intr 2-intr"
242*10898Sroland.mainz@nrubsig.orgexpected[xt-]="3-intr 2-intr 1-intr 1-0258"
243*10898Sroland.mainz@nrubsig.orgexpected[xtd]="3-intr 2-intr 1-intr 1-0258"
244*10898Sroland.mainz@nrubsig.orgexpected[z--]="3-intr 2-intr 1-0000"
245*10898Sroland.mainz@nrubsig.orgexpected[z-d]="3-intr 2-intr 1-0000"
246*10898Sroland.mainz@nrubsig.orgexpected[zt-]="3-intr 2-intr 1-intr 1-0000"
247*10898Sroland.mainz@nrubsig.orgexpected[ztd]="3-intr 2-intr 1-intr 1-0000"
2488462SApril.Chin@Sun.COM
2498462SApril.Chin@Sun.COMtst $SHELL > tst.got
2508462SApril.Chin@Sun.COM
2518462SApril.Chin@Sun.COMwhile	read ops out
2528462SApril.Chin@Sun.COMdo	[[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
2538462SApril.Chin@Sun.COMdone < tst.got
2548462SApril.Chin@Sun.COM
2558462SApril.Chin@Sun.COMfloat s=$SECONDS
256*10898Sroland.mainz@nrubsig.org[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
2578462SApril.Chin@Sun.COM(( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
2588462SApril.Chin@Sun.COM((s = SECONDS))
259*10898Sroland.mainz@nrubsig.org[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
2608462SApril.Chin@Sun.COM(( SECONDS-s < 4 )) && err_exit 'parent completes early'
261*10898Sroland.mainz@nrubsig.org
262*10898Sroland.mainz@nrubsig.orgunset n s t
263*10898Sroland.mainz@nrubsig.orgfor s in $(kill -l)
264*10898Sroland.mainz@nrubsig.orgdo	if	! n=$(kill -l $s 2>/dev/null)
265*10898Sroland.mainz@nrubsig.org	then	err_exit "'kill -l $s' failed"
266*10898Sroland.mainz@nrubsig.org		continue
267*10898Sroland.mainz@nrubsig.org	fi
268*10898Sroland.mainz@nrubsig.org	if	! t=$(kill -l $n 2>/dev/null)
269*10898Sroland.mainz@nrubsig.org	then	err_exit "'kill -l $n' failed"
270*10898Sroland.mainz@nrubsig.org		continue
271*10898Sroland.mainz@nrubsig.org	fi
272*10898Sroland.mainz@nrubsig.org	if	[[ $s == ?(SIG)$t ]]
273*10898Sroland.mainz@nrubsig.org	then	continue
274*10898Sroland.mainz@nrubsig.org	fi
275*10898Sroland.mainz@nrubsig.org	if	! m=$(kill -l $t 2>/dev/null)
276*10898Sroland.mainz@nrubsig.org	then	err_exit "'kill -l $t' failed"
277*10898Sroland.mainz@nrubsig.org		continue
278*10898Sroland.mainz@nrubsig.org	fi
279*10898Sroland.mainz@nrubsig.org	if	[[ $m == $n ]]
280*10898Sroland.mainz@nrubsig.org	then	continue
281*10898Sroland.mainz@nrubsig.org	fi
282*10898Sroland.mainz@nrubsig.org	err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
283*10898Sroland.mainz@nrubsig.orgdone
284*10898Sroland.mainz@nrubsig.orgyes=$(whence -p yes)
285*10898Sroland.mainz@nrubsig.org[[ $yes ]] && for exp in TERM VTALRM PIPE
286*10898Sroland.mainz@nrubsig.orgdo { $SHELL <<- EOF
287*10898Sroland.mainz@nrubsig.org		foo() { return 0; }
288*10898Sroland.mainz@nrubsig.org		trap foo EXIT
289*10898Sroland.mainz@nrubsig.org		{ sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
290*10898Sroland.mainz@nrubsig.org		$yes | while read yes; do
291*10898Sroland.mainz@nrubsig.org		        (/bin/date; sleep .1)
292*10898Sroland.mainz@nrubsig.org		done > /dev/null
293*10898Sroland.mainz@nrubsig.org	EOF
294*10898Sroland.mainz@nrubsig.org    } 2>> /dev/null
295*10898Sroland.mainz@nrubsig.org    got=$(kill -l $?)
296*10898Sroland.mainz@nrubsig.org    [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
297*10898Sroland.mainz@nrubsig.orgdone
298*10898Sroland.mainz@nrubsig.org
299*10898Sroland.mainz@nrubsig.orgSECONDS=0
300*10898Sroland.mainz@nrubsig.org$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished' > $tmp/sig
301*10898Sroland.mainz@nrubsig.org(( $?==3)) || err_exit "wrong exit status expecting 3 got $?"
302*10898Sroland.mainz@nrubsig.orgx=$(<$tmp/sig)
303*10898Sroland.mainz@nrubsig.org[[ $x == done ]] || err_exit "wrong result - execting done got $x"
304*10898Sroland.mainz@nrubsig.org(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2"
305*10898Sroland.mainz@nrubsig.org
306*10898Sroland.mainz@nrubsig.orgSECONDS=0
307*10898Sroland.mainz@nrubsig.org{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit" EXIT; (sleep 5);print finished' > $tmp/sig ;} 2> /dev/null
308*10898Sroland.mainz@nrubsig.org[[ $(kill -l $?) == TERM ]] || err_exit "wrong exit status expecting TERM got $(kill -l $?)"
309*10898Sroland.mainz@nrubsig.orgx=$(<$tmp/sig)
310*10898Sroland.mainz@nrubsig.org[[ $x == done ]] || err_exit "wrong result - execting done got $x"
311*10898Sroland.mainz@nrubsig.org(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2"
312*10898Sroland.mainz@nrubsig.org
313*10898Sroland.mainz@nrubsig.orgSECONDS=0
314*10898Sroland.mainz@nrubsig.orgx=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished')
315*10898Sroland.mainz@nrubsig.org(( $?==3)) || err_exit "wrong exit status expecting 3 got $?"
316*10898Sroland.mainz@nrubsig.org[[ $x == done ]] || err_exit "wrong result - execting done got $x"
317*10898Sroland.mainz@nrubsig.org(( SECONDS < 4 )) && err_exit "took $SECONDS seconds, expecting around 5"
318*10898Sroland.mainz@nrubsig.org
319*10898Sroland.mainz@nrubsig.orgtrap '' SIGBUS
320*10898Sroland.mainz@nrubsig.org[[ $($SHELL -c 'trap date SIGBUS;trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
321*10898Sroland.mainz@nrubsig.orgtrap -- - SIGBUS
322*10898Sroland.mainz@nrubsig.org
3238462SApril.Chin@Sun.COMexit $((Errors))
324