1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2008 AT&T Intellectual Property # 5# and is licensed under the # 6# Common Public License, Version 1.0 # 7# by AT&T Intellectual Property # 8# # 9# A copy of the License is available at # 10# http://www.opensource.org/licenses/cpl1.0.txt # 11# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 12# # 13# Information and Software Systems Research # 14# AT&T Research # 15# Florham Park NJ # 16# # 17# David Korn <dgk@research.att.com> # 18# # 19######################################################################## 20function err_exit 21{ 22 print -u2 -n "\t" 23 print -u2 -r ${Command}[$1]: "${@:2}" 24 let Errors+=1 25} 26alias err_exit='err_exit $LINENO' 27 28# test basic file operations like redirection, pipes, file expansion 29Command=${0##*/} 30integer Errors=0 31set -- \ 32 go+r 0000 \ 33 go-r 0044 \ 34 ug=r 0330 \ 35 go+w 0000 \ 36 go-w 0022 \ 37 ug=w 0550 \ 38 go+x 0000 \ 39 go-x 0011 \ 40 ug=x 0660 \ 41 go-rx 0055 \ 42 uo-wx 0303 \ 43 ug-rw 0660 \ 44 o= 0007 45while (( $# >= 2 )) 46do umask 0 47 umask $1 48 g=$(umask) 49 [[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g" 50 shift 2 51done 52umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed" 53if [[ $(umask -S) != u=rwx,g=rx,o=rx ]] 54then err_exit 'umask -S incorrect' 55fi 56mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" 57trap "cd /; rm -rf /tmp/ksh$$" EXIT 58pwd=$PWD 59[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL 60cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" 61um=$(umask -S) 62( umask 0777; > foobar ) 63rm -f foobar 64> foobar 65[[ -r foobar ]] || err_exit 'umask not being restored after subshell' 66umask "$um" 67rm -f foobar 68# optimizer bug test 69> foobar 70for i in 1 2 71do print foobar* 72 rm -f foobar 73done > out$$ 74if [[ "$(<out$$)" != "foobar"$'\n'"foobar*" ]] 75then print -u2 "optimizer bug with file expansion" 76fi 77rm -f out$$ foobar 78mkdir dir 79if [[ $(print */) != dir/ ]] 80then err_exit 'file expansion with trailing / not working' 81fi 82if [[ $(print *) != dir ]] 83then err_exit 'file expansion with single file not working' 84fi 85print hi > .foo 86if [[ $(print *) != dir ]] 87then err_exit 'file expansion leading . not working' 88fi 89date > dat1 || err_exit "date > dat1 failed" 90test -r dat1 || err_exit "dat1 is not readable" 91x=dat1 92cat <$x > dat2 || err_exit "cat < $x > dat2 failed" 93cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed" 94cat > dat4 <<! 95$(date) 96! 97cat dat1 dat2 | cat | cat | cat > dat5 & 98wait $! 99set -- dat* 100if (( $# != 5 )) 101then err_exit "dat* matches only $# files" 102fi 103if (command > foo\\abc) 2> /dev/null 104then set -- foo* 105 if [[ $1 != 'foo\abc' ]] 106 then err_exit 'foo* does not match foo\abc' 107 fi 108fi 109if ( : > TT* && : > TTfoo ) 2>/dev/null 110then set -- TT* 111 if (( $# < 2 )) 112 then err_exit 'TT* not expanding when file TT* exists' 113 fi 114fi 115cd ~- || err_exit "cd back failed" 116cat > /tmp/ksh$$/script <<- ! 117 #! $SHELL 118 print -r -- \$0 119! 120chmod 755 /tmp/ksh$$/script 121if [[ $(/tmp/ksh$$/script) != "/tmp/ksh$$/script" ]] 122then err_exit '$0 not correct for #! script' 123fi 124rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" 125bar=foo 126eval foo=\$bar 127if [[ $foo != foo ]] 128then err_exit 'eval foo=\$bar not working' 129fi 130bar='foo=foo\ bar' 131eval $bar 132if [[ $foo != 'foo bar' ]] 133then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working' 134fi 135cd /tmp 136cd ../../tmp || err_exit "cd ../../tmp failed" 137if [[ $PWD != /tmp ]] 138then err_exit 'cd ../../tmp is not /tmp' 139fi 140( sleep 2; cat <<! 141foobar 142! 143) | cat > /tmp/foobar$$ & 144wait $! 145foobar=$( < /tmp/foobar$$) 146if [[ $foobar != foobar ]] 147then err_exit "$foobar is not foobar" 148fi 149{ 150 print foo 151 /bin/echo bar 152 print bam 153} > /tmp/foobar$$ 154if [[ $( < /tmp/foobar$$) != $'foo\nbar\nbam' ]] 155then err_exit "Output file pointer not shared correctly." 156fi 157cat > /tmp/foobar$$ <<\! 158 print foo 159 /bin/echo bar 160 print bam 161! 162chmod +x /tmp/foobar$$ 163if [[ $(/tmp/foobar$$) != $'foo\nbar\nbam' ]] 164then err_exit "Script not working." 165fi 166if [[ $(/tmp/foobar$$ | /bin/cat) != $'foo\nbar\nbam' ]] 167then err_exit "Script | cat not working." 168fi 169if [[ $( /tmp/foobar$$) != $'foo\nbar\nbam' ]] 170then err_exit "Output file pointer not shared correctly." 171fi 172rm -f /tmp/foobar$$ 173x=$( (print foo) ; (print bar) ) 174if [[ $x != $'foo\nbar' ]] 175then err_exit " ( (print foo);(print bar ) failed" 176fi 177x=$( (/bin/echo foo) ; (print bar) ) 178if [[ $x != $'foo\nbar' ]] 179then err_exit " ( (/bin/echo);(print bar ) failed" 180fi 181x=$( (/bin/echo foo) ; (/bin/echo bar) ) 182if [[ $x != $'foo\nbar' ]] 183then err_exit " ( (/bin/echo);(/bin/echo bar ) failed" 184fi 185cat > /tmp/ksh$$ <<\! 186if [[ -p /dev/fd/0 ]] 187then builtin cat 188 cat - > /dev/null 189 [[ -p /dev/fd/0 ]] && print ok 190else print no 191fi 192! 193chmod +x /tmp/ksh$$ 194case $( (print) | /tmp/ksh$$;:) in 195ok) ;; 196no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;; 197*) err_exit "builtin replaces standard input pipe" ;; 198esac 199print 'print $0' > /tmp/ksh$$ 200print ". /tmp/ksh$$" > /tmp/ksh$$x 201chmod +x /tmp/ksh$$x 202if [[ $(/tmp/ksh$$x) != /tmp/ksh$$x ]] 203then err_exit '$0 not correct for . script' 204fi 205rm -r /tmp/ksh$$ /tmp/ksh$$x 206mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" 207cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" 208print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e 209chmod 755 a b c d e 210x=$(./a) 211if [[ $x != "hello there" ]] 212then err_exit "nested scripts failed" 213fi 214x=$( (./a) | cat) 215if [[ $x != "hello there" ]] 216then err_exit "scripts in subshells fail" 217fi 218cd ~- || err_exit "cd back failed" 219rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" 220x=$( (/bin/echo foo) 2> /dev/null ) 221if [[ $x != foo ]] 222then err_exit "subshell in command substitution fails" 223fi 224exec 1>&- 225x=$(print hello) 226if [[ $x != hello ]] 227then err_exit "command subsitution with stdout closed failed" 228fi 229cd $pwd 230x=$(cat <<\! | $SHELL 231/bin/echo | /bin/cat 232/bin/echo hello 233! 234) 235if [[ $x != $'\n'hello ]] 236then err_exit "$SHELL not working when standard input is a pipe" 237fi 238x=$( (/bin/echo hello) 2> /dev/null ) 239if [[ $x != hello ]] 240then err_exit "subshell in command substitution with 1 closed fails" 241fi 242cat > /tmp/ksh$$ <<- \! 243read line 2> /dev/null 244print done 245! 246if [[ $($SHELL /tmp/ksh$$ <&-) != done ]] 247then err_exit "executing script with 0 closed fails" 248fi 249trap '' INT 250cat > /tmp/ksh$$ <<- \! 251trap 'print bad' INT 252kill -s INT $$ 253print good 254! 255chmod +x /tmp/ksh$$ 256if [[ $($SHELL /tmp/ksh$$) != good ]] 257then err_exit "traps ignored by parent not ignored" 258fi 259trap - INT 260cat > /tmp/ksh$$ <<- \! 261read line 262/bin/cat 263! 264if [[ $($SHELL /tmp/ksh$$ <<! 265one 266two 267! 268) != two ]] 269then err_exit "standard input not positioned correctly" 270fi 271word=$(print $'foo\nbar' | { read line; /bin/cat;}) 272if [[ $word != bar ]] 273then err_exit "pipe to { read line; /bin/cat;} not working" 274fi 275word=$(print $'foo\nbar' | ( read line; /bin/cat) ) 276if [[ $word != bar ]] 277then err_exit "pipe to ( read line; /bin/cat) not working" 278fi 279if [[ $(print x{a,b}y) != 'xay xby' ]] 280then err_exit 'brace expansion not working' 281fi 282if [[ $(for i in foo bar 283 do ( tgz=$(print $i) 284 print $tgz) 285 done) != $'foo\nbar' ]] 286then err_exit 'for loop subshell optimizer bug' 287fi 288unset a1 289optbug() 290{ 291 set -A a1 foo bar bam 292 integer i 293 for ((i=0; i < 3; i++)) 294 do 295 (( ${#a1[@]} < 2 )) && return 0 296 set -- "${a1[@]}" 297 shift 298 set -A a1 -- "$@" 299 done 300 return 1 301} 302optbug || err_exit 'array size optimzation bug' 303wait # not running --pipefail which would interfere with subsequent tests 304: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect) 305sleep 20 & 306pids=$! 307if [[ $(jobs -p) != $! ]] 308then err_exit 'jobs -p not reporting a background job' 309fi 310sleep 20 & 311pids="$pids $!" 312foo() 313{ 314 set -- $(jobs -p) 315 (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected" 316} 317foo 318kill $pids 319 320[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working' 321[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored' 322[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug' 323command exec 3<> /dev/null 324if cat /dev/fd/3 >/dev/null 2>&1 325then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working' 326 [[ $($SHELL -c 'print $(cat <(print foo) )' 2> /dev/null) == foo ]] || err_exit 'process substitution in subshell not working' 327 [[ $($SHELL -c $'tee >(grep \'1$\' > /tmp/ksh'$$'x) > /dev/null <<- \!!! 328 line0 329 line1 330 line2 331 !!! 332 wait 333 cat /tmp/ksh'$$x 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails' 334 > /tmp/ksh$$x 335 [[ $($SHELL -c $' 336 for i in 1 337 do tee >(grep \'1$\' > /tmp/ksh'$$'x) > /dev/null <<- \!!! 338 line0 339 line1 340 line2 341 !!! 342 done 343 wait 344 cat /tmp/ksh'$$x 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop' 345 [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] || 346 err_exit 'process substitution of compound commands not working' 347fi 348[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted' 349print cat > /tmp/ksh$$x 350chmod +x /tmp/ksh$$x 351[[ $($SHELL -c "print foo | /tmp/ksh$$x ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails' 352[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure' 353[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure' 354exec 3<&- 355if [[ -d /dev/fd && -w /dev/fd/3 ]] 356then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop" 357 $SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop" 358fi 359exec 3> /dev/null 360print 'print foo "$@"' > /tmp/ksh$$x 361[[ $( print "(/tmp/ksh$$x bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails' 362print "#! $SHELL" > /tmp/ksh$$x 363print 'print -- $0' >> /tmp/ksh$$x 364chmod +x /tmp/ksh$$x 365[[ $(/tmp/ksh$$x) == /tmp/ksh$$x ]] || err_exit "\$0 is $0 instead of /tmp/ksh$$x" 366cat > /tmp/ksh$$x <<- \EOF 367 myfilter() { x=$(print ok | cat); print -r -- $SECONDS;} 368 set -o pipefail 369 sleep 3 | myfilter 370EOF 371(( $($SHELL /tmp/ksh$$x) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang' 372rm -f /tmp/ksh$$x 373exec 3<&- 374( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset' 375$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported' 376$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported' 377 x=${ 378 print hello 379 } 380 [[ $x == hello ]] 381EOF 382$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported ' 383 y=bye 384 x=${ 385 y=hello 386 print hello 387 } 388 [[ $y == $x ]] 389EOF 390$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported' 391 x=${ 392 print ${ print hello;} $(print world) 393 } 394 [[ $x == 'hello world' ]] 395EOF 396$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }' 397 x=${ { print -n } ; print -n hello ; } ; print ' world' } 398 [[ $x == '}hello world' ]] 399EOF 400$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working' 401 f() 402 { 403 print foo 404 } 405 [[ ${ f;}bar == foobar ]] 406EOF 407 408unset foo 409function foo 410{ 411 print bar 412} 413[[ ${foo} == bar ]] || err_exit '${foo} is not command substitution when foo unset' 414[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset' 415[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset' 416[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]' 417[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]' 418unset foo 419foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false' 420expected=foreback 421got=$(print -n fore;(sleep 2;print back)&) 422[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'" 423 424for false in false $(whence -p false) 425do x=$($false) && err_exit "x=\$($false) should fail" 426 $($false) && err_exit "\$($false) should fail" 427 $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail" 428done 429[[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved' 430exit $((Errors)) 431