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 -u$Error_fd -n "\t" 23*8462SApril.Chin@Sun.COM print -u$Error_fd -r ${Command}[$1]: "${@:2}" 24*8462SApril.Chin@Sun.COM (( Errors+=1 )) 25*8462SApril.Chin@Sun.COM} 26*8462SApril.Chin@Sun.COMalias err_exit='err_exit $LINENO' 27*8462SApril.Chin@Sun.COMCommand=${0##*/} 28*8462SApril.Chin@Sun.COMinteger Errors=0 Error_fd=2 29*8462SApril.Chin@Sun.COM 30*8462SApril.Chin@Sun.COMz=() 31*8462SApril.Chin@Sun.COMz.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi) 32*8462SApril.Chin@Sun.COMz.bar[0]=hello 33*8462SApril.Chin@Sun.COMz.bar[2]=world 34*8462SApril.Chin@Sun.COMz.bar[1]=(x=4 y=5) 35*8462SApril.Chin@Sun.COMval='( 36*8462SApril.Chin@Sun.COM typeset -a bar=( 37*8462SApril.Chin@Sun.COM [0]=hello 38*8462SApril.Chin@Sun.COM [2]=world 39*8462SApril.Chin@Sun.COM [1]=( 40*8462SApril.Chin@Sun.COM x=4 41*8462SApril.Chin@Sun.COM y=5 42*8462SApril.Chin@Sun.COM ) 43*8462SApril.Chin@Sun.COM ) 44*8462SApril.Chin@Sun.COM typeset -A foo=( 45*8462SApril.Chin@Sun.COM [one]=hello 46*8462SApril.Chin@Sun.COM [three]=hi 47*8462SApril.Chin@Sun.COM [two]=( 48*8462SApril.Chin@Sun.COM x=3 49*8462SApril.Chin@Sun.COM y=4 50*8462SApril.Chin@Sun.COM ) 51*8462SApril.Chin@Sun.COM ) 52*8462SApril.Chin@Sun.COM)' 53*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working' 54*8462SApril.Chin@Sun.COMz.bar[1]=yesyes 55*8462SApril.Chin@Sun.COM[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails' 56*8462SApril.Chin@Sun.COMz.bar[1]=(x=12 y=5) 57*8462SApril.Chin@Sun.COM[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails' 58*8462SApril.Chin@Sun.COMeval val="$z" 59*8462SApril.Chin@Sun.COM( 60*8462SApril.Chin@Sun.COM z.foo[three]=good 61*8462SApril.Chin@Sun.COM [[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working' 62*8462SApril.Chin@Sun.COM) 63*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment' 64*8462SApril.Chin@Sun.COMeval val="$z" 65*8462SApril.Chin@Sun.COM( 66*8462SApril.Chin@Sun.COMfalse 67*8462SApril.Chin@Sun.COM z.foo[two]=ok 68*8462SApril.Chin@Sun.COM [[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working' 69*8462SApril.Chin@Sun.COM z.bar[1]=yes 70*8462SApril.Chin@Sun.COM [[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working' 71*8462SApril.Chin@Sun.COM) 72*8462SApril.Chin@Sun.COM[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment' 73*8462SApril.Chin@Sun.COM 74*8462SApril.Chin@Sun.COMx=( 75*8462SApril.Chin@Sun.COM foo=( qqq=abc rrr=def) 76*8462SApril.Chin@Sun.COM bar=( zzz=no rst=fed) 77*8462SApril.Chin@Sun.COM) 78*8462SApril.Chin@Sun.COMeval val="$x" 79*8462SApril.Chin@Sun.COM( 80*8462SApril.Chin@Sun.COM unset x.foo 81*8462SApril.Chin@Sun.COM [[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset' 82*8462SApril.Chin@Sun.COM x.foo=good 83*8462SApril.Chin@Sun.COM [[ ${x.foo} == good ]] || err_exit 'x.foo should be good' 84*8462SApril.Chin@Sun.COM) 85*8462SApril.Chin@Sun.COM[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves' 86*8462SApril.Chin@Sun.COMunset l 87*8462SApril.Chin@Sun.COM( 88*8462SApril.Chin@Sun.COM l=( a=1 b="BE" ) 89*8462SApril.Chin@Sun.COM) 90*8462SApril.Chin@Sun.COM[[ ${l+foo} != foo ]] || err_exit 'l should be unset' 91*8462SApril.Chin@Sun.COM 92*8462SApril.Chin@Sun.COMError_fd=9 93*8462SApril.Chin@Sun.COMeval "exec $Error_fd>&2 2>/dev/null" 94*8462SApril.Chin@Sun.COM 95*8462SApril.Chin@Sun.COMTEST_notfound=notfound 96*8462SApril.Chin@Sun.COMwhile whence $TEST_notfound >/dev/null 2>&1 97*8462SApril.Chin@Sun.COMdo TEST_notfound=notfound-$RANDOM 98*8462SApril.Chin@Sun.COMdone 99*8462SApril.Chin@Sun.COM 100*8462SApril.Chin@Sun.COMtmp=/tmp/kshsubsh$$ 101*8462SApril.Chin@Sun.COMtrap "rm -f $tmp" EXIT 102*8462SApril.Chin@Sun.COMinteger BS=1024 nb=64 ss=60 bs no 103*8462SApril.Chin@Sun.COMfor bs in $BS 1 104*8462SApril.Chin@Sun.COMdo $SHELL -c ' 105*8462SApril.Chin@Sun.COM { 106*8462SApril.Chin@Sun.COM sleep '$ss' 107*8462SApril.Chin@Sun.COM kill -KILL $$ 108*8462SApril.Chin@Sun.COM } & 109*8462SApril.Chin@Sun.COM set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs') 110*8462SApril.Chin@Sun.COM print ${#1} 111*8462SApril.Chin@Sun.COM kill $! 112*8462SApril.Chin@Sun.COM ' > $tmp 2>/dev/null 113*8462SApril.Chin@Sun.COM no=$(<$tmp) 114*8462SApril.Chin@Sun.COM (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}" 115*8462SApril.Chin@Sun.COMdone 116*8462SApril.Chin@Sun.COM# this time with redirection on the trailing command 117*8462SApril.Chin@Sun.COMfor bs in $BS 1 118*8462SApril.Chin@Sun.COMdo $SHELL -c ' 119*8462SApril.Chin@Sun.COM { 120*8462SApril.Chin@Sun.COM sleep 2 121*8462SApril.Chin@Sun.COM sleep '$ss' 122*8462SApril.Chin@Sun.COM kill -KILL $$ 123*8462SApril.Chin@Sun.COM } & 124*8462SApril.Chin@Sun.COM set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null) 125*8462SApril.Chin@Sun.COM print ${#1} 126*8462SApril.Chin@Sun.COM kill $! 127*8462SApril.Chin@Sun.COM ' > $tmp 2>/dev/null 128*8462SApril.Chin@Sun.COM no=$(<$tmp) 129*8462SApril.Chin@Sun.COM (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}" 130*8462SApril.Chin@Sun.COMdone 131*8462SApril.Chin@Sun.COM 132*8462SApril.Chin@Sun.COM# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io 133*8462SApril.Chin@Sun.COM 134*8462SApril.Chin@Sun.COMset -- \ 135*8462SApril.Chin@Sun.COM 'post-line print' \ 136*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; print 1); print' \ 137*8462SApril.Chin@Sun.COM 1 \ 138*8462SApril.Chin@Sun.COM 'pre-line print' \ 139*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; print); print 1' \ 140*8462SApril.Chin@Sun.COM $'\n1' \ 141*8462SApril.Chin@Sun.COM 'multiple pre-line print' \ 142*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \ 143*8462SApril.Chin@Sun.COM $'\n\n1' \ 144*8462SApril.Chin@Sun.COM 'multiple post-line print' \ 145*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \ 146*8462SApril.Chin@Sun.COM 1 \ 147*8462SApril.Chin@Sun.COM 'intermediate print' \ 148*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \ 149*8462SApril.Chin@Sun.COM $'1\n\n2' \ 150*8462SApril.Chin@Sun.COM 'simple variable' \ 151*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \ 152*8462SApril.Chin@Sun.COM 2 \ 153*8462SApril.Chin@Sun.COM 'compound variable' \ 154*8462SApril.Chin@Sun.COM '$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \ 155*8462SApril.Chin@Sun.COM $'(\n\ta=2\n\tb=BE\n)' \ 156*8462SApril.Chin@Sun.COM 157*8462SApril.Chin@Sun.COMexport TEST_fork TEST_unset 158*8462SApril.Chin@Sun.COM 159*8462SApril.Chin@Sun.COMwhile (( $# >= 3 )) 160*8462SApril.Chin@Sun.COMdo txt=$1 161*8462SApril.Chin@Sun.COM cmd=$2 162*8462SApril.Chin@Sun.COM exp=$3 163*8462SApril.Chin@Sun.COM shift 3 164*8462SApril.Chin@Sun.COM for TEST_unset in '' 'unset var' 165*8462SApril.Chin@Sun.COM do for TEST_fork in '' 'ulimit -c 0' 166*8462SApril.Chin@Sun.COM do for TEST_shell in "eval" "$SHELL -c" 167*8462SApril.Chin@Sun.COM do if ! got=$($TEST_shell "$cmd") 168*8462SApril.Chin@Sun.COM then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed" 169*8462SApril.Chin@Sun.COM elif [[ "$got" != "$exp" ]] 170*8462SApril.Chin@Sun.COM then EXP=$(printf %q "$exp") 171*8462SApril.Chin@Sun.COM GOT=$(printf %q "$got") 172*8462SApril.Chin@Sun.COM err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT" 173*8462SApril.Chin@Sun.COM fi 174*8462SApril.Chin@Sun.COM done 175*8462SApril.Chin@Sun.COM done 176*8462SApril.Chin@Sun.COM done 177*8462SApril.Chin@Sun.COMdone 178*8462SApril.Chin@Sun.COM 179*8462SApril.Chin@Sun.COMr=$( ($SHELL -c ' 180*8462SApril.Chin@Sun.COM { 181*8462SApril.Chin@Sun.COM sleep 32 182*8462SApril.Chin@Sun.COM kill -KILL $$ 183*8462SApril.Chin@Sun.COM } & 184*8462SApril.Chin@Sun.COM for v in $(set | sed "s/=.*//") 185*8462SApril.Chin@Sun.COM do command unset $v 186*8462SApril.Chin@Sun.COM done 187*8462SApril.Chin@Sun.COM typeset -Z5 I 188*8462SApril.Chin@Sun.COM for ((I = 0; I < 1024; I++)) 189*8462SApril.Chin@Sun.COM do eval A$I=1234567890 190*8462SApril.Chin@Sun.COM done 191*8462SApril.Chin@Sun.COM a=$(set 2>&1) 192*8462SApril.Chin@Sun.COM print ok 193*8462SApril.Chin@Sun.COM kill -KILL $! 194*8462SApril.Chin@Sun.COM') 2>/dev/null) 195*8462SApril.Chin@Sun.COM[[ $r == ok ]] || err_exit "large subshell command substitution hangs" 196*8462SApril.Chin@Sun.COM 197*8462SApril.Chin@Sun.COMfor TEST_command in '' $TEST_notfound 198*8462SApril.Chin@Sun.COMdo for TEST_exec in '' 'exec' 199*8462SApril.Chin@Sun.COM do for TEST_fork in '' 'ulimit -c 0;' 200*8462SApril.Chin@Sun.COM do for TEST_redirect in '' '>/dev/null' 201*8462SApril.Chin@Sun.COM do for TEST_substitute in '' ': $' 202*8462SApril.Chin@Sun.COM do 203*8462SApril.Chin@Sun.COM 204*8462SApril.Chin@Sun.COM TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)" 205*8462SApril.Chin@Sun.COM [[ $TEST_test == '('*([[:space:]])')' ]] && continue 206*8462SApril.Chin@Sun.COM r=$($SHELL -c ' 207*8462SApril.Chin@Sun.COM { 208*8462SApril.Chin@Sun.COM sleep 2 209*8462SApril.Chin@Sun.COM kill -KILL $$ 210*8462SApril.Chin@Sun.COM } & 211*8462SApril.Chin@Sun.COM '"$TEST_test"' 212*8462SApril.Chin@Sun.COM kill $! 213*8462SApril.Chin@Sun.COM print ok 214*8462SApril.Chin@Sun.COM ') 215*8462SApril.Chin@Sun.COM [[ $r == ok ]] || err_exit "shell hangs on $TEST_test" 216*8462SApril.Chin@Sun.COM 217*8462SApril.Chin@Sun.COM done 218*8462SApril.Chin@Sun.COM done 219*8462SApril.Chin@Sun.COM done 220*8462SApril.Chin@Sun.COM done 221*8462SApril.Chin@Sun.COMdone 222*8462SApril.Chin@Sun.COM 223*8462SApril.Chin@Sun.COMexit $Errors 224