1*8462SApril.Chin@Sun.COM########################################################################
2*8462SApril.Chin@Sun.COM#                                                                      #
3*8462SApril.Chin@Sun.COM#               This software is part of the ast package               #
4*8462SApril.Chin@Sun.COM#          Copyright (c) 1982-2008 AT&T Intellectual Property          #
5*8462SApril.Chin@Sun.COM#                      and is licensed under the                       #
6*8462SApril.Chin@Sun.COM#                  Common Public License, Version 1.0                  #
7*8462SApril.Chin@Sun.COM#                    by AT&T Intellectual Property                     #
8*8462SApril.Chin@Sun.COM#                                                                      #
9*8462SApril.Chin@Sun.COM#                A copy of the License is available at                 #
10*8462SApril.Chin@Sun.COM#            http://www.opensource.org/licenses/cpl1.0.txt             #
11*8462SApril.Chin@Sun.COM#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12*8462SApril.Chin@Sun.COM#                                                                      #
13*8462SApril.Chin@Sun.COM#              Information and Software Systems Research               #
14*8462SApril.Chin@Sun.COM#                            AT&T Research                             #
15*8462SApril.Chin@Sun.COM#                           Florham Park NJ                            #
16*8462SApril.Chin@Sun.COM#                                                                      #
17*8462SApril.Chin@Sun.COM#                  David Korn <dgk@research.att.com>                   #
18*8462SApril.Chin@Sun.COM#                                                                      #
19*8462SApril.Chin@Sun.COM########################################################################
20*8462SApril.Chin@Sun.COMfunction err_exit
21*8462SApril.Chin@Sun.COM{
22*8462SApril.Chin@Sun.COM	print -u2 -n "\t"
23*8462SApril.Chin@Sun.COM	print -u2 -r ${Command}[$1]: "${@:2}"
24*8462SApril.Chin@Sun.COM	(( Errors++ ))
25*8462SApril.Chin@Sun.COM}
26*8462SApril.Chin@Sun.COMalias err_exit='err_exit $LINENO'
27*8462SApril.Chin@Sun.COM
28*8462SApril.Chin@Sun.COMCommand=${0##*/}
29*8462SApril.Chin@Sun.COMinteger Errors=0
30*8462SApril.Chin@Sun.COM
31*8462SApril.Chin@Sun.COMmkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
32*8462SApril.Chin@Sun.COMtrap 'cd /; rm -rf /tmp/ksh$$' EXIT
33*8462SApril.Chin@Sun.COMcd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
34*8462SApril.Chin@Sun.COM
35*8462SApril.Chin@Sun.COM[[ $( trap 'print -n got_child' SIGCHLD
36*8462SApril.Chin@Sun.COM	sleep 2 &
37*8462SApril.Chin@Sun.COM	for	((i=0; i < 4; i++))
38*8462SApril.Chin@Sun.COM	do 	sleep .9
39*8462SApril.Chin@Sun.COM		print -n $i
40*8462SApril.Chin@Sun.COM	done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
41*8462SApril.Chin@Sun.COM
42*8462SApril.Chin@Sun.COM# begin standalone SIGINT test generation
43*8462SApril.Chin@Sun.COM
44*8462SApril.Chin@Sun.COMcat > tst <<'!'
45*8462SApril.Chin@Sun.COM# shell trap tests
46*8462SApril.Chin@Sun.COM#
47*8462SApril.Chin@Sun.COM#    tst  control script that calls tst-1, must be run by ksh
48*8462SApril.Chin@Sun.COM#  tst-1  calls tst-2
49*8462SApril.Chin@Sun.COM#  tst-2  calls tst-3
50*8462SApril.Chin@Sun.COM#  tst-3  defaults or handles and discards/propagates SIGINT
51*8462SApril.Chin@Sun.COM#
52*8462SApril.Chin@Sun.COM# initial -v option lists script entry and SIGINT delivery
53*8462SApril.Chin@Sun.COM#
54*8462SApril.Chin@Sun.COM# three test options
55*8462SApril.Chin@Sun.COM#
56*8462SApril.Chin@Sun.COM#     d call next script directly, otherwise via $SHELL -c
57*8462SApril.Chin@Sun.COM#     t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
58*8462SApril.Chin@Sun.COM#     x trap, echo on SIGINT, and exit 0, otherwise SIGINT default
59*8462SApril.Chin@Sun.COM#
60*8462SApril.Chin@Sun.COM# Usage: tst [-v] [-options] shell-to-test ...
61*8462SApril.Chin@Sun.COM
62*8462SApril.Chin@Sun.COM# "trap + sig" is an unadvertized extension for this test
63*8462SApril.Chin@Sun.COM# if run from nmake SIGINT is set to SIG_IGN
64*8462SApril.Chin@Sun.COM# this call sets it back to SIG_DFL
65*8462SApril.Chin@Sun.COM# semantics w.r.t. function scope must be worked out before
66*8462SApril.Chin@Sun.COM# making it public
67*8462SApril.Chin@Sun.COMtrap + INT
68*8462SApril.Chin@Sun.COM
69*8462SApril.Chin@Sun.COMset -o monitor
70*8462SApril.Chin@Sun.COM
71*8462SApril.Chin@Sun.COMfunction gen
72*8462SApril.Chin@Sun.COM{
73*8462SApril.Chin@Sun.COM	typeset o t x d
74*8462SApril.Chin@Sun.COM	for x in - x
75*8462SApril.Chin@Sun.COM	do	case $x in
76*8462SApril.Chin@Sun.COM		[$1])	for t in - t
77*8462SApril.Chin@Sun.COM			do	case $t in
78*8462SApril.Chin@Sun.COM				[$1])	for d in - d
79*8462SApril.Chin@Sun.COM					do	case $d in
80*8462SApril.Chin@Sun.COM						[$1])	o="$o $x$t$d"
81*8462SApril.Chin@Sun.COM						esac
82*8462SApril.Chin@Sun.COM					done
83*8462SApril.Chin@Sun.COM				esac
84*8462SApril.Chin@Sun.COM			done
85*8462SApril.Chin@Sun.COM		esac
86*8462SApril.Chin@Sun.COM	done
87*8462SApril.Chin@Sun.COM	echo '' $o
88*8462SApril.Chin@Sun.COM}
89*8462SApril.Chin@Sun.COM
90*8462SApril.Chin@Sun.COMcase $1 in
91*8462SApril.Chin@Sun.COM-v)	v=v; shift ;;
92*8462SApril.Chin@Sun.COM-*v*)	v=v ;;
93*8462SApril.Chin@Sun.COM*)	v= ;;
94*8462SApril.Chin@Sun.COMesac
95*8462SApril.Chin@Sun.COMcase $1 in
96*8462SApril.Chin@Sun.COM*' '*)	o=$1; shift ;;
97*8462SApril.Chin@Sun.COM-*)	o=$(gen $1); shift ;;
98*8462SApril.Chin@Sun.COM*)	o=$(gen -txd) ;;
99*8462SApril.Chin@Sun.COMesac
100*8462SApril.Chin@Sun.COMcase $# in
101*8462SApril.Chin@Sun.COM0)	set ksh bash ksh88 pdksh ash zsh ;;
102*8462SApril.Chin@Sun.COMesac
103*8462SApril.Chin@Sun.COMfor f in $o
104*8462SApril.Chin@Sun.COMdo	case $# in
105*8462SApril.Chin@Sun.COM	1)	;;
106*8462SApril.Chin@Sun.COM	*)	echo ;;
107*8462SApril.Chin@Sun.COM	esac
108*8462SApril.Chin@Sun.COM	for sh
109*8462SApril.Chin@Sun.COM	do	if	$sh -c 'exit 0' > /dev/null 2>&1
110*8462SApril.Chin@Sun.COM		then	case $# in
111*8462SApril.Chin@Sun.COM			1)	printf '%3s ' "$f" ;;
112*8462SApril.Chin@Sun.COM			*)	printf '%16s %3s ' "$sh" "$f" ;;
113*8462SApril.Chin@Sun.COM			esac
114*8462SApril.Chin@Sun.COM			$sh tst-1 $v$f $sh > tst.out &
115*8462SApril.Chin@Sun.COM			wait
116*8462SApril.Chin@Sun.COM			echo $(cat tst.out)
117*8462SApril.Chin@Sun.COM		fi
118*8462SApril.Chin@Sun.COM	done
119*8462SApril.Chin@Sun.COMdone
120*8462SApril.Chin@Sun.COMcase $# in
121*8462SApril.Chin@Sun.COM1)	;;
122*8462SApril.Chin@Sun.COM*)	echo ;;
123*8462SApril.Chin@Sun.COMesac
124*8462SApril.Chin@Sun.COM!
125*8462SApril.Chin@Sun.COMcat > tst-1 <<'!'
126*8462SApril.Chin@Sun.COMexec 2>/dev/null
127*8462SApril.Chin@Sun.COMcase $1 in
128*8462SApril.Chin@Sun.COM*v*)	echo 1-main ;;
129*8462SApril.Chin@Sun.COMesac
130*8462SApril.Chin@Sun.COM{
131*8462SApril.Chin@Sun.COM	sleep 2
132*8462SApril.Chin@Sun.COM	case $1 in
133*8462SApril.Chin@Sun.COM	*v*)	echo "SIGINT" ;;
134*8462SApril.Chin@Sun.COM	esac
135*8462SApril.Chin@Sun.COM	kill -s INT 0
136*8462SApril.Chin@Sun.COM} &
137*8462SApril.Chin@Sun.COMcase $1 in
138*8462SApril.Chin@Sun.COM*t*)	trap '
139*8462SApril.Chin@Sun.COM		echo 1-intr
140*8462SApril.Chin@Sun.COM		trap - INT
141*8462SApril.Chin@Sun.COM		# omitting the self kill exposes shells that deliver
142*8462SApril.Chin@Sun.COM		# the SIGINT trap but exit 0 for -xt
143*8462SApril.Chin@Sun.COM		# kill -s INT $$
144*8462SApril.Chin@Sun.COM	' INT
145*8462SApril.Chin@Sun.COM	;;
146*8462SApril.Chin@Sun.COMesac
147*8462SApril.Chin@Sun.COMcase $1 in
148*8462SApril.Chin@Sun.COM*d*)	tst-2 $1 $2; status=$? ;;
149*8462SApril.Chin@Sun.COM*)	$2 -c "tst-2 $1 $2"; status=$? ;;
150*8462SApril.Chin@Sun.COMesac
151*8462SApril.Chin@Sun.COMprintf '1-%04d\n' $status
152*8462SApril.Chin@Sun.COMsleep 2
153*8462SApril.Chin@Sun.COM!
154*8462SApril.Chin@Sun.COMcat > tst-2 <<'!'
155*8462SApril.Chin@Sun.COMcase $1 in
156*8462SApril.Chin@Sun.COM*x*)	trap '
157*8462SApril.Chin@Sun.COM		echo 2-intr
158*8462SApril.Chin@Sun.COM		exit
159*8462SApril.Chin@Sun.COM	' INT
160*8462SApril.Chin@Sun.COM	;;
161*8462SApril.Chin@Sun.COM*t*)	trap '
162*8462SApril.Chin@Sun.COM		echo 2-intr
163*8462SApril.Chin@Sun.COM		trap - INT
164*8462SApril.Chin@Sun.COM		kill -s INT $$
165*8462SApril.Chin@Sun.COM	' INT
166*8462SApril.Chin@Sun.COM	;;
167*8462SApril.Chin@Sun.COMesac
168*8462SApril.Chin@Sun.COMcase $1 in
169*8462SApril.Chin@Sun.COM*v*)	echo 2-main ;;
170*8462SApril.Chin@Sun.COMesac
171*8462SApril.Chin@Sun.COMcase $1 in
172*8462SApril.Chin@Sun.COM*d*)	tst-3 $1 $2; status=$? ;;
173*8462SApril.Chin@Sun.COM*)	$2 -c "tst-3 $1 $2"; status=$? ;;
174*8462SApril.Chin@Sun.COMesac
175*8462SApril.Chin@Sun.COMprintf '2-%04d\n' $status
176*8462SApril.Chin@Sun.COM!
177*8462SApril.Chin@Sun.COMcat > tst-3 <<'!'
178*8462SApril.Chin@Sun.COMcase $1 in
179*8462SApril.Chin@Sun.COM*x*)	trap '
180*8462SApril.Chin@Sun.COM		sleep 2
181*8462SApril.Chin@Sun.COM		echo 3-intr
182*8462SApril.Chin@Sun.COM		exit 0
183*8462SApril.Chin@Sun.COM	' INT
184*8462SApril.Chin@Sun.COM	;;
185*8462SApril.Chin@Sun.COM*)	trap '
186*8462SApril.Chin@Sun.COM		sleep 2
187*8462SApril.Chin@Sun.COM		echo 3-intr
188*8462SApril.Chin@Sun.COM		trap - INT
189*8462SApril.Chin@Sun.COM		kill -s INT $$
190*8462SApril.Chin@Sun.COM	' INT
191*8462SApril.Chin@Sun.COM	;;
192*8462SApril.Chin@Sun.COMesac
193*8462SApril.Chin@Sun.COMcase $1 in
194*8462SApril.Chin@Sun.COM*v*)	echo 3-main ;;
195*8462SApril.Chin@Sun.COMesac
196*8462SApril.Chin@Sun.COMsleep 5
197*8462SApril.Chin@Sun.COMprintf '3-%04d\n' $?
198*8462SApril.Chin@Sun.COM!
199*8462SApril.Chin@Sun.COMchmod +x tst tst-?
200*8462SApril.Chin@Sun.COM
201*8462SApril.Chin@Sun.COM# end standalone test generation
202*8462SApril.Chin@Sun.COM
203*8462SApril.Chin@Sun.COMexport PATH=$PATH:
204*8462SApril.Chin@Sun.COMtypeset -A expected
205*8462SApril.Chin@Sun.COMexpected[---]="3-intr"
206*8462SApril.Chin@Sun.COMexpected[--d]="3-intr"
207*8462SApril.Chin@Sun.COMexpected[-t-]="3-intr 2-intr 1-intr 1-0258"
208*8462SApril.Chin@Sun.COMexpected[-td]="3-intr 2-intr 1-intr 1-0258"
209*8462SApril.Chin@Sun.COMexpected[x--]="3-intr 2-intr 1-0000"
210*8462SApril.Chin@Sun.COMexpected[x-d]="3-intr 2-intr 1-0000"
211*8462SApril.Chin@Sun.COMexpected[xt-]="3-intr 2-intr 1-intr 1-0000"
212*8462SApril.Chin@Sun.COMexpected[xtd]="3-intr 2-intr 1-intr 1-0000"
213*8462SApril.Chin@Sun.COM
214*8462SApril.Chin@Sun.COMtst $SHELL > tst.got
215*8462SApril.Chin@Sun.COM
216*8462SApril.Chin@Sun.COMwhile	read ops out
217*8462SApril.Chin@Sun.COMdo	[[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
218*8462SApril.Chin@Sun.COMdone < tst.got
219*8462SApril.Chin@Sun.COM
220*8462SApril.Chin@Sun.COMfloat s=$SECONDS
221*8462SApril.Chin@Sun.COM[[ $($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'
222*8462SApril.Chin@Sun.COM(( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
223*8462SApril.Chin@Sun.COM((s = SECONDS))
224*8462SApril.Chin@Sun.COM[[ $($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'
225*8462SApril.Chin@Sun.COM(( SECONDS-s < 4 )) && err_exit 'parent completes early'
226*8462SApril.Chin@Sun.COMexit $((Errors))
227